diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2021-07-29 11:22:28 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2021-07-30 15:10:49 -0400 |
commit | 145bc41dae7c7bfa093d61e77346f98e6a595a0e (patch) | |
tree | b6aa0a6a9a985dabf305c65bd12a2d9a82f19493 | |
parent | ebbcdd7fae1f802763850e4afedfdfa09cf10e1a (diff) | |
download | gcc-145bc41dae7c7bfa093d61e77346f98e6a595a0e.zip gcc-145bc41dae7c7bfa093d61e77346f98e6a595a0e.tar.gz gcc-145bc41dae7c7bfa093d61e77346f98e6a595a0e.tar.bz2 |
Handle constants in wi_fold for trunc_mod.
Handle const % const, as wi_fold_in_parts may now provide this. Before this
[10, 10] % [4, 4] would produce [0, 3] instead of [2, 2].
gcc/
* range-op.cc (operator_trunc_mod::wi_fold): Fold constants.
gcc/testsuite/
* gcc.dg/tree-ssa/pr61839_2.c: Adjust. Add new const fold test.
-rw-r--r-- | gcc/range-op.cc | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c | 39 |
2 files changed, 47 insertions, 4 deletions
diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 6922888..eb66e12 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -3240,6 +3240,18 @@ operator_trunc_mod::wi_fold (irange &r, tree type, return; } + // Check for constant and try to fold. + if (lh_lb == lh_ub && rh_lb == rh_ub) + { + wi::overflow_type ov = wi::OVF_NONE; + tmp = wi::mod_trunc (lh_lb, rh_lb, sign, &ov); + if (ov == wi::OVF_NONE) + { + r = int_range<2> (type, tmp, tmp); + return; + } + } + // ABS (A % B) < ABS (B) and either 0 <= A % B <= A or A <= A % B <= 0. new_ub = rh_ub - 1; if (sign == SIGNED) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c index f1b8feb..0e0f4c0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c @@ -45,9 +45,40 @@ int bar2 () return 0; } -/* Dont optimize 972195717 / 0 in function foo. */ +/* Ensure we are folding modulus sub-ranges properly. */ +__attribute__ ((noinline)) +int mod (int a, int b) +{ + int v1, v2; + v1 = (a < 10) ? 12 : 24; + v2 = (b > 20) ? 3 : 6; + + if (a > 20) + v1 = v1 * 2; + if (b > 20) + v2 = v2 * 2; + + if (a == b) + v2 = 0; + + /* v1 == 12, 24, or 48. v2 == 0, 3, 6, or 12. */ + int c = v1 % v2; + if (c == 0) + ; + else + __builtin_abort (); + return 0; +} + +/* EVRP now makes transformations in all functions, leaving a single + * builtin_abort call in bar2. */ +/* { dg-final { scan-tree-dump-times "__builtin_abort" 1 "evrp" } } */ + +/* Make sure to optimize 972195717 / 0 in function foo. */ /* { dg-final { scan-tree-dump-times "972195717 / " 0 "evrp" } } */ -/* Dont optimize 972195717 % 0 in function bar. */ -/* { dg-final { scan-tree-dump-times "972195717 % " 1 "evrp" } } */ -/* May optimize in function bar2, but EVRP doesn't perform this yet. */ +/* Make sure to optimize 972195717 % 0 in function bar. */ +/* { dg-final { scan-tree-dump-times "972195717 % " 0 "evrp" } } */ +/* Make sure to optimize 972195717 % [1,2] function bar2. */ /* { dg-final { scan-tree-dump-times "972195715 % " 0 "evrp" } } */ +/* [12,12][24,24][48,48] % [0,0][3,3][6,6][12,12] == [0,0] */ +/* { dg-final { scan-tree-dump-times "%" 0 "evrp" } } */ |