re PR rtl-optimization/54300 (regcprop incorrectly looks through parallel register...
authorRichard Earnshaw <rearnsha@arm.com>
Mon, 9 Dec 2013 14:54:00 +0000 (14:54 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Mon, 9 Dec 2013 14:54:00 +0000 (14:54 +0000)
PR rtl-optimization/54300

gcc/

PR rtl-optimization/54300
* regcprop.c (copyprop_hardreg_forward_1): Ensure any unused
outputs in a single-set are killed from the value chains.

gcc/testsuite:

PR rtl-optimization/54300
* gcc.target/arm/pr54300.C: New test.

From-SVN: r205807

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/ldrd-strd-offset.c [new file with mode: 0644]

index c100cee..ba39e4b 100644 (file)
@@ -1,3 +1,8 @@
+2013-12-09  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.c (mem_ok_for_ldrd_strd): Rename first argument as MEM.  Do
+       more address validation checks.
+
 2013-12-09  Marek Polacek  <polacek@redhat.com>
 
        PR sanitizer/59415
index c961fb1..bed2437 100644 (file)
@@ -15285,28 +15285,37 @@ operands_ok_ldrd_strd (rtx rt, rtx rt2, rtx rn, HOST_WIDE_INT offset,
 }
 
 /* Helper for gen_operands_ldrd_strd.  Returns true iff the memory
-   operand ADDR is an immediate offset from the base register and is
-   not volatile, in which case it sets BASE and OFFSET
-   accordingly.  */
-bool
-mem_ok_for_ldrd_strd (rtx addr, rtx *base, rtx *offset)
+   operand MEM's address contains an immediate offset from the base
+   register and has no side effects, in which case it sets BASE and
+   OFFSET accordingly.  */
+static bool
+mem_ok_for_ldrd_strd (rtx mem, rtx *base, rtx *offset)
 {
+  rtx addr;
+
+  gcc_assert (base != NULL && offset != NULL);
+
   /* TODO: Handle more general memory operand patterns, such as
      PRE_DEC and PRE_INC.  */
 
-  /* Convert a subreg of mem into mem itself.  */
-  if (GET_CODE (addr) == SUBREG)
-    addr = alter_subreg (&addr, true);
-
-  gcc_assert (MEM_P (addr));
+  if (side_effects_p (mem))
+    return false;
 
-  /* Don't modify volatile memory accesses.  */
-  if (MEM_VOLATILE_P (addr))
+  /* Can't deal with subregs.  */
+  if (GET_CODE (mem) == SUBREG)
     return false;
 
+  gcc_assert (MEM_P (mem));
+
   *offset = const0_rtx;
 
-  addr = XEXP (addr, 0);
+  addr = XEXP (mem, 0);
+
+  /* If addr isn't valid for DImode, then we can't handle it.  */
+  if (!arm_legitimate_address_p (DImode, addr,
+                                reload_in_progress || reload_completed))
+    return false;
+
   if (REG_P (addr))
     {
       *base = addr;
index 5c3e5b5..0f8a9e2 100644 (file)
@@ -1,3 +1,7 @@
+2013-12-09  Richard Earnshaw  <rearnsha@arm.com>
+
+       * gcc.target/arm/ldrd-strd-offset.c: New.
+
 2013-12-09  Martin Jambor  <mjambor@suse.cz>
 
        * gcc.c-torture/compile/pr39834.c: Remove optimization level option.
diff --git a/gcc/testsuite/gcc.target/arm/ldrd-strd-offset.c b/gcc/testsuite/gcc.target/arm/ldrd-strd-offset.c
new file mode 100644 (file)
index 0000000..a128a0a
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef struct
+{
+  int x;
+  int i, j;
+} off_struct;
+
+int foo (char *str, int *a, int b, int c)
+{
+  off_struct *p = (off_struct *)(str + 3);
+  b = p->i;
+  c = p->j;
+  *a = b + c;
+  return 0;
+}