Hi! The following testcase is miscompiled (to endless loop), because union_ranges didn't count with the possibility that *vr0max and vr1max are uncomparable (one of them is symbolic).
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, preapproved by richi on IRC, committed to trunk/4.8. 2013-12-02 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/59358 * tree-vrp.c (union_ranges): To check for the partially overlapping ranges or adjacent ranges, also compare *vr0max with vr1max. * gcc.c-torture/execute/pr59358.c: New test. --- gcc/tree-vrp.c.jj 2013-11-28 23:51:58.000000000 +0100 +++ gcc/tree-vrp.c 2013-12-02 13:24:10.750956769 +0100 @@ -7758,7 +7758,8 @@ union_ranges (enum value_range_type *vr0 } else if ((operand_less_p (vr1min, *vr0max) == 1 || operand_equal_p (vr1min, *vr0max, 0)) - && operand_less_p (*vr0min, vr1min) == 1) + && operand_less_p (*vr0min, vr1min) == 1 + && operand_less_p (*vr0max, vr1max) == 1) { /* [ ( ] ) or [ ]( ) */ if (*vr0type == VR_RANGE @@ -7792,7 +7793,8 @@ union_ranges (enum value_range_type *vr0 } else if ((operand_less_p (*vr0min, vr1max) == 1 || operand_equal_p (*vr0min, vr1max, 0)) - && operand_less_p (vr1min, *vr0min) == 1) + && operand_less_p (vr1min, *vr0min) == 1 + && operand_less_p (vr1max, *vr0max) == 1) { /* ( [ ) ] or ( )[ ] */ if (*vr0type == VR_RANGE --- gcc/testsuite/gcc.c-torture/execute/pr59358.c.jj 2013-12-02 13:26:33.984198815 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr59358.c 2013-12-02 13:26:17.000000000 +0100 @@ -0,0 +1,44 @@ +/* PR tree-optimization/59358 */ + +__attribute__((noinline, noclone)) int +foo (int *x, int y) +{ + int z = *x; + if (y > z && y <= 16) + while (y > z) + z *= 2; + return z; +} + +int +main () +{ + int i; + for (i = 1; i < 17; i++) + { + int j = foo (&i, 16); + int k; + if (i >= 8 && i <= 15) + k = 16 + (i - 8) * 2; + else if (i >= 4 && i <= 7) + k = 16 + (i - 4) * 4; + else if (i == 3) + k = 24; + else + k = 16; + if (j != k) + __builtin_abort (); + j = foo (&i, 7); + if (i >= 7) + k = i; + else if (i >= 4) + k = 8 + (i - 4) * 2; + else if (i == 3) + k = 12; + else + k = 8; + if (j != k) + __builtin_abort (); + } + return 0; +} Jakub