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