]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Support Zilsd code gen
authorKito Cheng <kito.cheng@sifive.com>
Mon, 12 May 2025 09:38:39 +0000 (02:38 -0700)
committerKito Cheng <kito.cheng@sifive.com>
Mon, 19 May 2025 06:31:42 +0000 (14:31 +0800)
This commit adds the code gen support for Zilsd, which is a
newly added extension for RISC-V. The Zilsd extension allows
for loading and storing 64-bit values using even-odd register
pairs.

We only try to do miminal code gen support for that, which means only
use the new instructions when the load store is 64 bits data, we can use
that to optimize the code gen of memcpy/memset/memmove and also the
prologue and epilogue of functions, but I think that probably should be
done in a follow up patch.

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_legitimize_move): Handle
load/store with odd-even reg pair.
(riscv_split_64bit_move_p): Don't split load/store if zilsd enabled.
(riscv_hard_regno_mode_ok): Only allow even reg can be used for
64 bits mode for zilsd.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zilsd-code-gen.c: New test.

gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/zilsd-code-gen.c [new file with mode: 0644]

index 8d84bee4688241875aa322d44a345d2130da4561..54395b8d3a7482ddb8573bf0c7855829f71704a8 100644 (file)
@@ -3740,6 +3740,26 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
       return true;
     }
 
+  if (TARGET_ZILSD
+      && (GET_MODE_UNIT_SIZE (mode) == (UNITS_PER_WORD * 2))
+      && ((REG_P (dest) && MEM_P (src))
+         || (MEM_P (dest) && REG_P (src)))
+      && can_create_pseudo_p ())
+    {
+      rtx reg = REG_P (dest) ? dest : src;
+      unsigned regno = REGNO (reg);
+      /* ZILSD requires an even-odd register pair, let RA to
+        fix the constraint if the reg is hard reg and not even reg.  */
+      if ((regno < FIRST_PSEUDO_REGISTER)
+         && (regno % 2) != 0)
+       {
+         rtx tmp = gen_reg_rtx (GET_MODE (reg));
+         emit_move_insn (tmp, src);
+         emit_move_insn (dest, tmp);
+         return true;
+       }
+    }
+
   /* RISC-V GCC may generate non-legitimate address due to we provide some
      pattern for optimize access PIC local symbol and it's make GCC generate
      unrecognizable instruction during optimizing.  */
@@ -4576,6 +4596,19 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
   if (TARGET_64BIT)
     return false;
 
+  /* Zilsd provides load/store with even-odd register pair. */
+  if (TARGET_ZILSD
+      && (((REG_P (dest) && MEM_P (src))
+         || (MEM_P (dest) && REG_P (src)))))
+    {
+      rtx reg = REG_P (dest) ? dest : src;
+      unsigned regno = REGNO (reg);
+      /* GCC may still generating some load/store with odd-even reg pair
+        because the ABI handling, but that's fine, just split that later.  */
+      if (GP_REG_P (regno))
+       return (regno < FIRST_PSEUDO_REGISTER) && ((regno % 2) != 0);
+    }
+
   /* There is no need to split if the FLI instruction in the `Zfa` extension can be used.  */
   if (satisfies_constraint_zfli (src))
     return false;
@@ -9798,6 +9831,12 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
       if (riscv_v_ext_mode_p (mode))
        return false;
 
+      /* Zilsd require load/store with even-odd reg pair.  */
+      if (TARGET_ZILSD
+         && (GET_MODE_UNIT_SIZE (mode) == (UNITS_PER_WORD * 2))
+         && ((regno % 2) != 0))
+       return false;
+
       if (!GP_REG_P (regno + nregs - 1))
        return false;
     }
diff --git a/gcc/testsuite/gcc.target/riscv/zilsd-code-gen.c b/gcc/testsuite/gcc.target/riscv/zilsd-code-gen.c
new file mode 100644 (file)
index 0000000..9155622
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zilsd -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+long long foo1(long long *a)
+{
+    return *a;
+}
+
+long long g;
+
+void foo2(long long a)
+{
+    g = a;
+}
+
+/* { dg-final { scan-assembler-times "ld\t" 1 } } */
+/* { dg-final { scan-assembler-times "sd\t" 1 } } */