- struct cl_optimization *caller_opt
- = TREE_OPTIMIZATION ((caller_tree)
- ? caller_tree
- : optimization_default_node);
-
- struct cl_optimization *callee_opt
- = TREE_OPTIMIZATION ((callee_tree)
- ? callee_tree
- : optimization_default_node);
-
- if (((caller_opt->x_optimize > callee_opt->x_optimize)
- || (caller_opt->x_optimize_size != callee_opt->x_optimize_size))
- /* gcc.dg/pr43564.c. Look at forced inline even in -O0. */
- && !DECL_DISREGARD_INLINE_LIMITS (e->callee->decl))
+ bool always_inline =
+ (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
+ && lookup_attribute ("always_inline",
+ DECL_ATTRIBUTES (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 ((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)))
+ {
+ e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
+ inlinable = false;
+ }
+ /* gcc.dg/pr43564.c. Apply user-forced inline even at -O0. */
+ else if (always_inline)
+ ;
+ /* 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))