Avoid infinite recursion on flattening

Jan Hubicka jh@suse.cz
Sun Jan 21 01:51:00 GMT 2007


Hi,
this patch avoid infinite recursion on flattening.  I somehow assumed we
are safe with recursive_inlining_p but it tests only self recursion
(this has changed from early implementations of inliner)

This problem caused C++ benchmarks to fail today, I am testing the patch
and will commit it tomorrow if it passes to not disturb them once again.

Honza

void
do_something(int);
void t();
void
q()
{
  do_something(5);
  t();
  do_something(4);
}
void
t()
{
  do_something(3);
  t();
  do_something(2);
}
 __attribute__ ((flatten))
void
m()
{
  do_something(1);
  t();
}
main()
{
  m();
}
	* ipa-iline.c (cgraph_decide_inlining_incrementally): Better debug
	output; avoid recursive inlining.
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 120999)
+++ ipa-inline.c	(working copy)
@@ -625,6 +625,8 @@ static void
@@ -1165,34 +1167,66 @@ cgraph_decide_inlining_incrementally (st
 
   /* First of all look for always inline functions.  */
   for (e = node->callees; e; e = e->next_callee)
-    if ((e->callee->local.disregard_inline_limits
-	 || (mode == INLINE_ALL && e->callee->local.inlinable))
-	&& e->inline_failed
-	&& (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl))
-	    == gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl)))
-        && !cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)
-	/* ??? It is possible that renaming variable removed the function body
-	   in duplicate_decls. See gcc.c-torture/compile/20011119-2.c  */
-	&& (DECL_SAVED_TREE (e->callee->decl) || e->callee->inline_decl))
-      {
-        if (dump_file)
-	  {
-	    fprintf (dump_file, "  Inlining always_inline %s",
-		     cgraph_node_name (e->callee));
-	    fprintf (dump_file, " into %s\n", cgraph_node_name (node));
-	  }
-	cgraph_mark_inline (e);
-	/* In order to fully inline always_inline functions at -O0, we need to
-	   recurse here, since the inlined functions might not be processed by
-	   incremental inlining at all yet.  
-
-	   Also flattening needs to be done recursively.  */
-	
-        if (!flag_unit_at_a_time || mode == INLINE_ALL)
-          cgraph_decide_inlining_incrementally (e->callee, mode);
-	
-	inlined = true;
-      }
+    {
+      if (dump_file && e->callee->local.inlinable
+	  && (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl))
+	      != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl))))
+	{
+	  fprintf (dump_file, "  Ignoring %s: SSA form not computed yet.\n",
+		   cgraph_node_name (e->callee));
+	}
+      if ((e->callee->local.disregard_inline_limits
+	   || (mode == INLINE_ALL && e->callee->local.inlinable))
+	  && e->inline_failed
+	  && (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl))
+	      == gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl)))
+	  && !cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)
+	  /* ??? It is possible that renaming variable removed the function body
+	     in duplicate_decls. See gcc.c-torture/compile/20011119-2.c  */
+	  && (DECL_SAVED_TREE (e->callee->decl) || e->callee->inline_decl))
+	{
+	  if (mode == INLINE_ALL)
+	    {
+	      struct cgraph_node *n;
+
+	      /* Veify that we are not inlining function into itself to prevent
+		 infinite loop.  */
+	      for (n = node; n->global.inlined_to ; n = node->callers->caller)
+		if (n->decl == e->callee->decl)
+		  break;
+	      if (n->global.inlined_to)
+		{
+		  e->inline_failed = (e->callee->local.disregard_inline_limits
+				     ? N_("recursive inlining") : "");
+		  if (dump_file)
+		    {
+		      fprintf (dump_file, "  Skipping recursive inlining at %s",
+			       cgraph_node_name (e->callee));
+		      fprintf (dump_file, " into %s\n", cgraph_node_name (node));
+		    }
+		  continue;
+		}
+	     }
+	  if (dump_file)
+	    {
+	      fprintf (dump_file, "  Inlining always_inline %s",
+		       cgraph_node_name (e->callee));
+	      fprintf (dump_file, " into %s\n", cgraph_node_name (node));
+	    }
+	  cgraph_mark_inline (e);
+	  
+	  /* In order to fully inline always_inline functions at -O0, we need to
+	     recurse here, since the inlined functions might not be processed by
+	     incremental inlining at all yet.  
+
+	     Also flattening needs to be done recursively.  */
+	  
+	  if (!flag_unit_at_a_time || mode == INLINE_ALL)
+	    cgraph_decide_inlining_incrementally (e->callee, mode);
+	  
+	  inlined = true;
+	}
+    }
 
   /* Now do the automatic inlining.  */
   if (!flag_really_no_inline && mode != INLINE_ALL)



More information about the Gcc-patches mailing list