https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66313
Marek Polacek <mpolacek at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |mpolacek at gcc dot gnu.org --- Comment #2 from Marek Polacek <mpolacek at gcc dot gnu.org> --- Done in this patch. I don't claim it's beautiful, but oh well. diff --git gcc/fold-const.c gcc/fold-const.c index 61eee4a..ce4e989 100644 --- gcc/fold-const.c +++ gcc/fold-const.c @@ -7050,11 +7050,18 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type, } if (same) - return fold_build2_loc (loc, MULT_EXPR, type, - fold_build2_loc (loc, code, type, - fold_convert_loc (loc, type, alt0), - fold_convert_loc (loc, type, alt1)), - fold_convert_loc (loc, type, same)); + { + /* Perform the expression in unsigned type to avoid introducing + undefined behavior, then convert it back to the original type. */ + tree utype = unsigned_type_for (type); + utype = utype ? utype : type; + tree op0 = fold_build2_loc (loc, code, utype, + fold_convert_loc (loc, utype, alt0), + fold_convert_loc (loc, utype, alt1)); + tree op1 = fold_convert_loc (loc, utype, same); + return fold_convert_loc (loc, type, fold_build2_loc (loc, MULT_EXPR, + utype, op0, op1)); + } return NULL_TREE; } diff --git gcc/testsuite/gcc.dg/fold-plusmult-2.c gcc/testsuite/gcc.dg/fold-plusmult-2.c index 82f9898..c74688b 100644 --- gcc/testsuite/gcc.dg/fold-plusmult-2.c +++ gcc/testsuite/gcc.dg/fold-plusmult-2.c @@ -16,4 +16,4 @@ int bar (int i) /* But eventually this to be canonicalized to (i + 2) * 2. */ /* { dg-final { scan-tree-dump "i \\\* 4 \\\+ 2" "original" } } */ -/* { dg-final { scan-tree-dump "\\\(i \\\+ 2\\\) \\\* 2" "original" } } */ +/* { dg-final { scan-tree-dump "i \\\+ 2\\\) \\\* 2" "original" } } */ diff --git gcc/testsuite/gcc.dg/fold-plusmult.c gcc/testsuite/gcc.dg/fold-plusmult.c index 1781552..f30fcbf 100644 --- gcc/testsuite/gcc.dg/fold-plusmult.c +++ gcc/testsuite/gcc.dg/fold-plusmult.c @@ -11,4 +11,4 @@ int test2 (int a) return (a + a)*2; } -/* { dg-final { scan-tree-dump-times "<a> \\\* 4" 2 "original" } } */ +/* { dg-final { scan-tree-dump-times "a.? \\\* 4" 2 "original" } } */