On Mon, 17 Jul 2017, Alexander Monakov wrote: > On Mon, 17 Jul 2017, Marc Glisse wrote: > > > +/* Combine successive multiplications. Similar to above, but handling > > > + overflow is different. */ > > > +(simplify > > > + (mult (mult @0 INTEGER_CST@1) INTEGER_CST@2) > > > + (with { > > > + bool overflow_p; > > > + wide_int mul = wi::mul (@1, @2, TYPE_SIGN (type), &overflow_p); > > > + } > > > + (if (!overflow_p || TYPE_OVERFLOW_WRAPS (type)) > > > > I wonder if there are cases where this would cause trouble for saturating > > integers. The only case I can think of is when @2 is -1, but that's likely > > simplified to NEGATE_EXPR first. > > Ah, yes, I think if @2 is -1 or 0 then we should not attempt this transform > for > either saturating or sanitized types, just like in the first patch. I think > wrapping the 'with' with 'if (!integer_minus_onep (@2) && !integer_zerop > (@2))' > works, since as you say it should become a negate/zero anyway?
Updated patch: * match.pd ((X * CST1) * CST2): Simplify to X * (CST1 * CST2). testsuite: * gcc.dg/tree-ssa/assoc-2.c: Enhance. * gcc.dg/tree-ssa/slsr-4.c: Adjust. diff --git a/gcc/match.pd b/gcc/match.pd index 36045f1..0bb5541 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -283,6 +283,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) || mul != wi::min_value (TYPE_PRECISION (type), SIGNED)) { build_zero_cst (type); }))))) +/* Combine successive multiplications. Similar to above, but handling + overflow is different. */ +(simplify + (mult (mult @0 INTEGER_CST@1) INTEGER_CST@2) + /* More specific rules can handle 0 and -1; skip them here to avoid + wrong transformations for sanitized and saturating types. */ + (if (!integer_zerop (@2) && !integer_minus_onep (@2)) + (with { + bool overflow_p; + wide_int mul = wi::mul (@1, @2, TYPE_SIGN (type), &overflow_p); + } + (if (!overflow_p || TYPE_OVERFLOW_WRAPS (type)) + (mult @0 { wide_int_to_tree (type, mul); }))))) + /* Optimize A / A to 1.0 if we don't care about NaNs or Infinities. */ (simplify diff --git a/gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c b/gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c index a92c882..cc0e9d4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c @@ -5,4 +5,15 @@ int f0(int a, int b){ return a * 33 * b * 55; } -/* { dg-final { scan-tree-dump-times "mult_expr" 2 "gimple" } } */ +int f1(int a){ + a *= 33; + return a * 55; +} + +int f2(int a, int b){ + a *= 33; + return a * b * 55; +} + +/* { dg-final { scan-tree-dump-times "mult_expr" 7 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "mult_expr" 5 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c index 17d7b4c..1e943b7 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c @@ -23,13 +23,9 @@ f (int i) foo (y); } -/* { dg-final { scan-tree-dump-times "\\* 4" 1 "slsr" } } */ -/* { dg-final { scan-tree-dump-times "\\* 10" 1 "slsr" } } */ -/* { dg-final { scan-tree-dump-times "\\+ 20;" 1 "slsr" } } */ +/* { dg-final { scan-tree-dump-times "\\* 40" 1 "slsr" } } */ /* { dg-final { scan-tree-dump-times "\\+ 200" 1 "slsr" } } */ -/* { dg-final { scan-tree-dump-times "\\- 16;" 1 "slsr" } } */ /* { dg-final { scan-tree-dump-times "\\- 160" 1 "slsr" } } */ -/* { dg-final { scan-tree-dump-times "\\* 4" 1 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "\\* 10" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\\* 40" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "\\+ 200" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "\\+ 40" 1 "optimized" } } */