(This patch supercedes this one:
http://gcc.gnu.org/ml/gcc-patches/2013-07/msg01462.html)
The movdi_aarch64 pattern allows moving a constant into an FP_REG,
but has the constraint Dd, which is stricter than the constraint N for
moving a constant into a CORE_REG. This is due to restricted values
allowed for MOVI instruction.
Due to the predicate allowing any constant that is valid for the
CORE_REGs, we can run into situations where IRA/reload has decided
to use FP_REGs but the value is not actually valid for MOVI.
This patch makes use of TARGET_PREFERRED_RELOAD_CLASS to ensure that
NO_REGS (which leads to literal pool) is returned, when the immediate
can't be put directly into FP_REGS.
A testcase is included.
Linux regressions all came back good.
OK for trunk?
Cheers,
Ian
2013-09-04 Ian Bolton <ian.bol...@arm.com>
gcc/
* config/aarch64/aarch64.c (aarch64_preferred_reload_class):
Return NO_REGS for immediate that can't be moved directly
into FP_REGS.
testsuite/
* gcc.target/aarch64/movdi_1.c: New test.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index aed035a..2c07ccf 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -4236,10 +4236,18 @@ aarch64_class_max_nregs (reg_class_t regclass, enum
machine_mode mode)
}
static reg_class_t
-aarch64_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass)
+aarch64_preferred_reload_class (rtx x, reg_class_t regclass)
{
- return ((regclass == POINTER_REGS || regclass == STACK_REG)
- ? GENERAL_REGS : regclass);
+ if (regclass == POINTER_REGS || regclass == STACK_REG)
+ return GENERAL_REGS;
+
+ /* If it's an integer immediate that MOVI can't handle, then
+ FP_REGS is not an option, so we return NO_REGS instead. */
+ if (CONST_INT_P (x) && reg_class_subset_p (regclass, FP_REGS)
+ && !aarch64_simd_imm_scalar_p (x, GET_MODE (x)))
+ return NO_REGS;
+
+ return regclass;
}
void
diff --git a/gcc/testsuite/gcc.target/aarch64/movdi_1.c
b/gcc/testsuite/gcc.target/aarch64/movdi_1.c
new file mode 100644
index 0000000..a22378d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/movdi_1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-inline" } */
+
+#include <arm_neon.h>
+
+void
+foo1 (uint64_t *a)
+{
+ uint64x1_t val18;
+ uint32x2_t val19;
+ uint64x1_t val20;
+ val19 = vcreate_u32 (0x800000004cf3dffbUL);
+ val20 = vrsra_n_u64 (val18, vreinterpret_u64_u32 (val19), 34);
+ vst1_u64 (a, val20);
+}
+
+void
+foo2 (uint64_t *a)
+{
+ uint64x1_t val18;
+ uint32x2_t val19;
+ uint64x1_t val20;
+ val19 = vcreate_u32 (0xdffbUL);
+ val20 = vrsra_n_u64 (val18, vreinterpret_u64_u32 (val19), 34);
+ vst1_u64 (a, val20);
+}