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  <rguent...@suse.de>

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

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().  */

Reply via email to