diff mbox

Fix wrong code with complex nested functions tree

Message ID 201008312308.38661.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Aug. 31, 2010, 9:08 p.m. UTC
The new iterative algorithm that computes the need for static chains in nested 
functions trees has a flaw: it only detects changes of static chain setting 
in the function it has just processed.  So if a child function is nested in 
its parent and already requires a static chain, the parent is nested in the 
root function and doesn't, and the child function calls a sibling of its 
parent that does, the parent won't get the static chain it eventually needs 
because the setting is toggled from within the child function.

Fixed by computing the sum of the static chains in each nest and iterating 
until after it doesn't change.  Tested on x86-64-suse-linux, applied on the 
mainline and 4.5 branch as obvious.


2010-08-31  Eric Botcazou  <ebotcazou@adacore.com>

	* tree-nested.c (convert_all_function_calls): Iterate until after the
	sum of static chains in the nest doesn't change.


2010-08-31  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.dg/nested-func-8.c: New test.
diff mbox

Patch

Index: tree-nested.c
===================================================================
--- tree-nested.c	(revision 163659)
+++ tree-nested.c	(working copy)
@@ -2070,9 +2070,8 @@  convert_gimple_call (gimple_stmt_iterato
 static void
 convert_all_function_calls (struct nesting_info *root)
 {
+  unsigned int chain_count = 0, old_chain_count, iter_count;
   struct nesting_info *n;
-  int iter_count;
-  bool any_changed;
 
   /* First, optimistically clear static_chain for all decls that haven't
      used the static chain already for variable access.  */
@@ -2088,6 +2087,7 @@  convert_all_function_calls (struct nesti
 	}
       else
 	DECL_STATIC_CHAIN (decl) = 1;
+      chain_count += DECL_STATIC_CHAIN (decl);
     }
 
   /* Walk the functions and perform transformations.  Note that these
@@ -2100,7 +2100,8 @@  convert_all_function_calls (struct nesti
   iter_count = 0;
   do
     {
-      any_changed = false;
+      old_chain_count = chain_count;
+      chain_count = 0;
       iter_count++;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2109,22 +2110,16 @@  convert_all_function_calls (struct nesti
       FOR_EACH_NEST_INFO (n, root)
 	{
 	  tree decl = n->context;
-	  bool old_static_chain = DECL_STATIC_CHAIN (decl);
-
 	  walk_function (convert_tramp_reference_stmt,
 			 convert_tramp_reference_op, n);
 	  walk_function (convert_gimple_call, NULL, n);
-
-	  /* If a call to another function created the use of a chain
-	     within this function, we'll have to continue iteration.  */
-	  if (!old_static_chain && DECL_STATIC_CHAIN (decl))
-	    any_changed = true;
+	  chain_count += DECL_STATIC_CHAIN (decl);
 	}
     }
-  while (any_changed);
+  while (chain_count != old_chain_count);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, "convert_all_function_calls iterations: %d\n\n",
+    fprintf (dump_file, "convert_all_function_calls iterations: %u\n\n",
 	     iter_count);
 }