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>
* 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",
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
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 ((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 uses FP 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. */
|| (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)))
|| (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. */
|| 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. */
|| (!early && check_maybe_down (flag_devirtualize)))
else 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 uses FP 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. */
|| (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)))
|| (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. */
|| 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. */
|| (!early && check_maybe_down (flag_devirtualize)))
{
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
inlinable = false;
@ -481,6 +490,17 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
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
optimizationflags we want to be bit nicer. However never inline
if one of functions is not optimized at all. */