As said in the other thread - this makes sure we don't perform inlining that might end up generating invalid code. It also preserves user-provided optimize attributes more properly.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2015-01-22 Richard Biener <rguent...@suse.de> * ipa-inline.c (can_inline_edge_p): Disable inlining of edges with IL incompatible options. Properly honor user optimize attributes. Index: gcc/ipa-inline.c =================================================================== --- gcc/ipa-inline.c (revision 219929) +++ gcc/ipa-inline.c (working copy) @@ -404,17 +404,56 @@ can_inline_edge_p (struct cgraph_edge *e optimization attribute. */ else if (caller_tree != callee_tree) { - /* gcc.dg/pr43564.c. Look at forced inline even in -O0. */ - if (DECL_DISREGARD_INLINE_LIMITS (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 (e->caller->decl, flag_strict_overflow) + != opt_for_fn (e->caller->decl, flag_strict_overflow)) + || (opt_for_fn (e->caller->decl, flag_wrapv) + != opt_for_fn (e->caller->decl, flag_wrapv)) + || (opt_for_fn (e->caller->decl, flag_trapv) + != opt_for_fn (e->caller->decl, flag_trapv)) + /* Strictly speaking only when the callee contains memory + accesses that are not using alias-set zero anyway. */ + || (opt_for_fn (e->caller->decl, flag_strict_aliasing) + != opt_for_fn (e->caller->decl, flag_strict_aliasing)) + /* Strictly speaking only when the callee uses FP math. */ + || (opt_for_fn (e->caller->decl, flag_rounding_math) + != opt_for_fn (e->caller->decl, flag_rounding_math)) + || (opt_for_fn (e->caller->decl, flag_trapping_math) + != opt_for_fn (e->caller->decl, flag_trapping_math)) + || (opt_for_fn (e->caller->decl, flag_unsafe_math_optimizations) + != opt_for_fn (e->caller->decl, flag_unsafe_math_optimizations)) + || (opt_for_fn (e->caller->decl, flag_finite_math_only) + != opt_for_fn (e->caller->decl, flag_finite_math_only)) + || (opt_for_fn (e->caller->decl, flag_signaling_nans) + != opt_for_fn (e->caller->decl, flag_signaling_nans)) + || (opt_for_fn (e->caller->decl, flag_cx_limited_range) + != opt_for_fn (e->caller->decl, flag_cx_limited_range)) + || (opt_for_fn (e->caller->decl, flag_signed_zeros) + != opt_for_fn (e->caller->decl, flag_signed_zeros)) + || (opt_for_fn (e->caller->decl, flag_associative_math) + != opt_for_fn (e->caller->decl, flag_associative_math)) + || (opt_for_fn (e->caller->decl, flag_reciprocal_math) + != opt_for_fn (e->caller->decl, flag_reciprocal_math)) + /* Strictly speaking only when the callee contains function + calls that may end up setting errno. */ + || (opt_for_fn (e->caller->decl, flag_errno_math) + != opt_for_fn (e->caller->decl, flag_errno_math))) + { + 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))) ; - /* When user added an attribute, honnor it. */ - else if ((lookup_attribute ("optimize", DECL_ATTRIBUTES (caller->decl)) - || lookup_attribute ("optimize", - DECL_ATTRIBUTES (callee->decl))) - && ((opt_for_fn (caller->decl, optimize) - > opt_for_fn (callee->decl, optimize)) - || (opt_for_fn (caller->decl, optimize_size) - != opt_for_fn (callee->decl, optimize_size)))) + /* When user added an attribute to the callee honor it. */ + else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl)) + && opts_for_fn (caller->decl) != opts_for_fn (callee->decl)) { e->inline_failed = CIF_OPTIMIZATION_MISMATCH; inlinable = false;