Message ID | 20130208142032.GN4385@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
On Fri, 8 Feb 2013, Jakub Jelinek wrote: > Hi! > > As the testcase shows, treating (-something_unsigned) / c as > -(something_unsigned / c) is wrong for unsigned types, seems to be > fine for signed types even for -fwrapv and for multiplication > instead of / or % looks fine to me too. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Ok. Thanks, Richard. > 2013-02-08 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/56250 > * fold-const.c (extract_muldiv_1) <case NEGATE_EXPR>: Don't optimize > if type is unsigned and code isn't MULT_EXPR. > > * gcc.c-torture/execute/pr56250.c: New test. > > --- gcc/fold-const.c.jj 2013-02-01 16:00:23.000000000 +0100 > +++ gcc/fold-const.c 2013-02-08 11:58:07.063147647 +0100 > @@ -5695,6 +5695,11 @@ extract_muldiv_1 (tree t, tree c, enum t > break; > /* FALLTHROUGH */ > case NEGATE_EXPR: > + /* For division and modulus, type can't be unsigned, as e.g. > + (-(x / 2U)) / 2U isn't equal to -((x / 2U) / 2U) for x >= 2. > + For signed types, even with wrapping overflow, this is fine. */ > + if (code != MULT_EXPR && TYPE_UNSIGNED (type)) > + break; > if ((t1 = extract_muldiv (op0, c, code, wide_type, strict_overflow_p)) > != 0) > return fold_build1 (tcode, ctype, fold_convert (ctype, t1)); > --- gcc/testsuite/gcc.c-torture/execute/pr56250.c.jj 2013-02-08 12:12:43.477013120 +0100 > +++ gcc/testsuite/gcc.c-torture/execute/pr56250.c 2013-02-08 11:58:20.000000000 +0100 > @@ -0,0 +1,13 @@ > +/* PR tree-optimization/56250 */ > + > +extern void abort (void); > + > +int > +main () > +{ > + unsigned int x = 2; > + unsigned int y = (0U - x / 2) / 2; > + if (-1U / x != y) > + abort (); > + return 0; > +} > > Jakub > >
--- gcc/fold-const.c.jj 2013-02-01 16:00:23.000000000 +0100 +++ gcc/fold-const.c 2013-02-08 11:58:07.063147647 +0100 @@ -5695,6 +5695,11 @@ extract_muldiv_1 (tree t, tree c, enum t break; /* FALLTHROUGH */ case NEGATE_EXPR: + /* For division and modulus, type can't be unsigned, as e.g. + (-(x / 2U)) / 2U isn't equal to -((x / 2U) / 2U) for x >= 2. + For signed types, even with wrapping overflow, this is fine. */ + if (code != MULT_EXPR && TYPE_UNSIGNED (type)) + break; if ((t1 = extract_muldiv (op0, c, code, wide_type, strict_overflow_p)) != 0) return fold_build1 (tcode, ctype, fold_convert (ctype, t1)); --- gcc/testsuite/gcc.c-torture/execute/pr56250.c.jj 2013-02-08 12:12:43.477013120 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr56250.c 2013-02-08 11:58:20.000000000 +0100 @@ -0,0 +1,13 @@ +/* PR tree-optimization/56250 */ + +extern void abort (void); + +int +main () +{ + unsigned int x = 2; + unsigned int y = (0U - x / 2) / 2; + if (-1U / x != y) + abort (); + return 0; +}