Hi,
this patch fixes first half of the PR. The PR is about a function that is
supposed
to be inlined at -O2. The function contains two calls, one indirect and
inlining
the indirect call makes things a lot better. GCC however things that replacing
call
by two calls at -O2 is a bad idea.
This patch solves first part of it. The function in question is COMDAT. We
already
know that C++ coding style makes COMDATs quite rarely to be shared and at -Os we
already handle them sort of similarly to static ufnctions. We however don't do
that
at -O2. This patch makes it happen in both cases.
Bootstrapped/regtested x86_64-linux, comitted.
Will commit the testcase with the followup fix.
PR tree-optimization/51680
* ipa-inline.c (want_inline_small_function_p): Be more lax on functions
whose inlining reduce unit size.
Index: ipa-inline.c
===================================================================
--- ipa-inline.c (revision 182949)
+++ ipa-inline.c (working copy)
@@ -482,21 +482,13 @@ want_inline_small_function_p (struct cgr
e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
want_inline = false;
}
- else if (!DECL_DECLARED_INLINE_P (callee->decl)
- && !flag_inline_functions)
- {
- e->inline_failed = CIF_NOT_DECLARED_INLINED;
- want_inline = false;
- }
- else if (!DECL_DECLARED_INLINE_P (callee->decl)
- && growth >= MAX_INLINE_INSNS_AUTO)
- {
- e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
- want_inline = false;
- }
- /* If call is cold, do not inline when function body would grow.
- Still inline when the overall unit size will shrink because the offline
- copy of function being eliminated.
+ /* Before giving up based on fact that caller size will grow, allow
+ functions that are called few times and eliminating the offline
+ copy will lead to overall code size reduction.
+ Not all of these will be handled by subsequent inlining of functions
+ called once: in particular weak functions are not handled or funcitons
+ that inline to multiple calls but a lot of bodies is optimized out.
+ Finally we want to inline earlier to allow inlining of callbacks.
This is slightly wrong on aggressive side: it is entirely possible
that function is called many times with a context where inlining
@@ -509,24 +501,39 @@ want_inline_small_function_p (struct cgr
first, this situation is not a problem at all: after inlining all
"good" calls, we will realize that keeping the function around is
better. */
- else if (!cgraph_maybe_hot_edge_p (e)
- && (DECL_EXTERNAL (callee->decl)
+ else if (growth <= MAX_INLINE_INSNS_SINGLE
+ /* Unlike for functions called once, we play unsafe with
+ COMDATs. We can allow that since we know functions
+ in consideration are small (and thus risk is small) and
+ moreover grow estimates already accounts that COMDAT
+ functions may or may not disappear when eliminated from
+ current unit. With good probability making aggressive
+ choice in all units is going to make overall program
+ smaller.
+
+ Consequently we ask cgraph_can_remove_if_no_direct_calls_p
+ instead of
+ cgraph_will_be_removed_from_program_if_no_direct_calls */
+ && !DECL_EXTERNAL (callee->decl)
+ && cgraph_can_remove_if_no_direct_calls_p (callee)
+ && estimate_growth (callee) <= 0)
+ ;
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
+ && !flag_inline_functions)
+ {
+ e->inline_failed = CIF_NOT_DECLARED_INLINED;
+ want_inline = false;
+ }
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
+ && growth >= MAX_INLINE_INSNS_AUTO)
+ {
+ e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
+ want_inline = false;
+ }
+ /* If call is cold, do not inline when function body would grow. */
+ else if (!cgraph_maybe_hot_edge_p (e))
- /* Unlike for functions called once, we play unsafe with
- COMDATs. We can allow that since we know functions
- in consideration are small (and thus risk is small) and
- moreover grow estimates already accounts that COMDAT
- functions may or may not disappear when eliminated from
- current unit. With good probability making aggressive
- choice in all units is going to make overall program
- smaller.
-
- Consequently we ask cgraph_can_remove_if_no_direct_calls_p
- instead of
- cgraph_will_be_removed_from_program_if_no_direct_calls */
- || !cgraph_can_remove_if_no_direct_calls_p (callee)
- || estimate_growth (callee) > 0))
{
e->inline_failed = CIF_UNLIKELY_CALL;
want_inline = false;