Fix can_inline_edge_p and code marking calls unreachable
Christophe Lyon
christophe.lyon@linaro.org
Thu Mar 26 22:58:00 GMT 2015
On 26 March 2015 at 22:12, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this patch missed hunk adding CIF code that I commited now
> * cif-code.def (CILK_SPAWN): New code
Hi,
After this fix, I can see build failures in glibc:
key_call.c:574:1: internal compiler error: in inline_call, at
ipa-inline-transform.c:386
}
^
0x10eb475 inline_call(cgraph_edge*, bool, vec<cgraph_edge*, va_heap,
vl_ptr>*, int*, bool, bool*)
/tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline-transform.c:381
0x10e43ed inline_small_functions
/tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline.c:1942
0x10e4ead ipa_inline
/tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline.c:2345
See http://abe.tcwglab.linaro.org/logs/validations/cross-validation/gcc-build/trunk/221710/build.html
for more detailed logs.
Thanks
Christophe
>
> --- trunk/gcc/cif-code.def 2015/03/26 20:37:53 221709
> +++ trunk/gcc/cif-code.def 2015/03/26 21:10:28 221710
> @@ -124,6 +124,10 @@
> DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
> N_("function attribute mismatch"))
>
> +/* We can't inline because of mismatched caller/callee attributes. */
> +DEFCIFCODE(CILK_SPAWN, CIF_FINAL_ERROR,
> + N_("caller function contains cilk spawn"))
> +
> /* We proved that the call is unreachable. */
> DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
> N_("unreachable"))
>
> I also noticed that this breaks one testcase which is cured by the following patch
> I am testing and will commit once it concludes. I apologize for the breakage.
>
> Honza
>
> * ipa-inline.c (check_maybe_up, check_maybe_down, check_match):
> New macros.
> (can_inline_edge_p): Relax option matching for always inline functions.
> Index: ipa-inline.c
> ===================================================================
> --- ipa-inline.c (revision 221706)
> +++ ipa-inline.c (working copy)
> @@ -298,6 +298,27 @@ sanitize_attrs_match_for_inline_p (const
> DECL_ATTRIBUTES (callee));
> }
>
> +/* Used for flags where it is safe to inline when caller's value is
> + grater than callee's. */
> +#define check_maybe_up(flag) \
> + (opts_for_fn (caller->decl)->x_##flag \
> + != opts_for_fn (callee->decl)->x_##flag \
> + && (!always_inline \
> + || opts_for_fn (caller->decl)->x_##flag \
> + < opts_for_fn (callee->decl)->x_##flag))
> +/* Used for flags where it is safe to inline when caller's value is
> + smaller than callee's. */
> +#define check_maybe_down(flag) \
> + (opts_for_fn (caller->decl)->x_##flag \
> + != opts_for_fn (callee->decl)->x_##flag \
> + && (!always_inline \
> + || opts_for_fn (caller->decl)->x_##flag \
> + > opts_for_fn (callee->decl)->x_##flag))
> +/* Used for flags where exact match is needed for correctness. */
> +#define check_match(flag) \
> + (opts_for_fn (caller->decl)->x_##flag \
> + != opts_for_fn (callee->decl)->x_##flag)
> +
> /* Decide if we can inline the edge and possibly update
> inline_failed reason.
> We check whether inlining is possible at all and whether
> @@ -401,74 +422,60 @@ can_inline_edge_p (struct cgraph_edge *e
> optimization attribute. */
> else if (caller_tree != callee_tree)
> {
> + bool always_inline =
> + (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
> + && lookup_attribute ("always_inline",
> + DECL_ATTRIBUTES (callee->decl)));
> +
> /* There are some options that change IL semantics which means
> we cannot inline in these cases for correctness reason.
> Not even for always_inline declared functions. */
> /* Strictly speaking only when the callee contains signed integer
> math where overflow is undefined. */
> - if ((opt_for_fn (caller->decl, flag_strict_overflow)
> - != opt_for_fn (callee->decl, flag_strict_overflow))
> - || (opt_for_fn (caller->decl, flag_wrapv)
> - != opt_for_fn (callee->decl, flag_wrapv))
> - || (opt_for_fn (caller->decl, flag_trapv)
> - != opt_for_fn (callee->decl, flag_trapv))
> + if ((check_maybe_up (flag_strict_overflow)
> + /* this flag is set by optimize. Allow inlining across
> + optimize boundary. */
> + && (!opt_for_fn (caller->decl, optimize)
> + == !opt_for_fn (callee->decl, optimize) || !always_inline))
> + || check_match (flag_wrapv)
> + || check_match (flag_trapv)
> /* Strictly speaking only when the callee contains memory
> accesses that are not using alias-set zero anyway. */
> - || (opt_for_fn (caller->decl, flag_strict_aliasing)
> - != opt_for_fn (callee->decl, flag_strict_aliasing))
> + || check_maybe_down (flag_strict_aliasing)
> /* Strictly speaking only when the callee uses FP math. */
> - || (opt_for_fn (caller->decl, flag_rounding_math)
> - != opt_for_fn (callee->decl, flag_rounding_math))
> - || (opt_for_fn (caller->decl, flag_trapping_math)
> - != opt_for_fn (callee->decl, flag_trapping_math))
> - || (opt_for_fn (caller->decl, flag_unsafe_math_optimizations)
> - != opt_for_fn (callee->decl, flag_unsafe_math_optimizations))
> - || (opt_for_fn (caller->decl, flag_finite_math_only)
> - != opt_for_fn (callee->decl, flag_finite_math_only))
> - || (opt_for_fn (caller->decl, flag_signaling_nans)
> - != opt_for_fn (callee->decl, flag_signaling_nans))
> - || (opt_for_fn (caller->decl, flag_cx_limited_range)
> - != opt_for_fn (callee->decl, flag_cx_limited_range))
> - || (opt_for_fn (caller->decl, flag_signed_zeros)
> - != opt_for_fn (callee->decl, flag_signed_zeros))
> - || (opt_for_fn (caller->decl, flag_associative_math)
> - != opt_for_fn (callee->decl, flag_associative_math))
> - || (opt_for_fn (caller->decl, flag_reciprocal_math)
> - != opt_for_fn (callee->decl, flag_reciprocal_math))
> + || check_maybe_up (flag_rounding_math)
> + || check_maybe_up (flag_trapping_math)
> + || check_maybe_down (flag_unsafe_math_optimizations)
> + || check_maybe_down (flag_finite_math_only)
> + || check_maybe_up (flag_signaling_nans)
> + || check_maybe_down (flag_cx_limited_range)
> + || check_maybe_up (flag_signed_zeros)
> + || check_maybe_down (flag_associative_math)
> + || check_maybe_down (flag_reciprocal_math)
> /* We do not want to make code compiled with exceptions to be brought
> into a non-EH function unless we know that the callee does not
> throw. This is tracked by DECL_FUNCTION_PERSONALITY. */
> - || (opt_for_fn (caller->decl, flag_non_call_exceptions)
> - != opt_for_fn (callee->decl, flag_non_call_exceptions)
> + || (check_match (flag_non_call_exceptions)
> /* TODO: We also may allow bringing !flag_non_call_exceptions
> to flag_non_call_exceptions function, but that may need
> extra work in tree-inline to add the extra EH edges. */
> && (!opt_for_fn (callee->decl, flag_non_call_exceptions)
> || DECL_FUNCTION_PERSONALITY (callee->decl)))
> - || (!opt_for_fn (caller->decl, flag_exceptions)
> - && opt_for_fn (callee->decl, flag_exceptions)
> + || (check_maybe_up (flag_exceptions)
> && DECL_FUNCTION_PERSONALITY (callee->decl))
> /* Strictly speaking only when the callee contains function
> calls that may end up setting errno. */
> - || (opt_for_fn (caller->decl, flag_errno_math)
> - != opt_for_fn (callee->decl, flag_errno_math))
> + || check_maybe_up (flag_errno_math)
> /* When devirtualization is diabled for callee, it is not safe
> to inline it as we possibly mangled the type info.
> Allow early inlining of always inlines. */
> - || (opt_for_fn (caller->decl, flag_devirtualize)
> - && !opt_for_fn (callee->decl, flag_devirtualize)
> - && (!early
> - || (!DECL_DISREGARD_INLINE_LIMITS (callee->decl)
> - || !lookup_attribute ("always_inline",
> - DECL_ATTRIBUTES (callee->decl))))))
> + || (!early && check_maybe_down (flag_devirtualize)))
> {
> e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
> inlinable = false;
> }
> /* gcc.dg/pr43564.c. Apply user-forced inline even at -O0. */
> - else if (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
> - && lookup_attribute ("always_inline",
> - DECL_ATTRIBUTES (callee->decl)))
> + else if (always_inline)
> ;
> /* When user added an attribute to the callee honor it. */
> else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))
More information about the Gcc-patches
mailing list