re PR ipa/65873 (Failure to inline always_inline memcpy)
PR ipa/65873 * ipa-inline.c (can_inline_edge_p): Allow early inlining of always inlines across optimization boundary. From-SVN: r223107
This commit is contained in:
parent
fe1814cf84
commit
ddb3773a12
|
@ -1,3 +1,9 @@
|
||||||
|
2015-05-12 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
|
PR ipa/65873
|
||||||
|
* ipa-inline.c (can_inline_edge_p): Allow early inlining of always
|
||||||
|
inlines across optimization boundary.
|
||||||
|
|
||||||
2015-05-12 Jason Merrill <jason@redhat.com>
|
2015-05-12 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
* config/mmix/mmix.c, config/msp430/msp430.c: Add space between
|
* config/mmix/mmix.c, config/msp430/msp430.c: Add space between
|
||||||
|
|
|
@ -427,46 +427,55 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
|
||||||
&& lookup_attribute ("always_inline",
|
&& lookup_attribute ("always_inline",
|
||||||
DECL_ATTRIBUTES (callee->decl)));
|
DECL_ATTRIBUTES (callee->decl)));
|
||||||
|
|
||||||
|
/* Until GCC 4.9 we did not check the semantics alterning flags
|
||||||
|
bellow and inline across optimization boundry.
|
||||||
|
Enabling checks bellow breaks several packages by refusing
|
||||||
|
to inline library always_inline functions. See PR65873.
|
||||||
|
Disable the check for early inlining for now until better solution
|
||||||
|
is found. */
|
||||||
|
if (always_inline && early)
|
||||||
|
;
|
||||||
/* There are some options that change IL semantics which means
|
/* There are some options that change IL semantics which means
|
||||||
we cannot inline in these cases for correctness reason.
|
we cannot inline in these cases for correctness reason.
|
||||||
Not even for always_inline declared functions. */
|
Not even for always_inline declared functions. */
|
||||||
/* Strictly speaking only when the callee contains signed integer
|
/* Strictly speaking only when the callee contains signed integer
|
||||||
math where overflow is undefined. */
|
math where overflow is undefined. */
|
||||||
if ((check_maybe_up (flag_strict_overflow)
|
else if ((check_maybe_up (flag_strict_overflow)
|
||||||
/* this flag is set by optimize. Allow inlining across
|
/* this flag is set by optimize. Allow inlining across
|
||||||
optimize boundary. */
|
optimize boundary. */
|
||||||
&& (!opt_for_fn (caller->decl, optimize)
|
&& (!opt_for_fn (caller->decl, optimize)
|
||||||
== !opt_for_fn (callee->decl, optimize) || !always_inline))
|
== !opt_for_fn (callee->decl, optimize) || !always_inline))
|
||||||
|| check_match (flag_wrapv)
|
|| check_match (flag_wrapv)
|
||||||
|| check_match (flag_trapv)
|
|| check_match (flag_trapv)
|
||||||
/* Strictly speaking only when the callee uses FP math. */
|
/* Strictly speaking only when the callee uses FP math. */
|
||||||
|| check_maybe_up (flag_rounding_math)
|
|| check_maybe_up (flag_rounding_math)
|
||||||
|| check_maybe_up (flag_trapping_math)
|
|| check_maybe_up (flag_trapping_math)
|
||||||
|| check_maybe_down (flag_unsafe_math_optimizations)
|
|| check_maybe_down (flag_unsafe_math_optimizations)
|
||||||
|| check_maybe_down (flag_finite_math_only)
|
|| check_maybe_down (flag_finite_math_only)
|
||||||
|| check_maybe_up (flag_signaling_nans)
|
|| check_maybe_up (flag_signaling_nans)
|
||||||
|| check_maybe_down (flag_cx_limited_range)
|
|| check_maybe_down (flag_cx_limited_range)
|
||||||
|| check_maybe_up (flag_signed_zeros)
|
|| check_maybe_up (flag_signed_zeros)
|
||||||
|| check_maybe_down (flag_associative_math)
|
|| check_maybe_down (flag_associative_math)
|
||||||
|| check_maybe_down (flag_reciprocal_math)
|
|| check_maybe_down (flag_reciprocal_math)
|
||||||
/* We do not want to make code compiled with exceptions to be brought
|
/* We do not want to make code compiled with exceptions to be
|
||||||
into a non-EH function unless we know that the callee does not
|
brought into a non-EH function unless we know that the callee
|
||||||
throw. This is tracked by DECL_FUNCTION_PERSONALITY. */
|
does not throw.
|
||||||
|| (check_match (flag_non_call_exceptions)
|
This is tracked by DECL_FUNCTION_PERSONALITY. */
|
||||||
/* TODO: We also may allow bringing !flag_non_call_exceptions
|
|| (check_match (flag_non_call_exceptions)
|
||||||
to flag_non_call_exceptions function, but that may need
|
/* TODO: We also may allow bringing !flag_non_call_exceptions
|
||||||
extra work in tree-inline to add the extra EH edges. */
|
to flag_non_call_exceptions function, but that may need
|
||||||
&& (!opt_for_fn (callee->decl, flag_non_call_exceptions)
|
extra work in tree-inline to add the extra EH edges. */
|
||||||
|| DECL_FUNCTION_PERSONALITY (callee->decl)))
|
&& (!opt_for_fn (callee->decl, flag_non_call_exceptions)
|
||||||
|| (check_maybe_up (flag_exceptions)
|
|| DECL_FUNCTION_PERSONALITY (callee->decl)))
|
||||||
&& DECL_FUNCTION_PERSONALITY (callee->decl))
|
|| (check_maybe_up (flag_exceptions)
|
||||||
/* Strictly speaking only when the callee contains function
|
&& DECL_FUNCTION_PERSONALITY (callee->decl))
|
||||||
calls that may end up setting errno. */
|
/* Strictly speaking only when the callee contains function
|
||||||
|| check_maybe_up (flag_errno_math)
|
calls that may end up setting errno. */
|
||||||
/* When devirtualization is diabled for callee, it is not safe
|
|| check_maybe_up (flag_errno_math)
|
||||||
to inline it as we possibly mangled the type info.
|
/* When devirtualization is diabled for callee, it is not safe
|
||||||
Allow early inlining of always inlines. */
|
to inline it as we possibly mangled the type info.
|
||||||
|| (!early && check_maybe_down (flag_devirtualize)))
|
Allow early inlining of always inlines. */
|
||||||
|
|| (!early && check_maybe_down (flag_devirtualize)))
|
||||||
{
|
{
|
||||||
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
|
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
|
||||||
inlinable = false;
|
inlinable = false;
|
||||||
|
@ -481,6 +490,17 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
|
||||||
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
|
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
|
||||||
inlinable = false;
|
inlinable = false;
|
||||||
}
|
}
|
||||||
|
/* If explicit optimize attribute are not used, the mismatch is caused
|
||||||
|
by different command line options used to build different units.
|
||||||
|
Do not care about COMDAT functions - those are intended to be
|
||||||
|
optimized with the optimization flags of module they are used in.
|
||||||
|
Also do not care about mixing up size/speed optimization when
|
||||||
|
DECL_DISREGARD_INLINE_LIMITS is set. */
|
||||||
|
else if ((callee->merged
|
||||||
|
&& !lookup_attribute ("optimize",
|
||||||
|
DECL_ATTRIBUTES (caller->decl)))
|
||||||
|
|| DECL_DISREGARD_INLINE_LIMITS (callee->decl))
|
||||||
|
;
|
||||||
/* If mismatch is caused by merging two LTO units with different
|
/* If mismatch is caused by merging two LTO units with different
|
||||||
optimizationflags we want to be bit nicer. However never inline
|
optimizationflags we want to be bit nicer. However never inline
|
||||||
if one of functions is not optimized at all. */
|
if one of functions is not optimized at all. */
|
||||||
|
|
Loading…
Reference in New Issue