This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix simplify_relational_operation_1 to avoid creating invalid rtl sharing (PR debug/42662)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 11 Jan 2010 11:07:58 -0500
- Subject: [PATCH] Fix simplify_relational_operation_1 to avoid creating invalid rtl sharing (PR debug/42662)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
As shown on the testcase below, simplify_relational_operation_1
when canonicalizing (ltu (plus x y) y) can create invalid rtl sharing,
if x can't be shared, because it uses op0's first operand twice in the
generated rtl.
Similar place where we optimize floating 2*x into x+x is handled properly
(calls copy_rtx). I couldn't find other similar issues during quick
skimming of simplify-rtx.c.
Fixed thusly, bootstrapped/regtested on x86_64-linux.
Ok for trunk? What about 4.4 where this bug is latent?
2010-01-11 Jakub Jelinek <jakub@redhat.com>
PR debug/42662
* simplify-rtx.c (simplify_relational_operation_1): Avoid invalid rtx
sharing when canonicalizing ({lt,ge}u (plus a b) b).
* gcc.dg/pr42662.c: New test.
--- gcc/simplify-rtx.c.jj 2009-11-25 16:47:36.000000000 +0100
+++ gcc/simplify-rtx.c 2010-01-11 10:34:19.000000000 +0100
@@ -4046,7 +4046,8 @@ simplify_relational_operation_1 (enum rt
&& rtx_equal_p (op1, XEXP (op0, 1))
/* Don't recurse "infinitely" for (LTU/GEU (PLUS b b) b). */
&& !rtx_equal_p (op1, XEXP (op0, 0)))
- return simplify_gen_relational (code, mode, cmp_mode, op0, XEXP (op0, 0));
+ return simplify_gen_relational (code, mode, cmp_mode, op0,
+ copy_rtx (XEXP (op0, 0)));
if (op1 == const0_rtx)
{
--- gcc/testsuite/gcc.dg/pr42662.c.jj 2010-01-11 10:36:57.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr42662.c 2010-01-11 10:37:24.000000000 +0100
@@ -0,0 +1,48 @@
+/* PR debug/42662 */
+/* { dg-do compile } */
+/* { dg-options "-g -O2" } */
+
+struct S { unsigned long s[17]; };
+
+static inline void
+foo (struct S *r, struct S *a, unsigned n)
+{
+ unsigned b = n / 8;
+ r->s[0] = (b >= 1 ? : a->s[1 - b]);
+}
+
+static inline void
+bar (struct S *r, struct S *a)
+{
+ r->s[0] = a->s[0] << 1;
+}
+
+static inline void
+baz (struct S *r, struct S *a, struct S *b)
+{
+ unsigned c = 0;
+ int i;
+ for (i = 0; i < 3; ++i)
+ {
+ unsigned long d = a->s[i];
+ long e = d + b->s[i];
+ if (c)
+ ++e == 0;
+ c = e < d;
+ r->s[i] = e;
+ }
+}
+
+void
+test (struct S *r, int s, int d)
+{
+ struct S u;
+ if (s)
+ {
+ bar (&u, r);
+ foo (r, r, 3);
+ baz (r, r, &u);
+ }
+ u.s[0] = d;
+ baz (r, r, &u);
+}
Jakub