recognize implied ranges for modulo.
authorAndrew MacLeod <amacleod@redhat.com>
Tue, 17 Nov 2020 19:47:58 +0000 (14:47 -0500)
committerAndrew MacLeod <amacleod@redhat.com>
Tue, 17 Nov 2020 21:59:48 +0000 (16:59 -0500)
implement op1_range for modulo with implied positive and negative ranges.

gcc/
PR tree-optimization/91029
* range-op.cc (operator_trunc_mod::op1_range): New.
gcc/testsuite/
* gcc.dg/pr91029.c: New.

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

index d0adc95527a5ac2c532fe22ea9cfa912e6153e9f..f37796cac709e062591ee09f304cfe494495a9b3 100644 (file)
@@ -2634,6 +2634,9 @@ public:
                        const wide_int &lh_ub,
                        const wide_int &rh_lb,
                        const wide_int &rh_ub) const;
+  virtual bool op1_range (irange &r, tree type,
+                         const irange &lhs,
+                         const irange &op2) const;
 } op_trunc_mod;
 
 void
@@ -2680,6 +2683,31 @@ operator_trunc_mod::wi_fold (irange &r, tree type,
   value_range_with_overflow (r, type, new_lb, new_ub);
 }
 
+bool
+operator_trunc_mod::op1_range (irange &r, tree type,
+                              const irange &lhs,
+                              const irange &op2) const
+{
+  // PR 91029.  Check for signed truncation with op2 >= 0.
+  if (TYPE_SIGN (type) == SIGNED && wi::ge_p (op2.lower_bound (), 0, SIGNED))
+    {
+      unsigned prec = TYPE_PRECISION (type);
+      // if a & b >=0 , then a >= 0.
+      if (wi::ge_p (lhs.lower_bound (), 0, SIGNED))
+       {
+         r = value_range (type, wi::zero (prec), wi::max_value (prec, SIGNED));
+         return true;
+       }
+      // if a & b < 0 , then a <= 0.
+      if (wi::lt_p (lhs.upper_bound (), 0, SIGNED))
+       {
+         r = value_range (type, wi::min_value (prec, SIGNED), wi::zero (prec));
+         return true;
+       }
+    }
+  return false;
+}
+
 
 class operator_logical_not : public range_operator
 {
diff --git a/gcc/testsuite/gcc.dg/pr91029.c b/gcc/testsuite/gcc.dg/pr91029.c
new file mode 100644 (file)
index 0000000..8a4134c
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void kill (void);
+int xx;
+
+void f1 (int i)
+{
+  if ((i % 7) == 3)
+    {
+      xx = (i < 0);
+      if (xx)
+        kill ();
+    }
+}
+
+void f2 (int i)
+{
+  if ((i % 7) >= 0)
+    {
+      xx = (i < 0);
+      if (xx)
+        kill ();
+    }
+}
+
+void f3 (int i)
+{
+  if ((i % 7) == -3)
+    {
+      xx = (i > 0);
+      if (xx)
+        kill ();
+    }
+}
+
+void f4 (int i)
+{
+  if ((i % 7) < 0)
+    {
+      xx = (i > 0);
+      if (xx)
+        kill ();
+    }
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } }  */