Commit 796bda22 by Jan Hubicka Committed by Jan Hubicka

invoke.texi (max-early-inliner-iterations): New flag.


	* doc/invoke.texi (max-early-inliner-iterations): New flag.
	* ipa-inline.c (enum inlining_mode): New INLINE_SIZE_NORECURSIVE.
	(try_inline): Fix return value.
	(cgraph_decide_inlining_incrementally): Honor new value.
	(cgraph_early_inlining): Handle indirect inlining.
	* params.def (PARAM_EARLY_INLINER_MAX_ITERATIONS): New.

	* testsuite/gcc.dg/tree-ssa/inline-3.c: New testcase

From-SVN: r147587
parent d88e5c37
2009-05-15 Jan Hubicka <jh@suse.cz> 2009-05-15 Jan Hubicka <jh@suse.cz>
* doc/invoke.texi (max-early-inliner-iterations): New flag.
* ipa-inline.c (enum inlining_mode): New INLINE_SIZE_NORECURSIVE.
(try_inline): Fix return value.
(cgraph_decide_inlining_incrementally): Honor new value.
(cgraph_early_inlining): Handle indirect inlining.
* params.def (PARAM_EARLY_INLINER_MAX_ITERATIONS): New.
2009-05-15 Jan Hubicka <jh@suse.cz>
* cgraph.h (struct cgraph_node): Add finalized_by_frotnend flag. * cgraph.h (struct cgraph_node): Add finalized_by_frotnend flag.
* cgraphunit.c (cgraph_finalize_function): Set it. * cgraphunit.c (cgraph_finalize_function): Set it.
(cgraph_expand_function): Use it. (cgraph_expand_function): Use it.
......
...@@ -7485,6 +7485,12 @@ whose probability exceeds given threshold (in percents). The default value is ...@@ -7485,6 +7485,12 @@ whose probability exceeds given threshold (in percents). The default value is
Specify growth that early inliner can make. In effect it increases amount of Specify growth that early inliner can make. In effect it increases amount of
inlining for code having large abstraction penalty. The default value is 12. inlining for code having large abstraction penalty. The default value is 12.
@item max-early-inliner-iterations
@itemx max-early-inliner-iterations
Limit of iterations of early inliner. This basically bounds number of nested
indirect calls early inliner can resolve. Deeper chains are still handled by
late inlining.
@item min-vect-loop-bound @item min-vect-loop-bound
The minimum number of iterations under which a loop will not get vectorized The minimum number of iterations under which a loop will not get vectorized
when @option{-ftree-vectorize} is used. The number of iterations after when @option{-ftree-vectorize} is used. The number of iterations after
......
...@@ -152,6 +152,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -152,6 +152,7 @@ along with GCC; see the file COPYING3. If not see
enum inlining_mode { enum inlining_mode {
INLINE_NONE = 0, INLINE_NONE = 0,
INLINE_ALWAYS_INLINE, INLINE_ALWAYS_INLINE,
INLINE_SIZE_NORECURSIVE,
INLINE_SIZE, INLINE_SIZE,
INLINE_ALL INLINE_ALL
}; };
...@@ -1269,6 +1270,7 @@ try_inline (struct cgraph_edge *e, enum inlining_mode mode, int depth) ...@@ -1269,6 +1270,7 @@ try_inline (struct cgraph_edge *e, enum inlining_mode mode, int depth)
struct cgraph_node *callee = e->callee; struct cgraph_node *callee = e->callee;
enum inlining_mode callee_mode = (enum inlining_mode) (size_t) callee->aux; enum inlining_mode callee_mode = (enum inlining_mode) (size_t) callee->aux;
bool always_inline = e->callee->local.disregard_inline_limits; bool always_inline = e->callee->local.disregard_inline_limits;
bool inlined = false;
/* We've hit cycle? */ /* We've hit cycle? */
if (callee_mode) if (callee_mode)
...@@ -1323,9 +1325,10 @@ try_inline (struct cgraph_edge *e, enum inlining_mode mode, int depth) ...@@ -1323,9 +1325,10 @@ try_inline (struct cgraph_edge *e, enum inlining_mode mode, int depth)
if (mode == INLINE_ALL || always_inline) if (mode == INLINE_ALL || always_inline)
cgraph_decide_inlining_incrementally (e->callee, mode, depth + 1); cgraph_decide_inlining_incrementally (e->callee, mode, depth + 1);
inlined = true;
} }
callee->aux = (void *)(size_t) callee_mode; callee->aux = (void *)(size_t) callee_mode;
return true; return inlined;
} }
/* Decide on the inlining. We do so in the topological order to avoid /* Decide on the inlining. We do so in the topological order to avoid
...@@ -1348,7 +1351,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node, ...@@ -1348,7 +1351,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
old_mode = (enum inlining_mode) (size_t)node->aux; old_mode = (enum inlining_mode) (size_t)node->aux;
if (mode != INLINE_ALWAYS_INLINE if (mode != INLINE_ALWAYS_INLINE && mode != INLINE_SIZE_NORECURSIVE
&& lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL) && lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL)
{ {
if (dump_file) if (dump_file)
...@@ -1362,69 +1365,70 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node, ...@@ -1362,69 +1365,70 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
node->aux = (void *)(size_t) mode; node->aux = (void *)(size_t) mode;
/* First of all look for always inline functions. */ /* First of all look for always inline functions. */
for (e = node->callees; e; e = e->next_callee) if (mode != INLINE_SIZE_NORECURSIVE)
{ for (e = node->callees; e; e = e->next_callee)
if (!e->callee->local.disregard_inline_limits {
&& (mode != INLINE_ALL || !e->callee->local.inlinable)) if (!e->callee->local.disregard_inline_limits
continue; && (mode != INLINE_ALL || !e->callee->local.inlinable))
if (gimple_call_cannot_inline_p (e->call_stmt))
continue;
/* When the edge is already inlined, we just need to recurse into
it in order to fully flatten the leaves. */
if (!e->inline_failed && mode == INLINE_ALL)
{
inlined |= try_inline (e, mode, depth);
continue;
}
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
"Considering to always inline inline candidate %s.\n",
cgraph_node_name (e->callee));
}
if (cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed))
{
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file, "Not inlining: recursive call.\n");
}
continue;
}
if (!tree_can_inline_p (node->decl, e->callee->decl))
{
gimple_call_set_cannot_inline (e->call_stmt, true);
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
"Not inlining: Target specific option mismatch.\n");
}
continue;
}
if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl))
!= gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl)))
{
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file, "Not inlining: SSA form does not match.\n");
}
continue; continue;
} if (gimple_call_cannot_inline_p (e->call_stmt))
if (!e->callee->analyzed && !e->callee->inline_decl)
{
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
"Not inlining: Function body no longer available.\n");
}
continue; continue;
} /* When the edge is already inlined, we just need to recurse into
inlined |= try_inline (e, mode, depth); it in order to fully flatten the leaves. */
} if (!e->inline_failed && mode == INLINE_ALL)
{
inlined |= try_inline (e, mode, depth);
continue;
}
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
"Considering to always inline inline candidate %s.\n",
cgraph_node_name (e->callee));
}
if (cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed))
{
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file, "Not inlining: recursive call.\n");
}
continue;
}
if (!tree_can_inline_p (node->decl, e->callee->decl))
{
gimple_call_set_cannot_inline (e->call_stmt, true);
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
"Not inlining: Target specific option mismatch.\n");
}
continue;
}
if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl))
!= gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->callee->decl)))
{
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file, "Not inlining: SSA form does not match.\n");
}
continue;
}
if (!e->callee->analyzed && !e->callee->inline_decl)
{
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
"Not inlining: Function body no longer available.\n");
}
continue;
}
inlined |= try_inline (e, mode, depth);
}
/* Now do the automatic inlining. */ /* Now do the automatic inlining. */
if (mode != INLINE_ALL && mode != INLINE_ALWAYS_INLINE) if (mode != INLINE_ALL && mode != INLINE_ALWAYS_INLINE)
...@@ -1459,7 +1463,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node, ...@@ -1459,7 +1463,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
/* When the function body would grow and inlining the function won't /* When the function body would grow and inlining the function won't
eliminate the need for offline copy of the function, don't inline. eliminate the need for offline copy of the function, don't inline.
*/ */
if ((mode == INLINE_SIZE if (((mode == INLINE_SIZE || mode == INLINE_SIZE_NORECURSIVE)
|| (!flag_inline_functions || (!flag_inline_functions
&& !DECL_DECLARED_INLINE_P (e->callee->decl))) && !DECL_DECLARED_INLINE_P (e->callee->decl)))
&& (cgraph_estimate_size_after_inlining (1, e->caller, e->callee) && (cgraph_estimate_size_after_inlining (1, e->caller, e->callee)
...@@ -1531,15 +1535,22 @@ cgraph_early_inlining (void) ...@@ -1531,15 +1535,22 @@ cgraph_early_inlining (void)
{ {
struct cgraph_node *node = cgraph_node (current_function_decl); struct cgraph_node *node = cgraph_node (current_function_decl);
unsigned int todo = 0; unsigned int todo = 0;
int iterations = 0;
if (sorrycount || errorcount) if (sorrycount || errorcount)
return 0; return 0;
if (cgraph_decide_inlining_incrementally (node, INLINE_SIZE, 0)) while (cgraph_decide_inlining_incrementally (node,
iterations
? INLINE_SIZE_NORECURSIVE : INLINE_SIZE, 0)
&& iterations < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS))
{ {
timevar_push (TV_INTEGRATION); timevar_push (TV_INTEGRATION);
todo = optimize_inline_calls (current_function_decl); todo |= optimize_inline_calls (current_function_decl);
iterations++;
timevar_pop (TV_INTEGRATION); timevar_pop (TV_INTEGRATION);
} }
if (dump_file)
fprintf (dump_file, "Iterations: %i\n", iterations);
cfun->always_inline_functions_inlined = true; cfun->always_inline_functions_inlined = true;
return todo; return todo;
} }
......
...@@ -139,6 +139,14 @@ DEFPARAM (PARAM_MIN_INLINE_RECURSIVE_PROBABILITY, ...@@ -139,6 +139,14 @@ DEFPARAM (PARAM_MIN_INLINE_RECURSIVE_PROBABILITY,
"Inline recursively only when the probability of call being executed exceeds the parameter", "Inline recursively only when the probability of call being executed exceeds the parameter",
10, 0, 0) 10, 0, 0)
/* Limit of iterations of early inliner. This basically bounds number of
nested indirect calls early inliner can resolve. Deeper chains are still
handled by late inlining. */
DEFPARAM (PARAM_EARLY_INLINER_MAX_ITERATIONS,
"max-early-inliner-iterations",
"The maximum number of nested indirect inlining performed by early inliner",
10, 0, 0)
/* Limit the number of expansions created by the variable expansion /* Limit the number of expansions created by the variable expansion
optimization to avoid register pressure. */ optimization to avoid register pressure. */
DEFPARAM (PARAM_MAX_VARIABLE_EXPANSIONS, DEFPARAM (PARAM_MAX_VARIABLE_EXPANSIONS,
......
2009-05-15 Jan Hubicka <jh@suse.cz> 2009-05-15 Jan Hubicka <jh@suse.cz>
* testsuite/gcc.dg/tree-ssa/inline-3.c: New testcase
2009-05-15 Jan Hubicka <jh@suse.cz>
* gcc.target/i386/align-main-1.c (check): Mark noinline. * gcc.target/i386/align-main-1.c (check): Mark noinline.
* gcc.target/i386/align-main-2.c (check): Mark noinline. * gcc.target/i386/align-main-2.c (check): Mark noinline.
* gcc.dg/ipa/ipa-4.c: Disable early inlining. * gcc.dg/ipa/ipa-4.c: Disable early inlining.
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-einline2" } */
extern void inlined ();
void inline_me_too (void);
void inline_through_me (void (*ptr)(void));
void
inline_me (void)
{
inlined();
}
void main(void)
{
inline_through_me (inline_me);
inline_through_me (inline_me_too);
}
void
inline_through_me (void (*ptr)(void))
{
ptr();
}
void
inline_me_too (void)
{
inlined();
}
/* { dg-final { scan-tree-dump-times "Inlining inline_me " 1 "einline2"} } */
/* { dg-final { scan-tree-dump-times "Inlining inline_me_too " 1 "einline2"} } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment