As the PR observes, if the first operand of a right shift is 0 or -1, operand 2 doesn't matter and the result will be the same as op1, so it can be turned into a copy.

This patch checks for that condition and performs the operation in EVRP.

Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.

Andrew

commit f0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Thu Oct 14 10:43:58 2021 -0400

    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.

diff --git a/gcc/testsuite/gcc.dg/pr102738.c b/gcc/testsuite/gcc.dg/pr102738.c
new file mode 100644
index 00000000000..776fcecb27a
--- /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 9bf58f416f2..d0f7cb41bc8 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;
 	}

Reply via email to