On Thu, Nov 8, 2012 at 9:04 PM, Jakub Jelinek <ja...@redhat.com> wrote: > 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).
Ok. Thanks, Richard. > 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