aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2021-10-14 10:43:58 -0400
committerAndrew MacLeod <amacleod@redhat.com>2021-10-14 13:56:37 -0400
commitf0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0 (patch)
tree71c7d4f4e47be4d9c5dd632be114c68d99fc8091
parent2c4666fb0686a8f5a55821f1527351dc71c018b4 (diff)
downloadgcc-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.c48
-rw-r--r--gcc/vr-values.c22
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;
}