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:
Jan Hubicka 2015-05-13 04:54:50 +02:00 committed by Jan Hubicka
parent fe1814cf84
commit ddb3773a12
2 changed files with 61 additions and 35 deletions

View File

@ -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

View File

@ -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. */