]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Fix memory cost for FPM_REGNUM
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 23 Jan 2025 13:57:01 +0000 (13:57 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Thu, 23 Jan 2025 13:57:01 +0000 (13:57 +0000)
GCC 15 is going to be the first release to support FPMR.
While working on a follow-up patch, I noticed that for:

    (set (reg:DI R) ...)
    ...
    (set (reg:DI fpmr) (reg:DI R))

IRA would prefer to spill R to memory rather than allocate a GPR.
This is because the register move cost for GENERAL_REGS to
MOVEABLE_SYSREGS is very high:

  /* Moves to/from sysregs are expensive, and must go via GPR.  */
  if (from == MOVEABLE_SYSREGS)
    return 80 + aarch64_register_move_cost (mode, GENERAL_REGS, to);
  if (to == MOVEABLE_SYSREGS)
    return 80 + aarch64_register_move_cost (mode, from, GENERAL_REGS);

but the memory cost for MOVEABLE_SYSREGS was the same as for
GENERAL_REGS, making memory much cheaper.

Loading and storing FPMR involves a GPR temporary, so the cost should
account for moving into and out of that temporary.

This did show up indirectly in some of the existing asm tests,
where the stack frame allocated 16 bytes for callee saves (D8)
and another 16 bytes for spilling a temporary register.

It's possible that other registers need the same treatment
and it's more than probable that this code needs a rework.
None of that seems suitable for stage 4 though.

gcc/
* config/aarch64/aarch64.cc (aarch64_memory_move_cost): Account
for the cost of moving in and out of GENERAL_SYSREGS.

gcc/testsuite/
* gcc.target/aarch64/acle/fpmr-5.c: New test.
* gcc.target/aarch64/sve2/acle/asm/dot_lane_mf8.c: Don't expect
a spill slot to be allocated.
* gcc.target/aarch64/sve2/acle/asm/mlalb_lane_mf8.c: Likewise.
* gcc.target/aarch64/sve2/acle/asm/mlallbb_lane_mf8.c: Likewise.
* gcc.target/aarch64/sve2/acle/asm/mlallbt_lane_mf8.c: Likewise.
* gcc.target/aarch64/sve2/acle/asm/mlalltb_lane_mf8.c: Likewise.
* gcc.target/aarch64/sve2/acle/asm/mlalltt_lane_mf8.c: Likewise.
* gcc.target/aarch64/sve2/acle/asm/mlalt_lane_mf8.c: Likewise.

gcc/config/aarch64/aarch64.cc
gcc/testsuite/gcc.target/aarch64/acle/fpmr-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/dot_lane_mf8.c
gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/mlalb_lane_mf8.c
gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/mlallbb_lane_mf8.c
gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/mlallbt_lane_mf8.c
gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/mlalltb_lane_mf8.c
gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/mlalltt_lane_mf8.c
gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/mlalt_lane_mf8.c

index dba779a8e51e4262a9e7e8b8a72253b355741019..a1f5619a615295c45f0f572b20f8e366e8e509b6 100644 (file)
@@ -15858,9 +15858,16 @@ aarch64_memory_move_cost (machine_mode mode, reg_class_t rclass_i, bool in)
            ? aarch64_tune_params.memmov_cost.load_fp
            : aarch64_tune_params.memmov_cost.store_fp);
 
+  /* If the move needs to go through GPRs, add the cost of doing that.  */
+  int base = 0;
+  if (rclass_i == MOVEABLE_SYSREGS)
+    base += (in
+            ? aarch64_register_move_cost (DImode, GENERAL_REGS, rclass_i)
+            : aarch64_register_move_cost (DImode, rclass_i, GENERAL_REGS));
+
   return (in
-         ? aarch64_tune_params.memmov_cost.load_int
-         : aarch64_tune_params.memmov_cost.store_int);
+         ? base + aarch64_tune_params.memmov_cost.load_int
+         : base + aarch64_tune_params.memmov_cost.store_int);
 }
 
 /* Implement TARGET_INSN_COST.  We have the opportunity to do something
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/fpmr-5.c b/gcc/testsuite/gcc.target/aarch64/acle/fpmr-5.c
new file mode 100644 (file)
index 0000000..da6d7f6
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-O" } */
+
+#include <stdint.h>
+
+void f(int cond)
+{
+  uint64_t x;
+  asm volatile ("" : "=r" (x));
+  if (cond)
+    {
+      register uint64_t fpmr asm ("fpmr") = x;
+      asm volatile ("" :: "Umv" (fpmr));
+    }
+}
+
+/* { dg-final { scan-assembler-not {\tsub\tsp,} } } */
index 9e54cd11c4b71f427c44634d75b32c83fb93ed20..83fe5cff5d3c8bfd428c834e81189475bcfc885a 100644 (file)
@@ -70,7 +70,7 @@ TEST_DUAL_Z (dot_lane_1_f16, svfloat16_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fdot    z0\.h, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (dot_lane_z8_f16, svfloat16_t, svmfloat8_t, z8,
@@ -151,7 +151,7 @@ TEST_DUAL_Z (dot_lane_1_f32, svfloat32_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fdot    z0\.s, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (dot_lane_z8_f32, svfloat32_t, svmfloat8_t, z8,
index e7af1b6dcc6977812b1fab89b623ce635278b2e6..39a272f60e0e0d6b8cd396ac1131f68352182670 100644 (file)
@@ -70,7 +70,7 @@ TEST_DUAL_Z (mlalb_lane_1_f16, svfloat16_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fmlalb  z0\.h, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (mlalb_lane_z8_f16, svfloat16_t, svmfloat8_t, z8,
index 07a529d8dc9b9136800c42950cb2f3645df15852..2d084515c856d9d22482696c5ebaa1092bf165e5 100644 (file)
@@ -70,7 +70,7 @@ TEST_DUAL_Z (mlallbb_lane_1_f32, svfloat32_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fmlallbb        z0\.s, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (mlallbb_lane_z8_f32, svfloat32_t, svmfloat8_t, z8,
index 9da29fbfb0b7a5b167b5b2846e8ce69b26eeb809..6dadbcf2e173f43a1818e74fa0bbe804b1b2cbf8 100644 (file)
@@ -70,7 +70,7 @@ TEST_DUAL_Z (mlallbt_lane_1_f32, svfloat32_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fmlallbt        z0\.s, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (mlallbt_lane_z8_f32, svfloat32_t, svmfloat8_t, z8,
index cbe297c188b74c0e5b3271bf33c0c169c8d72b1a..6b9e06c7550c481b97e4ea47de04ac8aa12c3d52 100644 (file)
@@ -70,7 +70,7 @@ TEST_DUAL_Z (mlalltb_lane_1_f32, svfloat32_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fmlalltb        z0\.s, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (mlalltb_lane_z8_f32, svfloat32_t, svmfloat8_t, z8,
index fc5bfba7877c66e41b8621cbaf3073f91bdb3c08..f33c4fe79658700df68e75b35b0f25b128dc410f 100644 (file)
@@ -70,7 +70,7 @@ TEST_DUAL_Z (mlalltt_lane_1_f32, svfloat32_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fmlalltt        z0\.s, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (mlalltt_lane_z8_f32, svfloat32_t, svmfloat8_t, z8,
index 4f5a1045420afd65da78122c5945947170ae1f6c..604d3325d605e76d73ee37fba1784b9abd21a8ac 100644 (file)
@@ -70,7 +70,7 @@ TEST_DUAL_Z (mlalt_lane_1_f16, svfloat16_t, svmfloat8_t,
 **     msr     fpmr, x0
 **     mov     (z[0-7])\.d, z8\.d
 **     fmlalt  z0\.h, z1\.b, \1\.b\[1\]
-**     ldr     d8, \[sp\], 32
+**     ldr     d8, \[sp\], 16
 **     ret
 */
 TEST_DUAL_LANE_REG (mlalt_lane_z8_f16, svfloat16_t, svmfloat8_t, z8,