This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix up cprop to canonicalize PLUS/MINUS with 2 CONSTANT_P arguments (PR rtl-optimization/57915)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Eric Botcazou <ebotcazou at adacore dot com>, Steven Bosscher <stevenb dot gcc at gmail dot com>, Richard Biener <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 31 Jan 2014 22:28:10 +0100
- Subject: [PATCH] Fix up cprop to canonicalize PLUS/MINUS with 2 CONSTANT_P arguments (PR rtl-optimization/57915)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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 <jakub@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