aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/doc/invoke.texi12
-rw-r--r--gcc/ipa-inline.c99
-rw-r--r--gcc/params.def10
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 <hubicka@ucw.cz>
+
+ * 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 <richard.sandiford@arm.com>
* 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.",