Hi, This is a followup to https://gcc.gnu.org/ml/gcc-patches/2017-05/msg01545.html
Recently due to a fix for PR 80800 GCC has lost the ability to reassociate signed multiplications chains to go from 'X * CST1 * Y * CST2' to 'X * Y * (CST1 * CST2)'. The fix to that PR prevents extract_muldiv from introducing '(X * (CST1 * CST2)) * Y', which was wrong because it may cause intermediate signed overflow (unexpected if Y == 0). As mentioned in that thread, we can reassociate constants to outermost operands instead: this is safe because CST1 cannot be 0 or -1, since those are handled by other match.pd rules. (in fact it's possible to reassociate negates too, and go from '(-X) * Y * CST' to '(X * Y) * (-CST)' if (-CST) doesn't overflow (again, we know that CST != 1), but I'm not sure how valuable that is in practice, so opted not to do that yet) The following patch reinstates folding by adding a new match.pd rule that moves constants to outermost operands, where they can be merged by fold_binary machinery if their product doesn't overflow. Bootstrapped and regtested on amd64, OK for trunk? * match.pd ((X * CST) * Y): Reassociate to (X * Y) * CST. diff --git a/gcc/match.pd b/gcc/match.pd index 4c64b21..e49f879 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2139,6 +2139,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (mult @0 integer_minus_onep) (negate @0)) +/* Reassociate (X * CST) * Y to (X * Y) * CST. This does not introduce + signed overflow: previous rules handle CST being -1 or 0, and for + the rest we know that if X * Y overflows, so does (X * CST) * Y. */ +(if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_SATURATING (type)) + (simplify + (mult:c (mult @0 INTEGER_CST@1) @2) + (if (TREE_CODE (@2) != INTEGER_CST) + (mult (mult @0 @2) @1)))) + /* True if we can easily extract the real and imaginary parts of a complex number. */ (match compositional_complex