Message ID | 20130410153114.GE16463@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
On 04/10/2013 09:31 AM, Jakub Jelinek wrote: > Hi! > > As f1 in the testcase shows, applying distributive law in extract_muldiv_1 > isn't safe if overflow behavior isn't defined, if we have > (op0 + c1) * c2 > and the type is signed, we can't just try to fold that to > op0 * c2 + (c1 * c2) > even when we know that c1*c2 doesn't overflow, because op0 * c2 > might overflow even when (op0 + c1) * c2 doesn't. > > Fixed thusly, after all that hunk of code is often soon undone by > fold_build2 again or later during GIMPLE optimizations, > bootstrapped/regtested on x86_64-linux and i686-linux, ok > for trunk/4.8? > > 2013-04-10 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/56899 > * fold-const.c (extract_muldiv_1): Apply distributive law > only if TYPE_OVERFLOW_WRAPS (ctype). > > * gcc.c-torture/execute/pr56899.c: New test. OK, but I think you should update the comment before the test. Right now it just references the overflow of the constant multiplication. jeff
--- gcc/fold-const.c.jj 2013-04-03 15:46:45.000000000 +0200 +++ gcc/fold-const.c 2013-04-10 14:45:20.590321561 +0200 @@ -5851,7 +5851,7 @@ extract_muldiv_1 (tree t, tree c, enum t /* The last case is if we are a multiply. In that case, we can apply the distributive law to commute the multiply and addition if the multiplication of the constants doesn't overflow. */ - if (code == MULT_EXPR) + if (code == MULT_EXPR && TYPE_OVERFLOW_WRAPS (ctype)) return fold_build2 (tcode, ctype, fold_build2 (code, ctype, fold_convert (ctype, op0), --- gcc/testsuite/gcc.c-torture/execute/pr56899.c.jj 2013-04-10 14:58:37.015788243 +0200 +++ gcc/testsuite/gcc.c-torture/execute/pr56899.c 2013-04-10 14:58:08.000000000 +0200 @@ -0,0 +1,47 @@ +/* PR tree-optimization/56899 */ + +#if __SIZEOF_INT__ == 4 && __CHAR_BIT__ == 8 +__attribute__((noinline, noclone)) void +f1 (int v) +{ + int x = -214748365 * (v - 1); + if (x != -1932735285) + __builtin_abort (); +} + +__attribute__((noinline, noclone)) void +f2 (int v) +{ + int x = 214748365 * (v + 1); + if (x != -1932735285) + __builtin_abort (); +} + +__attribute__((noinline, noclone)) void +f3 (unsigned int v) +{ + unsigned int x = -214748365U * (v - 1); + if (x != -1932735285U) + __builtin_abort (); +} + +__attribute__((noinline, noclone)) void +f4 (unsigned int v) +{ + unsigned int x = 214748365U * (v + 1); + if (x != -1932735285U) + __builtin_abort (); +} +#endif + +int +main () +{ +#if __SIZEOF_INT__ == 4 && __CHAR_BIT__ == 8 + f1 (10); + f2 (-10); + f3 (10); + f4 (-10U); +#endif + return 0; +}