https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92712
--- Comment #17 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Untested patch: --- gcc/match.pd.jj 2019-11-05 14:59:22.546873967 +0100 +++ gcc/match.pd 2019-11-29 18:17:27.472002727 +0100 @@ -2480,18 +2480,42 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (plusminus @0 (mult:c@3 @0 @2)) (if ((!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type) + /* For @0 + @0*@2 this transformation would introduce UB + (where there was none before) for @0 in [-1,0] and @2 max. + For @0 - @0*@2 this transformation would introduce UB + for @0 0 and @2 in [min,min+1] or @0 -1 and @2 min+1. */ || (INTEGRAL_TYPE_P (type) - && tree_expr_nonzero_p (@0) - && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type))))) + && ((tree_expr_nonzero_p (@0) + && expr_not_equal_to (@0, + wi::minus_one (TYPE_PRECISION (type)))) + || (plusminus == PLUS_EXPR + ? expr_not_equal_to (@2, + wi::max_value (TYPE_PRECISION (type), SIGNED)) + /* Let's ignore the @0 -1 and @2 min case. */ + : (expr_not_equal_to (@2, + wi::min_value (TYPE_PRECISION (type), SIGNED)) + && expr_not_equal_to (@2, + wi::min_value (TYPE_PRECISION (type), SIGNED) + + 1)))))) && single_use (@3)) (mult (plusminus { build_one_cst (type); } @2) @0))) (simplify (plusminus (mult:c@3 @0 @2) @0) (if ((!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type) + /* For @0*@2 + @0 this transformation would introduce UB + (where there was none before) for @0 in [-1,0] and @2 max. + For @0*@2 - @0 this transformation would introduce UB + for @0 0 and @2 min. */ || (INTEGRAL_TYPE_P (type) - && tree_expr_nonzero_p (@0) - && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type))))) + && ((tree_expr_nonzero_p (@0) + && (plusminus == MINUS_EXPR + || expr_not_equal_to (@0, + wi::minus_one (TYPE_PRECISION (type))))) + || expr_not_equal_to (@2, + (plusminus == PLUS_EXPR + ? wi::max_value (TYPE_PRECISION (type), SIGNED) + : wi::min_value (TYPE_PRECISION (type), SIGNED)))))) && single_use (@3)) (mult (plusminus @2 { build_one_cst (type); }) @0)))))) This doesn't try to do anything about the A*B+A*C cases. Fixes the #c0 testcase and shows I've screwed up my simplified testcases, the case that is fixed with this patch is e.g. int foo (int t, int v) { int a = t - 1; int b = a * v; return b + v; } where we don't know anything about v (VARYING), but from a = t - 1 we know it is not INT_MAX and can use that in the optimization.