Fix PR84067

Message ID alpine.LSU.2.20.1803271342290.18265@zhemvz.fhfr.qr
State New
Headers show
Series
  • Fix PR84067
Related show

Commit Message

Richard Biener March 27, 2018, 11:44 a.m.
The following guards the fold_plusminus_mult patterns with explicit
single_use checks to avoid regressing gcc.dg/wmul-1.c, that is,
introduction of additional multiplications.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

I've checked with a cross to aarch64 that the FAIL is gone.

Richard.

2018-03-27  Richard Biener  <rguenther@suse.de>

	PR middle-ed/84067
	* match.pd ((A * C) +- (B * C) -> (A+-B) * C): Guard with
	explicit single_use checks.

Patch

Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 258871)
+++ gcc/match.pd	(working copy)
@@ -1948,30 +1948,35 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      && (!FLOAT_TYPE_P (type) || flag_associative_math))
  (for plusminus (plus minus)
   (simplify
-   (plusminus (mult:cs @0 @1) (mult:cs @0 @2))
-   (if (!ANY_INTEGRAL_TYPE_P (type)
-        || TYPE_OVERFLOW_WRAPS (type)
-        || (INTEGRAL_TYPE_P (type)
-	    && tree_expr_nonzero_p (@0)
-	    && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
-    (mult (plusminus @1 @2) @0)))
-  /* We cannot generate constant 1 for fract.  */
-  (if (!ALL_FRACT_MODE_P (TYPE_MODE (type)))
-   (simplify
-    (plusminus @0 (mult:cs @0 @2))
-    (if (!ANY_INTEGRAL_TYPE_P (type)
+   (plusminus (mult:cs@3 @0 @1) (mult:cs@4 @0 @2))
+   (if ((!ANY_INTEGRAL_TYPE_P (type)
 	 || TYPE_OVERFLOW_WRAPS (type)
 	 || (INTEGRAL_TYPE_P (type)
 	     && tree_expr_nonzero_p (@0)
 	     && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+	/* If @1 +- @2 is constant require a hard single-use on either
+	   original operand (but not on both).  */
+	&& (single_use (@3) || single_use (@4)))
+    (mult (plusminus @1 @2) @0)))
+  /* We cannot generate constant 1 for fract.  */
+  (if (!ALL_FRACT_MODE_P (TYPE_MODE (type)))
+   (simplify
+    (plusminus @0 (mult:c@3 @0 @2))
+    (if ((!ANY_INTEGRAL_TYPE_P (type)
+	  || TYPE_OVERFLOW_WRAPS (type)
+	  || (INTEGRAL_TYPE_P (type)
+	      && tree_expr_nonzero_p (@0)
+	      && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+	 && single_use (@3))
      (mult (plusminus { build_one_cst (type); } @2) @0)))
    (simplify
-    (plusminus (mult:cs @0 @2) @0)
-    (if (!ANY_INTEGRAL_TYPE_P (type)
-	 || TYPE_OVERFLOW_WRAPS (type)
-	 || (INTEGRAL_TYPE_P (type)
-	     && tree_expr_nonzero_p (@0)
-	     && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+    (plusminus (mult:c@3 @0 @2) @0)
+    (if ((!ANY_INTEGRAL_TYPE_P (type)
+	  || TYPE_OVERFLOW_WRAPS (type)
+	  || (INTEGRAL_TYPE_P (type)
+	      && tree_expr_nonzero_p (@0)
+	      && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+	 && single_use (@3))
      (mult (plusminus @2 { build_one_cst (type); }) @0))))))
 
 /* Simplifications of MIN_EXPR, MAX_EXPR, fmin() and fmax().  */