Commit 1e83bd70 by Jan Hubicka

Convert inliner to new param infrastructure

/bin/sh: :q: command not found
This patch adds opt_for_fn for all cross module params used by inliner
so they can be modified at function granuality.  With inlining almost always
there are three functions to consider (callee and caller of the inlined edge
and the outer function caller is inlined to).

I always use the outer function params since that is how local parameters
behave.  I hope it is kind of what is also expected in most case: it is better
to inline agressively into -O3 compiled code rather than inline agressively -O3
functions into their callers.

New params infrastructure is nice.  One drawback is that is very hard to
search for individual param uses since they all occupy global namespace.
With C++ world we had chance to do something like params.param_flag_name
or params::param_flag_name instead...

Bootstrapped/regtested x86_64-linux, comitted.

	* cif-code.def (MAX_INLINE_INSNS_SINGLE_O2_LIMIT): Remove.
	* doc/invoke.texi (max-inline-insns-single-O2,
	inline-heuristics-hint-percent-O2, inline-min-speedup-O2,
	early-inlining-insns-O2): Remove documentation.
	* ipa-fnsummary.c (analyze_function_body,
	compute_fn_summary): Use opt_for_fn when accessing parameters.
	* ipa-inline.c (caller_growth_limits, can_inline_edge_p,
	inline_insns_auto, can_inline_edge_by_limits_p,
	want_early_inline_function_p, big_speedup_p,
	want_inline_small_function_p, want_inline_self_recursive_call_p,
	recursive_inlining, compute_max_insns, inline_small_functions):
	Likewise.
	* opts.c (default_options): Add -O3 defaults for
	OPT__param_early_inlining_insns_,
	OPT__param_inline_heuristics_hint_percent_,
	OPT__param_inline_min_speedup_, OPT__param_max_inline_insns_single_.
	* params.opt (-param=early-inlining-insns-O2=,
	-param=inline-heuristics-hint-percent-O2=,
	-param=inline-min-speedup-O2=, -param=max-inline-insns-single-O2=
	-param=early-inlining-insns=, -param=inline-heuristics-hint-percent=,
	-param=inline-min-speedup=, -param=inline-unit-growth=,
	-param=large-function-growth=, -param=large-stack-frame=,
	-param=large-stack-frame-growth=, -param=large-unit-insns=,
	-param=max-inline-insns-recursive=,
	-param=max-inline-insns-recursive-auto=,
	-param=max-inline-insns-single=,
	-param=max-inline-insns-size=, -param=max-inline-insns-small=,
	-param=max-inline-recursive-depth=,
	-param=max-inline-recursive-depth-auto=,
	-param=min-inline-recursive-probability=,
	-param=partial-inlining-entry-probability=,
	-param=uninlined-function-insns=, -param=uninlined-function-time=,
	-param=uninlined-thunk-insns=, -param=uninlined-thunk-time=): Add
	Optimization.

	* g++.dg/tree-ssa/pr53844.C: Drop -O2 from param name.
	* g++.dg/tree-ssa/pr61034.C: Likewise.
	* g++.dg/tree-ssa/pr8781.C: Likewise.
	* g++.dg/warn/Wstringop-truncation-1.C: Likewise.
	* gcc.dg/ipa/pr63416.c: Likewise.
	* gcc.dg/tree-ssa/ssa-thread-12.c: Likewise.
	* gcc.dg/vect/pr66142.c: Likewise.
	* gcc.dg/winline-3.c: Likewise.
	* gcc.target/powerpc/pr72804.c: Likewise.

From-SVN: r278645
parent 9340d345
...@@ -178,13 +178,13 @@ caller_growth_limits (struct cgraph_edge *e) ...@@ -178,13 +178,13 @@ caller_growth_limits (struct cgraph_edge *e)
if (limit < what_size_info->self_size) if (limit < what_size_info->self_size)
limit = what_size_info->self_size; limit = what_size_info->self_size;
limit += limit * param_large_function_growth / 100; limit += limit * opt_for_fn (to->decl, param_large_function_growth) / 100;
/* Check the size after inlining against the function limits. But allow /* Check the size after inlining against the function limits. But allow
the function to shrink if it went over the limits by forced inlining. */ the function to shrink if it went over the limits by forced inlining. */
newsize = estimate_size_after_inlining (to, e); newsize = estimate_size_after_inlining (to, e);
if (newsize >= ipa_size_summaries->get (what)->size if (newsize >= ipa_size_summaries->get (what)->size
&& newsize > param_large_function_insns && newsize > opt_for_fn (to->decl, param_large_function_insns)
&& newsize > limit) && newsize > limit)
{ {
e->inline_failed = CIF_LARGE_FUNCTION_GROWTH_LIMIT; e->inline_failed = CIF_LARGE_FUNCTION_GROWTH_LIMIT;
...@@ -200,7 +200,8 @@ caller_growth_limits (struct cgraph_edge *e) ...@@ -200,7 +200,8 @@ caller_growth_limits (struct cgraph_edge *e)
on every invocation of the caller (i.e. its call statement dominates on every invocation of the caller (i.e. its call statement dominates
exit block). We do not track this information, yet. */ exit block). We do not track this information, yet. */
stack_size_limit += ((gcov_type)stack_size_limit stack_size_limit += ((gcov_type)stack_size_limit
* param_stack_frame_growth / 100); * opt_for_fn (to->decl, param_stack_frame_growth)
/ 100);
inlined_stack = (ipa_get_stack_frame_offset (to) inlined_stack = (ipa_get_stack_frame_offset (to)
+ outer_info->estimated_self_stack_size + outer_info->estimated_self_stack_size
...@@ -213,7 +214,7 @@ caller_growth_limits (struct cgraph_edge *e) ...@@ -213,7 +214,7 @@ caller_growth_limits (struct cgraph_edge *e)
This bit overoptimistically assume that we are good at stack This bit overoptimistically assume that we are good at stack
packing. */ packing. */
&& inlined_stack > ipa_fn_summaries->get (to)->estimated_stack_size && inlined_stack > ipa_fn_summaries->get (to)->estimated_stack_size
&& inlined_stack > param_large_stack_frame) && inlined_stack > opt_for_fn (to->decl, param_large_stack_frame))
{ {
e->inline_failed = CIF_LARGE_STACK_FRAME_GROWTH_LIMIT; e->inline_failed = CIF_LARGE_STACK_FRAME_GROWTH_LIMIT;
return false; return false;
...@@ -395,20 +396,10 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, ...@@ -395,20 +396,10 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
static int static int
inline_insns_single (cgraph_node *n, bool hint) inline_insns_single (cgraph_node *n, bool hint)
{ {
if (opt_for_fn (n->decl, optimize) >= 3)
{
if (hint)
return param_max_inline_insns_single
* param_inline_heuristics_hint_percent / 100;
return param_max_inline_insns_single;
}
else
{
if (hint) if (hint)
return param_max_inline_insns_single_o2 return opt_for_fn (n->decl, param_max_inline_insns_single)
* param_inline_heuristics_hint_percent_o2 / 100; * opt_for_fn (n->decl, param_inline_heuristics_hint_percent) / 100;
return param_max_inline_insns_single_o2; return opt_for_fn (n->decl, param_max_inline_insns_single);
}
} }
/* Return inlining_insns_auto limit for function N. If HINT is true /* Return inlining_insns_auto limit for function N. If HINT is true
...@@ -419,7 +410,8 @@ inline_insns_auto (cgraph_node *n, bool hint) ...@@ -419,7 +410,8 @@ inline_insns_auto (cgraph_node *n, bool hint)
{ {
int max_inline_insns_auto = opt_for_fn (n->decl, param_max_inline_insns_auto); int max_inline_insns_auto = opt_for_fn (n->decl, param_max_inline_insns_auto);
if (hint) if (hint)
return max_inline_insns_auto * param_inline_heuristics_hint_percent / 100; return max_inline_insns_auto
* opt_for_fn (n->decl, param_inline_heuristics_hint_percent) / 100;
return max_inline_insns_auto; return max_inline_insns_auto;
} }
...@@ -563,7 +555,7 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report, ...@@ -563,7 +555,7 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
> opt_for_fn (caller->decl, optimize_size)) > opt_for_fn (caller->decl, optimize_size))
{ {
int growth = estimate_edge_growth (e); int growth = estimate_edge_growth (e);
if (growth > param_max_inline_insns_size if (growth > opt_for_fn (caller->decl, param_max_inline_insns_size)
&& (!DECL_DECLARED_INLINE_P (callee->decl) && (!DECL_DECLARED_INLINE_P (callee->decl)
&& growth >= MAX (inline_insns_single (caller, false), && growth >= MAX (inline_insns_single (caller, false),
inline_insns_auto (caller, false)))) inline_insns_auto (caller, false))))
...@@ -675,9 +667,7 @@ want_early_inline_function_p (struct cgraph_edge *e) ...@@ -675,9 +667,7 @@ want_early_inline_function_p (struct cgraph_edge *e)
/* First take care of very large functions. */ /* First take care of very large functions. */
int min_growth = estimate_min_edge_growth (e), growth = 0; int min_growth = estimate_min_edge_growth (e), growth = 0;
int n; int n;
int early_inlining_insns = opt_for_fn (e->caller->decl, optimize) >= 3 int early_inlining_insns = param_early_inlining_insns;
? param_early_inlining_insns
: param_early_inlining_insns_o2;
if (min_growth > early_inlining_insns) if (min_growth > early_inlining_insns)
{ {
...@@ -824,9 +814,7 @@ big_speedup_p (struct cgraph_edge *e) ...@@ -824,9 +814,7 @@ big_speedup_p (struct cgraph_edge *e)
cgraph_node *caller = (e->caller->inlined_to cgraph_node *caller = (e->caller->inlined_to
? e->caller->inlined_to ? e->caller->inlined_to
: e->caller); : e->caller);
int limit = opt_for_fn (caller->decl, optimize) >= 3 int limit = opt_for_fn (caller->decl, param_inline_min_speedup);
? param_inline_min_speedup
: param_inline_min_speedup_o2;
if ((time - inlined_time) * 100 > time * limit) if ((time - inlined_time) * 100 > time * limit)
return true; return true;
...@@ -841,6 +829,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -841,6 +829,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
{ {
bool want_inline = true; bool want_inline = true;
struct cgraph_node *callee = e->callee->ultimate_alias_target (); struct cgraph_node *callee = e->callee->ultimate_alias_target ();
cgraph_node *to = (e->caller->inlined_to
? e->caller->inlined_to : e->caller);
/* Allow this function to be called before can_inline_edge_p, /* Allow this function to be called before can_inline_edge_p,
since it's usually cheaper. */ since it's usually cheaper. */
...@@ -876,9 +866,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -876,9 +866,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT ? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
: CIF_MAX_INLINE_INSNS_AUTO_LIMIT); : CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
else else
e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl) e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
? CIF_MAX_INLINE_INSNS_SINGLE_O2_LIMIT
: CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
want_inline = false; want_inline = false;
} }
else else
...@@ -890,7 +878,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -890,7 +878,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
| INLINE_HINT_loop_iterations | INLINE_HINT_loop_iterations
| INLINE_HINT_loop_stride)); | INLINE_HINT_loop_stride));
if (growth <= param_max_inline_insns_size) if (growth <= opt_for_fn (to->decl,
param_max_inline_insns_size))
; ;
/* Apply param_max_inline_insns_single limit. Do not do so when /* Apply param_max_inline_insns_single limit. Do not do so when
hints suggests that inlining given function is very profitable. hints suggests that inlining given function is very profitable.
...@@ -902,15 +891,13 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -902,15 +891,13 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
|| growth >= inline_insns_single (e->caller, true) || growth >= inline_insns_single (e->caller, true)
|| !big_speedup_p (e))) || !big_speedup_p (e)))
{ {
if (opt_for_fn (e->caller->decl, optimize) >= 3)
e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT; e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
else
e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_O2_LIMIT;
want_inline = false; want_inline = false;
} }
else if (!DECL_DECLARED_INLINE_P (callee->decl) else if (!DECL_DECLARED_INLINE_P (callee->decl)
&& !opt_for_fn (e->caller->decl, flag_inline_functions) && !opt_for_fn (e->caller->decl, flag_inline_functions)
&& growth >= param_max_inline_insns_small) && growth >= opt_for_fn (to->decl,
param_max_inline_insns_small))
{ {
/* growth_positive_p is expensive, always test it last. */ /* growth_positive_p is expensive, always test it last. */
if (growth >= inline_insns_single (e->caller, false) if (growth >= inline_insns_single (e->caller, false)
...@@ -951,7 +938,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -951,7 +938,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
} }
/* EDGE is self recursive edge. /* EDGE is self recursive edge.
We hand two cases - when function A is inlining into itself We handle two cases - when function A is inlining into itself
or when function A is being inlined into another inliner copy of function or when function A is being inlined into another inliner copy of function
A within function B. A within function B.
...@@ -970,10 +957,12 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge, ...@@ -970,10 +957,12 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
char const *reason = NULL; char const *reason = NULL;
bool want_inline = true; bool want_inline = true;
sreal caller_freq = 1; sreal caller_freq = 1;
int max_depth = param_max_inline_recursive_depth_auto; int max_depth = opt_for_fn (outer_node->decl,
param_max_inline_recursive_depth_auto);
if (DECL_DECLARED_INLINE_P (edge->caller->decl)) if (DECL_DECLARED_INLINE_P (edge->caller->decl))
max_depth = param_max_inline_recursive_depth; max_depth = opt_for_fn (outer_node->decl,
param_max_inline_recursive_depth);
if (!edge->maybe_hot_p ()) if (!edge->maybe_hot_p ())
{ {
...@@ -1035,7 +1024,8 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge, ...@@ -1035,7 +1024,8 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
{ {
if (edge->sreal_frequency () * 100 if (edge->sreal_frequency () * 100
<= caller_freq <= caller_freq
* param_min_inline_recursive_probability) * opt_for_fn (outer_node->decl,
param_min_inline_recursive_probability))
{ {
reason = "frequency of recursive call is too small"; reason = "frequency of recursive call is too small";
want_inline = false; want_inline = false;
...@@ -1241,7 +1231,9 @@ edge_badness (struct cgraph_edge *edge, bool dump) ...@@ -1241,7 +1231,9 @@ edge_badness (struct cgraph_edge *edge, bool dump)
/* ... or when early optimizers decided to split and edge /* ... or when early optimizers decided to split and edge
frequency still indicates splitting is a win ... */ frequency still indicates splitting is a win ... */
|| (callee->split_part && !caller->split_part || (callee->split_part && !caller->split_part
&& freq * 100 < param_partial_inlining_entry_probability && freq * 100
< opt_for_fn (caller->decl,
param_partial_inlining_entry_probability)
/* ... and do not overwrite user specified hints. */ /* ... and do not overwrite user specified hints. */
&& (!DECL_DECLARED_INLINE_P (edge->callee->decl) && (!DECL_DECLARED_INLINE_P (edge->callee->decl)
|| DECL_DECLARED_INLINE_P (caller->decl))))) || DECL_DECLARED_INLINE_P (caller->decl)))))
...@@ -1599,7 +1591,10 @@ static bool ...@@ -1599,7 +1591,10 @@ static bool
recursive_inlining (struct cgraph_edge *edge, recursive_inlining (struct cgraph_edge *edge,
vec<cgraph_edge *> *new_edges) vec<cgraph_edge *> *new_edges)
{ {
int limit = param_max_inline_insns_recursive_auto; cgraph_node *to = (edge->caller->inlined_to
? edge->caller->inlined_to : edge->caller);
int limit = opt_for_fn (to->decl,
param_max_inline_insns_recursive_auto);
edge_heap_t heap (sreal::min ()); edge_heap_t heap (sreal::min ());
struct cgraph_node *node; struct cgraph_node *node;
struct cgraph_edge *e; struct cgraph_edge *e;
...@@ -1612,7 +1607,7 @@ recursive_inlining (struct cgraph_edge *edge, ...@@ -1612,7 +1607,7 @@ recursive_inlining (struct cgraph_edge *edge,
node = node->inlined_to; node = node->inlined_to;
if (DECL_DECLARED_INLINE_P (node->decl)) if (DECL_DECLARED_INLINE_P (node->decl))
limit = param_max_inline_insns_recursive; limit = opt_for_fn (to->decl, param_max_inline_insns_recursive);
/* Make sure that function is small enough to be considered for inlining. */ /* Make sure that function is small enough to be considered for inlining. */
if (estimate_size_after_inlining (node, edge) >= limit) if (estimate_size_after_inlining (node, edge) >= limit)
...@@ -1735,14 +1730,14 @@ recursive_inlining (struct cgraph_edge *edge, ...@@ -1735,14 +1730,14 @@ recursive_inlining (struct cgraph_edge *edge,
allow the unit to grow. */ allow the unit to grow. */
static int static int
compute_max_insns (int insns) compute_max_insns (cgraph_node *node, int insns)
{ {
int max_insns = insns; int max_insns = insns;
if (max_insns < param_large_unit_insns) if (max_insns < opt_for_fn (node->decl, param_large_unit_insns))
max_insns = param_large_unit_insns; max_insns = opt_for_fn (node->decl, param_large_unit_insns);
return ((int64_t) max_insns return ((int64_t) max_insns
* (100 + param_inline_unit_growth) / 100); * (100 + opt_for_fn (node->decl, param_inline_unit_growth)) / 100);
} }
...@@ -1906,7 +1901,7 @@ inline_small_functions (void) ...@@ -1906,7 +1901,7 @@ inline_small_functions (void)
struct cgraph_edge *edge; struct cgraph_edge *edge;
edge_heap_t edge_heap (sreal::min ()); edge_heap_t edge_heap (sreal::min ());
auto_bitmap updated_nodes; auto_bitmap updated_nodes;
int min_size, max_size; int min_size;
auto_vec<cgraph_edge *> new_indirect_edges; auto_vec<cgraph_edge *> new_indirect_edges;
int initial_size = 0; int initial_size = 0;
struct cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count); struct cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count);
...@@ -1973,7 +1968,6 @@ inline_small_functions (void) ...@@ -1973,7 +1968,6 @@ inline_small_functions (void)
initial_size); initial_size);
overall_size = initial_size; overall_size = initial_size;
max_size = compute_max_insns (overall_size);
min_size = overall_size; min_size = overall_size;
/* Populate the heap with all edges we might inline. */ /* Populate the heap with all edges we might inline. */
...@@ -2141,7 +2135,9 @@ inline_small_functions (void) ...@@ -2141,7 +2135,9 @@ inline_small_functions (void)
edge_badness (edge, true); edge_badness (edge, true);
} }
if (overall_size + growth > max_size where = edge->caller;
if (overall_size + growth > compute_max_insns (where, min_size)
&& !DECL_DISREGARD_INLINE_LIMITS (callee->decl)) && !DECL_DISREGARD_INLINE_LIMITS (callee->decl))
{ {
edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT; edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT;
...@@ -2164,7 +2160,6 @@ inline_small_functions (void) ...@@ -2164,7 +2160,6 @@ inline_small_functions (void)
specific inliner. */ specific inliner. */
if (edge->recursive_p ()) if (edge->recursive_p ())
{ {
where = edge->caller;
if (where->inlined_to) if (where->inlined_to)
where = where->inlined_to; where = where->inlined_to;
if (!recursive_inlining (edge, if (!recursive_inlining (edge,
...@@ -2278,7 +2273,6 @@ inline_small_functions (void) ...@@ -2278,7 +2273,6 @@ inline_small_functions (void)
if (min_size > overall_size) if (min_size > overall_size)
{ {
min_size = overall_size; min_size = overall_size;
max_size = compute_max_insns (min_size);
if (dump_file) if (dump_file)
fprintf (dump_file, "New minimal size reached: %i\n", min_size); fprintf (dump_file, "New minimal size reached: %i\n", min_size);
......
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