Hi! If shift count range is [0, 1], then for unsigned LSHIFT_EXPR bound is the topmost bit, but as llshift method always sign-extends the result into double_int, the test don't properly find out that deriving the value range is unsafe. In this case vr0 is [0x7fff8001, 0x80000001], thus when shifting up by 0 or one bit we might shift out either zero or 1.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2013-04-26 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/57083 * tree-vrp.c (extract_range_from_binary_expr_1): For LSHIFT_EXPR with non-singleton shift count range, zero extend low_bound for uns case. * gcc.dg/torture/pr57083.c: New test. --- gcc/tree-vrp.c.jj 2013-04-24 12:07:07.000000000 +0200 +++ gcc/tree-vrp.c 2013-04-26 17:59:41.077938198 +0200 @@ -2837,7 +2837,7 @@ extract_range_from_binary_expr_1 (value_ if (uns) { - low_bound = bound; + low_bound = bound.zext (prec); high_bound = complement.zext (prec); if (tree_to_double_int (vr0.max).ult (low_bound)) { --- gcc/testsuite/gcc.dg/torture/pr57083.c.jj 2013-04-26 18:09:05.396031875 +0200 +++ gcc/testsuite/gcc.dg/torture/pr57083.c 2013-04-26 18:08:51.000000000 +0200 @@ -0,0 +1,15 @@ +/* PR tree-optimization/57083 */ +/* { dg-do run { target int32plus } } */ + +extern void abort (void); +short x = 1; +int y = 0; + +int +main () +{ + unsigned t = (0x7fff8001U - x) << (y == 0); + if (t != 0xffff0000U) + abort (); + return 0; +} Jakub