[PATCH] Fix extract_muldiv (PR tree-optimization/56899)
Jakub Jelinek
jakub@redhat.com
Wed Apr 10 17:25:00 GMT 2013
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.
--- 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;
+}
Jakub
More information about the Gcc-patches
mailing list