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