From 2925cad2151842daa387950e62d989090e47c91d Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 3 Oct 2019 17:08:21 +0200 Subject: [PATCH] params.def (PARAM_INLINE_HEURISTICS_HINT_PERCENT, [...]): New. * params.def (PARAM_INLINE_HEURISTICS_HINT_PERCENT, PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2): New. * doc/invoke.texi (inline-heuristics-hint-percent, inline-heuristics-hint-percent-O2): Document. * tree-inline.c (inline_insns_single, inline_insns_auto): Add new hint attribute. (can_inline_edge_by_limits_p): Use it. From-SVN: r276516 --- gcc/ChangeLog | 10 ++++++ gcc/doc/invoke.texi | 12 +++++++ gcc/ipa-inline.c | 99 +++++++++++++++++++++++++++++++---------------------- gcc/params.def | 10 ++++++ 4 files changed, 90 insertions(+), 41 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ae3a0799..ff52beb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-10-03 Jan Hubicka + + * params.def (PARAM_INLINE_HEURISTICS_HINT_PERCENT, + PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2): New. + * doc/invoke.texi (inline-heuristics-hint-percent, + inline-heuristics-hint-percent-O2): Document. + * tree-inline.c (inline_insns_single, inline_insns_auto): Add new + hint attribute. + (can_inline_edge_by_limits_p): Use it. + 2019-10-03 Richard Sandiford * config/arm/arm.c (arm_print_value): Use real_to_decimal diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4861920..ac20e3a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -11215,6 +11215,18 @@ function prologue and epilogue. Extra time accounted by inliner for function overhead such as time needed to execute function prologue and epilogue +@item inline-heuristics-hint-percent +@item inline-heuristics-hint-percent-O2 +The scale (in percents) applied to @option{inline-insns-single}, +@option{inline-insns-single-O2}, @option{inline-insns-auto}, +@option{inline-insns-auto-O2} when inline heuristics hints that inlining is +very profitable (will enable later optimizations). + +For functions compiled with optimization levels +@option{-O3} and @option{-Ofast} parameter +@option{inline-heuristics-hint-percent} is applied. In other cases +@option{inline-heuristics-hint-percent-O2} is applied. + @item uninlined-thunk-insns @item uninlined-thunk-time Same as @option{--param uninlined-function-insns} and diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 98d7fd3..725e675 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -390,26 +390,48 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, return inlinable; } -/* Return inlining_insns_single limit for function N */ +/* Return inlining_insns_single limit for function N. If HINT is true + scale up the bound. */ static int -inline_insns_single (cgraph_node *n) +inline_insns_single (cgraph_node *n, bool hint) { if (opt_for_fn (n->decl, optimize >= 3)) - return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE); + { + if (hint) + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE) + * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT) / 100; + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE); + } else - return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE_O2); + { + if (hint) + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE_O2) + * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2) / 100; + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE_O2); + } } -/* Return inlining_insns_auto limit for function N */ +/* Return inlining_insns_auto limit for function N. If HINT is true + scale up the bound. */ static int -inline_insns_auto (cgraph_node *n) +inline_insns_auto (cgraph_node *n, bool hint) { if (opt_for_fn (n->decl, optimize >= 3)) - return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO); + { + if (hint) + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO) + * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT) / 100; + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO); + } else - return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO_O2); + { + if (hint) + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO_O2) + * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2) / 100; + return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO_O2); + } } /* Decide if we can inline the edge and possibly update @@ -554,8 +576,8 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report, int growth = estimate_edge_growth (e); if (growth > PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE) && (!DECL_DECLARED_INLINE_P (callee->decl) - && growth >= MAX (inline_insns_single (caller), - inline_insns_auto (caller)))) + && growth >= MAX (inline_insns_single (caller, false), + inline_insns_auto (caller, false)))) { e->inline_failed = CIF_OPTIMIZATION_MISMATCH; inlinable = false; @@ -801,15 +823,12 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) want_inline = false; } /* Do fast and conservative check if the function can be good - inline candidate. At the moment we allow inline hints to - promote non-inline functions to inline and we increase - MAX_INLINE_INSNS_SINGLE 16-fold for inline functions. */ + inline candidate. */ else if ((!DECL_DECLARED_INLINE_P (callee->decl) && (!e->count.ipa ().initialized_p () || !e->maybe_hot_p ())) && ipa_fn_summaries->get (callee)->min_size - ipa_call_summaries->get (e)->call_stmt_size - > MAX (inline_insns_single (e->caller), - inline_insns_auto (e->caller))) + > inline_insns_auto (e->caller, true)) { if (opt_for_fn (e->caller->decl, optimize) >= 3) e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT; @@ -821,7 +840,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) || e->count.ipa ().nonzero_p ()) && ipa_fn_summaries->get (callee)->min_size - ipa_call_summaries->get (e)->call_stmt_size - > 16 * inline_insns_single (e->caller)) + > inline_insns_single (e->caller, true)) { if (opt_for_fn (e->caller->decl, optimize) >= 3) e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl) @@ -837,20 +856,22 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) { int growth = estimate_edge_growth (e); ipa_hints hints = estimate_edge_hints (e); - int big_speedup = -1; /* compute this lazily */ + bool apply_hints = (hints & (INLINE_HINT_indirect_call + | INLINE_HINT_known_hot + | INLINE_HINT_loop_iterations + | INLINE_HINT_loop_stride)); if (growth <= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE)) ; /* Apply 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. + Avoid computation of big_speedup_p when not necessary to change + outcome of decision. */ else if (DECL_DECLARED_INLINE_P (callee->decl) - && growth >= inline_insns_single (e->caller) - && (growth >= inline_insns_single (e->caller) * 16 - || (!(hints & (INLINE_HINT_indirect_call - | INLINE_HINT_known_hot - | INLINE_HINT_loop_iterations - | INLINE_HINT_loop_stride)) - && !(big_speedup = big_speedup_p (e))))) + && growth >= inline_insns_single (e->caller, apply_hints) + && (apply_hints + || growth >= inline_insns_single (e->caller, true) + || !big_speedup_p (e))) { if (opt_for_fn (e->caller->decl, optimize) >= 3) e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT; @@ -863,28 +884,23 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) && growth >= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SMALL)) { /* growth_likely_positive is expensive, always test it last. */ - if (growth >= inline_insns_single (e->caller) + if (growth >= inline_insns_single (e->caller, false) || growth_likely_positive (callee, growth)) { e->inline_failed = CIF_NOT_DECLARED_INLINED; want_inline = false; } } - /* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline - Upgrade it to MAX_INLINE_INSNS_SINGLE when hints suggests that - inlining given function is very profitable. */ + /* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline. + Bypass the limit when speedup seems big. */ else if (!DECL_DECLARED_INLINE_P (callee->decl) - && !(hints & INLINE_HINT_known_hot) - && growth >= ((hints & (INLINE_HINT_indirect_call - | INLINE_HINT_loop_iterations - | INLINE_HINT_loop_stride)) - ? MAX (inline_insns_auto (e->caller), - inline_insns_single (e->caller)) - : inline_insns_auto (e->caller)) - && !(big_speedup == -1 ? big_speedup_p (e) : big_speedup)) + && growth >= inline_insns_auto (e->caller, apply_hints) + && (apply_hints + || growth >= inline_insns_auto (e->caller, true) + || !big_speedup_p (e))) { /* growth_likely_positive is expensive, always test it last. */ - if (growth >= inline_insns_single (e->caller) + if (growth >= inline_insns_single (e->caller, false) || growth_likely_positive (callee, growth)) { if (opt_for_fn (e->caller->decl, optimize) >= 3) @@ -896,7 +912,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) } /* If call is cold, do not inline when function body would grow. */ else if (!e->maybe_hot_p () - && (growth >= inline_insns_single (e->caller) + && (growth >= inline_insns_single (e->caller, false) || growth_likely_positive (callee, growth))) { e->inline_failed = CIF_UNLIKELY_CALL; @@ -1200,12 +1216,13 @@ edge_badness (struct cgraph_edge *edge, bool dump) int caller_growth = caller_info->growth; /* Only apply the penalty when caller looks like inline candidate, - and it is not called once and. */ + and it is not called once. */ if (!caller_info->single_caller && overall_growth < caller_growth && caller_info->inlinable && caller_info->size < (DECL_DECLARED_INLINE_P (caller->decl) - ? inline_insns_single (caller) : inline_insns_auto (caller))) + ? inline_insns_single (caller, false) + : inline_insns_auto (caller, false))) { if (dump) fprintf (dump_file, diff --git a/gcc/params.def b/gcc/params.def index 80f73b8..4cb48d9 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -102,6 +102,16 @@ DEFPARAM (PARAM_MAX_INLINE_INSNS_SMALL, "The maximum number of instructions when automatically inlining small functions.", 0, 0, 0) +DEFPARAM (PARAM_INLINE_HEURISTICS_HINT_PERCENT, + "inline-heuristics-hint-percent", + "The scale (in percents) applied to inline-insns-single and auto limits when heuristics hints that inlining is very profitable with -O3 and -Ofast.", + 1600, 100, 1000000) + +DEFPARAM (PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2, + "inline-heuristics-hint-percent-O2", + "The scale (in percents) applied to inline-insns-single and auto limits when heuristics hints that inlining is very profitable.", + 200, 100, 1000000) + DEFPARAM (PARAM_MAX_INLINE_INSNS_SIZE, "max-inline-insns-size", "The maximum number of instructions when inlining for size.", -- 2.7.4