Message ID | alpine.LSU.2.11.1501221023100.12482@zhemvz.fhfr.qr |
---|---|
State | New |
Headers | show |
> > 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 <rguenther@suse.de> > > * ipa-inline.c (can_inline_edge_p): Disable inlining of edges > with IL incompatible options. Properly honor user optimize > attributes. Thanks, in fact I had similar patch in queue, just wanted to catch you on IRC and discuss posibility of making this a flag in common.opt Honza > > 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;
On Thu, 22 Jan 2015, Jan Hubicka wrote: > > > > 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 <rguenther@suse.de> > > > > * ipa-inline.c (can_inline_edge_p): Disable inlining of edges > > with IL incompatible options. Properly honor user optimize > > attributes. > > Thanks, in fact I had similar patch in queue, just wanted to catch you on IRC > and discuss posibility of making this a flag in common.opt Sure - I briefly considered this but we're in stage4 now so I was just fixing the obvious correctness issues. We also have to fix /* Don't inline if the callee can throw non-call exceptions but the caller cannot. FIXME: this is obviously wrong for LTO where STRUCT_FUNCTION is missing. Move the flag into cgraph node or mirror it in the inline summary. */ else if (callee_fun && callee_fun->can_throw_non_call_exceptions && !(caller_fun && caller_fun->can_throw_non_call_exceptions)) { e->inline_failed = CIF_NON_CALL_EXCEPTIONS; inlinable = false; } in some way (eventually we can just use opt_for_fn ()->flag_non_call_exceptions). Richard. > Honza > > > > 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; > >
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;