Hi! With -fwrapv the range test optimization miscompiles the following testcase (both inter-bb version in 4.8+ in first function and the pure fold-const.c one since 3.4). The problem is that with -fwrapv and signed type -x in [-,b] doesn't imply x in [-b,-] and -x in [a,-] doesn't imply x in [-,-a], as -INT_MIN is INT_MIN and thus if INT_MIN was in the range, after negation it needs to be in the range too (and similarly if it wasn't, it can't be there). Turns out that if we make sure both low and high are non-NULL (i.e. replace - with INT_MIN resp. INT_MAX), normalize: will do the right thing that it does also for unsigned operation - if it detects the high bound is lower than low bound, it adjusts the range by inverting it.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk (what about 4.7 where bar is miscompiled too)? Perhaps for PLUS_EXPR/MINUS_EXPR and signed -fwrapv type we could do the same instead of return NULL_TREE; that we do right now (added by Kazu for PR23518). 2012-11-08 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/55236 * fold-const.c (make_range_step) <case NEGATE_EXPR>: For -fwrapv and signed ARG0_TYPE, force low and high to be non-NULL. * gcc.dg/pr55236.c: New test. --- gcc/fold-const.c.jj 2012-11-07 11:24:34.000000000 +0100 +++ gcc/fold-const.c 2012-11-08 16:54:38.978339040 +0100 @@ -3880,6 +3880,17 @@ make_range_step (location_t loc, enum tr return arg0; case NEGATE_EXPR: + /* If flag_wrapv and ARG0_TYPE is signed, make sure + low and high are non-NULL, then normalize will DTRT. */ + if (!TYPE_UNSIGNED (arg0_type) + && !TYPE_OVERFLOW_UNDEFINED (arg0_type)) + { + if (low == NULL_TREE) + low = TYPE_MIN_VALUE (arg0_type); + if (high == NULL_TREE) + high = TYPE_MAX_VALUE (arg0_type); + } + /* (-x) IN [a,b] -> x in [-b, -a] */ n_low = range_binop (MINUS_EXPR, exp_type, build_int_cst (exp_type, 0), --- gcc/testsuite/gcc.dg/pr55236.c.jj 2012-11-08 16:40:49.171781137 +0100 +++ gcc/testsuite/gcc.dg/pr55236.c 2012-11-08 16:41:20.044578919 +0100 @@ -0,0 +1,31 @@ +/* PR tree-optimization/55236 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fwrapv" } */ + +extern void abort (); + +__attribute__((noinline, noclone)) void +foo (int i) +{ + if (i > 0) + abort (); + i = -i; + if (i < 0) + return; + abort (); +} + +__attribute__((noinline, noclone)) void +bar (int i) +{ + if (i > 0 || (-i) >= 0) + abort (); +} + +int +main () +{ + foo (-__INT_MAX__ - 1); + bar (-__INT_MAX__ - 1); + return 0; +} Jakub