diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6fcf9b2ed9b..ca02f822b23 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-01-12 Bin Cheng + + PR tree-optimization/68911 + * tree-vrp.c (adjust_range_with_scev): Check overflow in range + information computed for expression "init + nit * step". + 2016-01-12 Sandra Loosemore * doc/invoke.texi (Invoking GCC): Copy-edit. Incorporate information diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ec887e97505..435ffde8e1b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-01-12 Bin Cheng + + PR tree-optimization/68911 + * gcc.c-torture/execute/pr68911.c: New test. + 2016-01-12 Marek Polacek PR c++/68979 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68911.c b/gcc/testsuite/gcc.c-torture/execute/pr68911.c new file mode 100644 index 00000000000..b8cbdb59289 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr68911.c @@ -0,0 +1,27 @@ +extern void abort (void); + +char a; +int b, c; +short d; + +int main () +{ + unsigned e = 2; + unsigned timeout = 0; + + for (; c < 2; c++) + { + int f = ~e / 7; + if (f) + a = e = ~(b && d); + while (e < 94) + { + e++; + if (++timeout > 100) + goto die; + } + } + return 0; +die: + abort (); +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 920a9b1818d..8f35eb73277 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -4259,6 +4259,27 @@ adjust_range_with_scev (value_range *vr, struct loop *loop, /* Likewise if the addition did. */ if (maxvr.type == VR_RANGE) { + value_range initvr = VR_INITIALIZER; + + if (TREE_CODE (init) == SSA_NAME) + initvr = *(get_value_range (init)); + else if (is_gimple_min_invariant (init)) + set_value_range_to_value (&initvr, init, NULL); + else + return; + + /* Check if init + nit * step overflows. Though we checked + scev {init, step}_loop doesn't wrap, it is not enough + because the loop may exit immediately. Overflow could + happen in the plus expression in this case. */ + if ((dir == EV_DIR_DECREASES + && (is_negative_overflow_infinity (maxvr.min) + || compare_values (maxvr.min, initvr.min) != -1)) + || (dir == EV_DIR_GROWS + && (is_positive_overflow_infinity (maxvr.max) + || compare_values (maxvr.max, initvr.max) != 1))) + return; + tmin = maxvr.min; tmax = maxvr.max; }