diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2021-10-14 10:43:58 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2021-10-14 13:56:37 -0400 |
commit | f0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0 (patch) | |
tree | 71c7d4f4e47be4d9c5dd632be114c68d99fc8091 | |
parent | 2c4666fb0686a8f5a55821f1527351dc71c018b4 (diff) | |
download | gcc-f0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0.zip gcc-f0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0.tar.gz gcc-f0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0.tar.bz2 |
Simplification for right shift.
When the first operand of a signed right shift is zero or negative one, the
RHS doesn't matter and the shift can be converted to a copy.
PR tree-optimization/102738
gcc/
* vr-values.c (simplify_using_ranges::simplify): Handle RSHIFT_EXPR.
gcc/testsuite
* gcc.dg/pr102738.c: New.
-rw-r--r-- | gcc/testsuite/gcc.dg/pr102738.c | 48 | ||||
-rw-r--r-- | gcc/vr-values.c | 22 |
2 files changed, 70 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/pr102738.c b/gcc/testsuite/gcc.dg/pr102738.c new file mode 100644 index 0000000..776fcec --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102738.c @@ -0,0 +1,48 @@ +/* PR tree-optimization/102738 */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +/* Remove arithmetic shift right when the LHS is known to be 0 or -1. */ + +int a1(__int128 f, int g) +{ + /* Leaves f >> 127. */ + return (f >> 127) >> g; +} + +int a2(int f, int g) +{ + /* Leaves f >> 31. */ + return (f >> 31) >> g; +} + +int a3(int f, int g) +{ + if (f == 0 || f == -1) + return f >> g; + __builtin_unreachable(); +} + +int a4(int f, int g) +{ + if (f == 0 || f == 1) + return (-f) >> g; + __builtin_unreachable(); +} + +int a5(int f, int g) +{ + if (f == 0 || f == 1) + return (f-1) >> g; + return 0; +} + +int a6(int f, int g) +{ + if (f == 6 || f == 7) + return (f-7) >> g; + __builtin_unreachable(); +} + +/* { dg-final { scan-tree-dump-times " >> 127" 1 "evrp" } } */ +/* { dg-final { scan-tree-dump-times " >> 31" 1 "evrp" } } */ +/* { dg-final { scan-tree-dump-times " >> " 2 "evrp" } } */ diff --git a/gcc/vr-values.c b/gcc/vr-values.c index 9bf58f4..d0f7cb4 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -4281,6 +4281,28 @@ simplify_using_ranges::simplify (gimple_stmt_iterator *gsi) case MAX_EXPR: return simplify_min_or_max_using_ranges (gsi, stmt); + case RSHIFT_EXPR: + { + tree op0 = gimple_assign_rhs1 (stmt); + tree type = TREE_TYPE (op0); + int_range_max range; + if (TYPE_SIGN (type) == SIGNED + && query->range_of_expr (range, op0, stmt)) + { + unsigned prec = TYPE_PRECISION (TREE_TYPE (op0)); + int_range<2> nzm1 (type, wi::minus_one (prec), wi::zero (prec), + VR_ANTI_RANGE); + range.intersect (nzm1); + // If there are no ranges other than [-1, 0] remove the shift. + if (range.undefined_p ()) + { + gimple_assign_set_rhs_from_tree (gsi, op0); + return true; + } + return false; + } + break; + } default: break; } |