[PR102546] X << Y being non-zero implies X is also non-zero.
authorAldy Hernandez <aldyh@redhat.com>
Fri, 1 Oct 2021 11:05:36 +0000 (13:05 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Fri, 1 Oct 2021 22:03:23 +0000 (00:03 +0200)
This patch teaches this to range-ops.

Tested on x86-64 Linux.

gcc/ChangeLog:

PR tree-optimization/102546
* range-op.cc (operator_lshift::op1_range): Teach range-ops that
X << Y is non-zero implies X is also non-zero.

gcc/range-op.cc
gcc/testsuite/gcc.dg/tree-ssa/pr102546.c [new file with mode: 0644]

index 5e37133..2baca4a 100644 (file)
@@ -2078,6 +2078,12 @@ operator_lshift::op1_range (irange &r,
                            relation_kind rel ATTRIBUTE_UNUSED) const
 {
   tree shift_amount;
+
+  if (!lhs.contains_p (build_zero_cst (type)))
+    r.set_nonzero (type);
+  else
+    r.set_varying (type);
+
   if (op2.singleton_p (&shift_amount))
     {
       wide_int shift = wi::to_wide (shift_amount);
@@ -2089,21 +2095,24 @@ operator_lshift::op1_range (irange &r,
        return false;
       if (shift == 0)
        {
-         r = lhs;
+         r.intersect (lhs);
          return true;
        }
 
       // Work completely in unsigned mode to start.
       tree utype = type;
+      int_range_max tmp_range;
       if (TYPE_SIGN (type) == SIGNED)
        {
          int_range_max tmp = lhs;
          utype = unsigned_type_for (type);
          range_cast (tmp, utype);
-         op_rshift.fold_range (r, utype, tmp, op2);
+         op_rshift.fold_range (tmp_range, utype, tmp, op2);
        }
       else
-       op_rshift.fold_range (r, utype, lhs, op2);
+       op_rshift.fold_range (tmp_range, utype, lhs, op2);
+
+      r.intersect (tmp_range);
 
       // Start with ranges which can produce the LHS by right shifting the
       // result by the shift amount.
@@ -2128,7 +2137,8 @@ operator_lshift::op1_range (irange &r,
        range_cast (r, type);
       return true;
     }
-  return false;
+
+  return !r.varying_p ();
 }
 
 bool
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
new file mode 100644 (file)
index 0000000..4bd9874
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-O3 -fdump-tree-optimized" }
+
+static int a;
+static char b, c, d;
+void bar(void);
+void foo(void);
+
+int main() {
+    int f = 0;
+    for (; f <= 5; f++) {
+        bar();
+        b = b && f;
+        d = f << f;
+        if (!(a >= d || f))
+            foo();
+        c = 1;
+        for (; c; c = 0)
+            ;
+    }
+}
+
+// { dg-final { scan-tree-dump-not "foo" "optimized" } }