re PR ipa/65873 (Failure to inline always_inline memcpy)
authorJan Hubicka <hubicka@ucw.cz>
Wed, 13 May 2015 02:54:50 +0000 (04:54 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 13 May 2015 02:54:50 +0000 (02:54 +0000)
PR ipa/65873
* ipa-inline.c (can_inline_edge_p): Allow early inlining of always
inlines across optimization boundary.

From-SVN: r223107

gcc/ChangeLog
gcc/ipa-inline.c

index 10b8fdd7490288cffbe5850f611a83840b0a0450..3da39da22e50a43ab73f1db7fb94bee2a60ba74a 100644 (file)
@@ -1,3 +1,9 @@
+2015-05-12  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/65873
+       * ipa-inline.c (can_inline_edge_p): Allow early inlining of always
+       inlines across optimization boundary.
+
 2015-05-12  Jason Merrill  <jason@redhat.com>
 
        * config/mmix/mmix.c, config/msp430/msp430.c: Add space between
index 017f3a50090246ff40a2f9b20a7c4ee64de336f8..7fd2374bc52962d10ee410c266179a4eee574ed1 100644 (file)
@@ -427,46 +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 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;
@@ -481,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.  */