re PR middle-end/31115 (libstdc++ 22_locale/num_get/get/char/2.cc 27_io/basic_ostream...
authorRichard Guenther <rguenther@suse.de>
Sun, 11 Mar 2007 16:08:35 +0000 (16:08 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sun, 11 Mar 2007 16:08:35 +0000 (16:08 +0000)
2007-03-11  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/31115
* tree-vrp.c (extract_range_from_binary_expr): Make sure
the shift count is positive and non-anti-range for RSHIFT_EXPR.
A shift count of zero is not special as with *_DIV_EXPR.
(vrp_int_const_binop): Handle RSHIFT_EXPR for determining overflow
direction.

* gcc.dg/torture/pr31115.c: New testcase.

From-SVN: r122821

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr31115.c [new file with mode: 0644]
gcc/tree-vrp.c

index d26d9bec7a656fccfcbcfa02fe1ef28c3b252ab4..c6659410339167deaefea1b73f40dae6adeb5c1e 100644 (file)
@@ -1,3 +1,12 @@
+2007-03-11  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/31115
+       * tree-vrp.c (extract_range_from_binary_expr): Make sure
+       the shift count is positive and non-anti-range for RSHIFT_EXPR.
+       A shift count of zero is not special as with *_DIV_EXPR.
+       (vrp_int_const_binop): Handle RSHIFT_EXPR for determining overflow
+       direction.
+
 2007-03-11  Ian Lance Taylor  <iant@google.com>
 
        * tree-vrp.c (vrp_int_const_binop): Handle PLUS_EXPR and
index ac53f61749d7cbfcf485b5d8a58bc0fda730fe20..886bc4ea11e18302419e61af575e21060c633c7f 100644 (file)
@@ -1,3 +1,8 @@
+2007-03-11  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/31115
+       * gcc.dg/torture/pr31115.c: New testcase.
+
 2007-03-11  Ira Rosen  <irar@il.ibm.com>
 
        PR tree-optimization/29925
diff --git a/gcc/testsuite/gcc.dg/torture/pr31115.c b/gcc/testsuite/gcc.dg/torture/pr31115.c
new file mode 100644 (file)
index 0000000..1395a34
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+extern void exit(int);
+extern void abort();
+void foo (int e1)
+{
+  if (e1 < 0)
+    {
+      e1 = -e1;
+      if (e1 >>= 4)
+        {
+          if (e1 >= 1 << 5)
+            exit(0);
+        }
+    }
+}
+
+int main()
+{
+  foo(-(1<<9));
+  abort();
+}
index d3fd911dbb1b6549a9270f5dc03ceab563aa04e8..b137628c975411209ef46cd393cc9122ca68ce40 100644 (file)
@@ -1569,6 +1569,12 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
              && (sgn1 >= 0
                  ? !is_positive_overflow_infinity (val2)
                  : is_negative_overflow_infinity (val2)))
+         /* We only get in here with positive shift count, so the
+            overflow direction is the same as the sign of val1.
+            Actually rshift does not overflow at all, but we only
+            handle the case of shifting overflowed -INF and +INF.  */
+         || (code == RSHIFT_EXPR
+             && sgn1 >= 0)
          /* For division, the only case is -INF / -1 = +INF.  */
          || code == TRUNC_DIV_EXPR
          || code == FLOOR_DIV_EXPR
@@ -1802,6 +1808,17 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
          return;
        }
 
+      /* If we have a RSHIFT_EXPR with a possibly negative shift
+        count or an anti-range shift count drop to VR_VARYING.
+        We currently cannot handle the overflow cases correctly.  */
+      if (code == RSHIFT_EXPR
+         && (vr1.type == VR_ANTI_RANGE
+             || !vrp_expr_computes_nonnegative (op1, &sop)))
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
+
       /* Multiplications and divisions are a bit tricky to handle,
         depending on the mix of signs we have in the two ranges, we
         need to operate on different values to get the minimum and
@@ -1816,7 +1833,8 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
         the new range.  */
 
       /* Divisions by zero result in a VARYING value.  */
-      if (code != MULT_EXPR
+      if ((code != MULT_EXPR
+          && code != RSHIFT_EXPR)
          && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
        {
          set_value_range_to_varying (vr);