This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix simplify_relational_operation_1 to avoid creating invalid rtl sharing (PR debug/42662)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]