Hi!

Without this patch, cprop can propagate e.g. a SYMBOL_REF to former
(mem (plus (reg) (const_int)))
making it invalid RTL (as plus of CONSTANT_P arguments must be simplified
or surrounded by CONST).

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2014-01-31  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/57915
        * recog.c (simplify_while_replacing): For PLUS/MINUS
        with both operands CONSTANT_P where one operand is equal
        to TO call simplify_gen_binary.

        * gcc.target/i386/pr57915.c: New test.

--- gcc/recog.c.jj      2014-01-23 10:53:05.000000000 +0100
+++ gcc/recog.c 2014-01-31 16:08:06.371826412 +0100
@@ -590,6 +590,14 @@ simplify_while_replacing (rtx *loc, rtx
        validate_change (object, loc,
                         simplify_gen_binary
                         (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
+      /* Canonicalize addition of two constants, that must be either
+        simplified into a constant or (const (plus (...) (...))).  */
+      else if (CONSTANT_P (XEXP (x, 0))
+              && CONSTANT_P (XEXP (x, 1))
+              && (XEXP (x, 0) == to || XEXP (x, 1) == to))
+       validate_change (object, loc,
+                        simplify_gen_binary
+                        (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
       break;
     case MINUS:
       if (CONST_SCALAR_INT_P (XEXP (x, 1)))
@@ -599,6 +607,14 @@ simplify_while_replacing (rtx *loc, rtx
                          simplify_gen_unary (NEG,
                                              GET_MODE (x), XEXP (x, 1),
                                              GET_MODE (x))), 1);
+      /* Canonicalize subtraction of two constants, that must be either
+        simplified into a constant or (const (minus (...) (...))).  */
+      else if (CONSTANT_P (XEXP (x, 0))
+              && CONSTANT_P (XEXP (x, 1))
+              && (XEXP (x, 0) == to || XEXP (x, 1) == to))
+       validate_change (object, loc,
+                        simplify_gen_binary
+                        (MINUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
       break;
     case ZERO_EXTEND:
     case SIGN_EXTEND:
--- gcc/testsuite/gcc.target/i386/pr57915.c.jj  2014-01-31 16:10:47.436942155 
+0100
+++ gcc/testsuite/gcc.target/i386/pr57915.c     2014-01-31 16:10:21.000000000 
+0100
@@ -0,0 +1,33 @@
+/* PR rtl-optimization/57915 */
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+extern struct T { char a[8]; char b[16]; } t;
+int c;
+void foo (void);
+
+extern inline char *
+baz (char *x, const char *y)
+{
+  const char *e = y;
+  unsigned long f, g;
+  asm ("" : "+c" (f), "+D" (e) : "a" ('\0'), "X" (*e));
+  g = e - 1 - y;
+  __builtin_memcpy (x, y, g);
+  x[g] = '\0';
+  return x;
+}
+
+void
+bar (void)
+{
+  char d[16];
+  baz (d, t.b);
+
+  for (;;)
+    {
+      foo ();
+      if (c)
+       baz (d, t.b);
+    }
+}

        Jakub

Reply via email to