[AArch64] Adjust preferred_reload_class of SP+C
diff mbox

Message ID 526012EF.5090105@arm.com
State New
Headers show

Commit Message

Marcus Shawcroft Oct. 17, 2013, 4:40 p.m. UTC
Hi,

This patch addresses an issue in reload triggered by the
gfortran.dg/loc_2.f90 regression test at -O3 with LRA disabled.

The patch is based on work done	by Ian Bolton here at ARM which	I've
dusted down and submitted.

Following SFP elimination and under heavy register pressure, reload
attempts the reload of SP+offset into a V register.  The AArch64
instruction set does not support such an operation.

We considered two solutions to this issue:

1) Detect the SP+offset pattern in secondary reload and use an
intermediate X register.

2) Detect the SP+offset->V pattern in	preferred_reload_class and
return NO_REG before secondary reload gets involved.

The latter looks like a simpler and more intuitive solution to me than
the first.  I also note that the i386 backend implementation of
preferred_reload_class contains equivalent code.

I intend to leave this patch on the list for a few days before
committing to give folks knowledgable on reload and the associated
target hooks the opportunity to comment.

Thanks
/Marcus

2013-10-17  Ian Bolton  <ian.bolton@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>

         * config/aarch64/aarch64.c (aarch64_preferred_reload_class):
         Special case reload SP+C into none GENERAL_REGS.

Patch
diff mbox

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 7fce7a0..cc9ecdd 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -4237,6 +4237,24 @@  aarch64_preferred_reload_class (rtx x, reg_class_t regclass)
       && !aarch64_simd_imm_scalar_p (x, GET_MODE (x)))
     return NO_REGS;
 
+  /* Register eliminiation can result in a request for
+     SP+constant->FP_REGS.  We cannot support such operations which
+     use SP as source and an FP_REG as destination, so reject out
+     right now.  */
+  if (! reg_class_subset_p (regclass, GENERAL_REGS) && GET_CODE (x) == PLUS)
+    {
+      rtx lhs = XEXP (x, 0);
+
+      /* Look through a possible SUBREG introduced by ILP32.  */
+      if (GET_CODE (lhs) == SUBREG)
+	lhs = SUBREG_REG (lhs);
+
+      gcc_assert (REG_P (lhs));
+      gcc_assert (reg_class_subset_p (REGNO_REG_CLASS (REGNO (lhs)),
+				      POINTER_REGS));
+      return NO_REGS;
+    }
+
   return regclass;
 }