aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr31115.c22
-rw-r--r--gcc/tree-vrp.c20
4 files changed, 55 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d26d9be..c665941 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ac53f61..886bc4e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..1395a34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr31115.c
@@ -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();
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d3fd911..b137628 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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);