ipa-inline.c (check_maybe_up, [...]): New macros.
authorJan Hubicka <hubicka@ucw.cz>
Thu, 26 Mar 2015 23:43:27 +0000 (00:43 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 26 Mar 2015 23:43:27 +0000 (23:43 +0000)
* ipa-inline.c (check_maybe_up, check_maybe_down, check_match):
New macros.
(can_inline_edge_p): Relax option matching for always inline functions.

From-SVN: r221714

gcc/ChangeLog
gcc/ipa-inline.c

index 0d4d17287f247a2ae3c39488c67eccafe6d1a3d2..14cfadca4095e0d41cd81736a3313154c127fec5 100644 (file)
@@ -1,3 +1,9 @@
+2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-inline.c (check_maybe_up, check_maybe_down, check_match):
+       New macros.
+       (can_inline_edge_p): Relax option matching for always inline functions.
+
 2015-03-26  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/65561
index 49af4cec13d55dc1975cf29d7fd836a83f7aa8bd..24b25a0e3189a32a989ed128bfc298be27819095 100644 (file)
@@ -298,6 +298,27 @@ sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee)
       DECL_ATTRIBUTES (callee));
 }
 
+/* Used for flags where it is safe to inline when caller's value is
+   grater than callee's.  */
+#define check_maybe_up(flag) \
+      (opts_for_fn (caller->decl)->x_##flag            \
+       != opts_for_fn (callee->decl)->x_##flag         \
+       && (!always_inline                              \
+          || opts_for_fn (caller->decl)->x_##flag      \
+             < opts_for_fn (callee->decl)->x_##flag))
+/* Used for flags where it is safe to inline when caller's value is
+   smaller than callee's.  */
+#define check_maybe_down(flag) \
+      (opts_for_fn (caller->decl)->x_##flag            \
+       != opts_for_fn (callee->decl)->x_##flag         \
+       && (!always_inline                              \
+          || opts_for_fn (caller->decl)->x_##flag      \
+             > opts_for_fn (callee->decl)->x_##flag))
+/* Used for flags where exact match is needed for correctness.  */
+#define check_match(flag) \
+      (opts_for_fn (caller->decl)->x_##flag            \
+       != opts_for_fn (callee->decl)->x_##flag)
+
  /* Decide if we can inline the edge and possibly update
    inline_failed reason.  
    We check whether inlining is possible at all and whether
@@ -401,74 +422,60 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
      optimization attribute.  */
   else if (caller_tree != callee_tree)
     {
+      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 ((opt_for_fn (caller->decl, flag_strict_overflow)
-          != opt_for_fn (callee->decl, flag_strict_overflow))
-         || (opt_for_fn (caller->decl, flag_wrapv)
-             != opt_for_fn (callee->decl, flag_wrapv))
-         || (opt_for_fn (caller->decl, flag_trapv)
-             != opt_for_fn (callee->decl, flag_trapv))
+      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.  */
-         || (opt_for_fn (caller->decl, flag_strict_aliasing)
-             != opt_for_fn (callee->decl, flag_strict_aliasing))
+         || check_maybe_down (flag_strict_aliasing)
          /* Strictly speaking only when the callee uses FP math.  */
-         || (opt_for_fn (caller->decl, flag_rounding_math)
-             != opt_for_fn (callee->decl, flag_rounding_math))
-         || (opt_for_fn (caller->decl, flag_trapping_math)
-             != opt_for_fn (callee->decl, flag_trapping_math))
-         || (opt_for_fn (caller->decl, flag_unsafe_math_optimizations)
-             != opt_for_fn (callee->decl, flag_unsafe_math_optimizations))
-         || (opt_for_fn (caller->decl, flag_finite_math_only)
-             != opt_for_fn (callee->decl, flag_finite_math_only))
-         || (opt_for_fn (caller->decl, flag_signaling_nans)
-             != opt_for_fn (callee->decl, flag_signaling_nans))
-         || (opt_for_fn (caller->decl, flag_cx_limited_range)
-             != opt_for_fn (callee->decl, flag_cx_limited_range))
-         || (opt_for_fn (caller->decl, flag_signed_zeros)
-             != opt_for_fn (callee->decl, flag_signed_zeros))
-         || (opt_for_fn (caller->decl, flag_associative_math)
-             != opt_for_fn (callee->decl, flag_associative_math))
-         || (opt_for_fn (caller->decl, flag_reciprocal_math)
-             != opt_for_fn (callee->decl, flag_reciprocal_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.  */
-         || (opt_for_fn (caller->decl, flag_non_call_exceptions)
-             != opt_for_fn (callee->decl, flag_non_call_exceptions)
+         || (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)))
-         || (!opt_for_fn (caller->decl, flag_exceptions)
-             && opt_for_fn (callee->decl, flag_exceptions)
+         || (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.  */
-         || (opt_for_fn (caller->decl, flag_errno_math)
-             != opt_for_fn (callee->decl, flag_errno_math))
+         || 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.  */
-         || (opt_for_fn (caller->decl, flag_devirtualize)
-             && !opt_for_fn (callee->decl, flag_devirtualize)
-             && (!early
-                 || (!DECL_DISREGARD_INLINE_LIMITS (callee->decl)
-                     || !lookup_attribute ("always_inline",
-                                           DECL_ATTRIBUTES (callee->decl))))))
+         || (!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 (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
-              && lookup_attribute ("always_inline",
-                                   DECL_ATTRIBUTES (callee->decl)))
+      else if (always_inline)
        ;
       /* When user added an attribute to the callee honor it.  */
       else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))