[ARM] PR 47551: neon-related spill faliure

Richard Sandiford richard.sandiford@linaro.org
Mon Jan 31 12:34:00 GMT 2011


This patch fixes a reload failure that occurs if (a) a register with
a "structure" mode such as CImode is spilled to the stack and (b) the
stack slot is out of the neon load/store range.

For structure and vector modes, the only legitimate addresses are
those that neon supports.  This means that, when (b) occurs, reload will
rightly decide to reload the address into a temporary reload register.
The problem is that the ARM backend also says that the load must go
through a GENERAL_REGS reload register:

Reloads for insn # 1817
Reload 0: reload_in (SI) = (plus:SI (reg/f:SI 11 fp)
                                                    (const_int -7548 [0xffffffffffffe284]))
        CORE_REGS, RELOAD_FOR_OUTPUT_ADDRESS (opnum = 0), can't combine
        reload_in_reg: (plus:SI (reg/f:SI 11 fp)
                                                    (const_int -7548 [0xffffffffffffe284]))
Reload 1: reload_in (SI) = (plus:SI (reg/f:SI 11 fp)
                                                    (const_int -7548 [0xffffffffffffe284]))
        CORE_REGS, RELOAD_FOR_OTHER_ADDRESS (opnum = 0), can't combine
        reload_in_reg: (plus:SI (reg/f:SI 11 fp)
                                                    (const_int -7548 [0xffffffffffffe284]))
Reload 2: GENERAL_REGS, RELOAD_FOR_OTHER_ADDRESS (opnum = 0), can't combine, secondary_reload_p
Reload 3: GENERAL_REGS, RELOAD_FOR_OUTPUT_ADDRESS (opnum = 0), can't combine, secondary_reload_p
Reload 4: reload_in (CI) = (mem/c:CI (plus:SI (reg/f:SI 11 fp)
                                                        (const_int -7548 [0xffffffffffffe284])) [0 %sfp+-7496 S48 A64])
        reload_out (CI) = (mem/c:CI (plus:SI (reg/f:SI 11 fp)
                                                        (const_int -7548 [0xffffffffffffe284])) [0 %sfp+-7496 S48 A64])
        VFP_REGS, RELOAD_OTHER (opnum = 0), can't combine
        reload_in_reg: (reg:CI 303 [ D.14795 ])
        reload_out_reg: (reg:CI 303 [ D.14795 ])
        secondary_in_reload = 2, secondary_out_reload = 3

where secondary reloads 2 and 3 are bogus.

This comes from two related problems in coproc_secondary_reload_class:
it doesn't handle structure modes like CImode, and it checks whether
the MEM is already legitimate.  The latter is wrong because the memory
is still in its unreloaded form.  The structure and vector move patterns
handle all valid addresses, and reload will take care of invalid
addresses for us, so we should simply check for a MEM.

Tested on arm-linux-gnueabi (-marm and -mthumb).  I don't think this
is a regression, so: OK to install once 4.7 is open?

Richard


gcc/
	PR target/47551
	* config/arm/arm.c (coproc_secondary_reload_class): Handle
	structure modes.  Don't check neon_vector_mem_operand for
	vector or structure modes.

gcc/testsuite/
	PR target/47551
	* gcc.target/arm/neon-modes-2.c: New test.

Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2011-01-31 11:13:20.000000000 +0000
+++ gcc/config/arm/arm.c	2011-01-31 11:27:45.000000000 +0000
@@ -9083,11 +9083,14 @@ coproc_secondary_reload_class (enum mach
       return GENERAL_REGS;
     }
 
+  /* The neon move patterns handle all legitimate vector and struct
+     addresses.  */
   if (TARGET_NEON
+      && MEM_P (x)
       && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
-          || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
-      && neon_vector_mem_operand (x, 0))
-     return NO_REGS;
+	  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
+	  || VALID_NEON_STRUCT_MODE (mode)))
+    return NO_REGS;
 
   if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode))
     return NO_REGS;
Index: gcc/testsuite/gcc.target/arm/neon-modes-2.c
===================================================================
--- /dev/null	2011-01-26 10:43:14.268819722 +0000
+++ gcc/testsuite/gcc.target/arm/neon-modes-2.c	2011-01-31 11:28:42.000000000 +0000
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-O1" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+
+#define SETUP(A) x##A = vld3_u32 (ptr + A * 0x20)
+#define MODIFY(A) x##A = vld3_lane_u32 (ptr + A * 0x20 + 0x10, x##A, 1)
+#define STORE(A) vst3_u32 (ptr + A * 0x20, x##A)
+
+#define MANY(A) A (0), A (1), A (2), A (3), A (4), A (5)
+
+void
+bar (uint32_t *ptr, int y)
+{
+  uint32x2x3_t MANY (SETUP);
+  int *x = __builtin_alloca (y);
+  int z[0x1000];
+  foo (x, z);
+  MANY (MODIFY);
+  foo (x, z);
+  MANY (STORE);
+}



More information about the Gcc-patches mailing list