From: hubicka Date: Sun, 17 May 2015 17:43:04 +0000 (+0000) Subject: PR ipa/65873 X-Git-Url: https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff_plain;h=fc3632866e34cff032e25db6e71a2bbf09b5b244 PR ipa/65873 * ipa-inline.c (can_inline_edge_p): Allow early inlining of always inlines across optimization boundary; be tolerant about COMDAT; allow inlining across -fstrict-aliasing boundary. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-5-branch@223270 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 4533ea4..7097cf3 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -427,49 +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 contains memory - accesses that are not using alias-set zero anyway. */ - || check_maybe_down (flag_strict_aliasing) - /* 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; @@ -484,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. */ @@ -515,7 +532,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, else if (opt_for_fn (callee->decl, optimize_size) < opt_for_fn (caller->decl, optimize_size) || (opt_for_fn (callee->decl, optimize) - >= opt_for_fn (caller->decl, optimize))) + > opt_for_fn (caller->decl, optimize))) { if (estimate_edge_time (e) >= 20 + inline_edge_summary (e)->call_stmt_time)