Fix option andling in can_inline_edge_p

Jan Hubicka hubicka@ucw.cz
Sun Mar 1 00:57:00 GMT 2015


hi,
this patch fixes bug in can_inline_edge_p where opt_for_fn is taken from
inline clone and not function being inlined into itself.  Those opt_for_fn
are going to be ignored and thus have no meaning.

I also fixed case wehre !flag_devirtualize would get inlined into
flag_devirtualize but at WPA time we possibly made changes clobbering type
information.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

	* ipa-inline.c (can_inline_edge_p): Match opt_for_fn on inline
	target; also match flag_ipa_devirt.
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 221076)
+++ ipa-inline.c	(working copy)
@@ -310,7 +310,7 @@ sanitize_attrs_match_for_inline_p (const
 
 static bool
 can_inline_edge_p (struct cgraph_edge *e, bool report,
-		   bool disregard_limits = false)
+		   bool disregard_limits = false, bool early = false)
 {
   bool inlinable = true;
   enum availability avail;
@@ -409,39 +409,48 @@ can_inline_edge_p (struct cgraph_edge *e
 	 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))
+      if ((opt_for_fn (caller->decl, flag_strict_overflow)
+	   != opt_for_fn (caller->decl, flag_strict_overflow))
+	  || (opt_for_fn (caller->decl, flag_wrapv)
+	      != opt_for_fn (caller->decl, flag_wrapv))
+	  || (opt_for_fn (caller->decl, flag_trapv)
+	      != opt_for_fn (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))
+	  || (opt_for_fn (caller->decl, flag_strict_aliasing)
+	      != opt_for_fn (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))
+	  || (opt_for_fn (caller->decl, flag_rounding_math)
+	      != opt_for_fn (caller->decl, flag_rounding_math))
+	  || (opt_for_fn (caller->decl, flag_trapping_math)
+	      != opt_for_fn (caller->decl, flag_trapping_math))
+	  || (opt_for_fn (caller->decl, flag_unsafe_math_optimizations)
+	      != opt_for_fn (caller->decl, flag_unsafe_math_optimizations))
+	  || (opt_for_fn (caller->decl, flag_finite_math_only)
+	      != opt_for_fn (caller->decl, flag_finite_math_only))
+	  || (opt_for_fn (caller->decl, flag_signaling_nans)
+	      != opt_for_fn (caller->decl, flag_signaling_nans))
+	  || (opt_for_fn (caller->decl, flag_cx_limited_range)
+	      != opt_for_fn (caller->decl, flag_cx_limited_range))
+	  || (opt_for_fn (caller->decl, flag_signed_zeros)
+	      != opt_for_fn (caller->decl, flag_signed_zeros))
+	  || (opt_for_fn (caller->decl, flag_associative_math)
+	      != opt_for_fn (caller->decl, flag_associative_math))
+	  || (opt_for_fn (caller->decl, flag_reciprocal_math)
+	      != opt_for_fn (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)))
+	  || (opt_for_fn (caller->decl, flag_errno_math)
+	      != opt_for_fn (caller->decl, 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))))))
 	{
 	  e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
 	  inlinable = false;
@@ -532,7 +541,7 @@ can_early_inline_edge_p (struct cgraph_e
 	fprintf (dump_file, "  edge not inlinable: not in SSA form\n");
       return false;
     }
-  if (!can_inline_edge_p (e, true))
+  if (!can_inline_edge_p (e, true, false, true))
     return false;
   return true;
 }



More information about the Gcc-patches mailing list