From 13338552e20fc9327a4bf620715939db13c23ba6 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Sun, 11 Mar 2007 16:08:35 +0000 Subject: [PATCH] re PR middle-end/31115 (libstdc++ 22_locale/num_get/get/char/2.cc 27_io/basic_ostream/inserters_arithmetic/char/6.cc) 2007-03-11 Richard Guenther 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 | 9 +++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr31115.c | 22 ++++++++++++++++++++++ gcc/tree-vrp.c | 20 +++++++++++++++++++- 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr31115.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d26d9bec7a6..c6659410339 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2007-03-11 Richard Guenther + + 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 * tree-vrp.c (vrp_int_const_binop): Handle PLUS_EXPR and diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ac53f61749d..886bc4ea11e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-03-11 Richard Guenther + + PR tree-optimization/31115 + * gcc.dg/torture/pr31115.c: New testcase. + 2007-03-11 Ira Rosen 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 00000000000..1395a34b322 --- /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 d3fd911dbb1..b137628c975 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);