[gcc r17-2468] RISC-V: Exclude t1 from SIBCALL_REGS

Ma Jin via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:bfc82936d1ea078d21a58e063fd27022371ca3a3

commit r17-2468-gbfc82936d1ea078d21a58e063fd27022371ca3a3
Author: Jin Ma <[email protected]>
Date:   Sat Jul 11 22:45:54 2026 +0800

    RISC-V: Exclude t1 from SIBCALL_REGS
    
    RISCV_CALL_ADDRESS_TEMP and RISCV_PROLOGUE_TEMP2 both use t1.  An
    indirect sibcall target in t1 can therefore be overwritten by an RVV
    scalable-frame epilogue before the final jump.
    
    Exclude t1 from SIBCALL_REGS and map it to JALR_REGS.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.cc (riscv_regno_to_class): Map t1 to
            JALR_REGS.
            * config/riscv/riscv.h (RISCV_PROLOGUE_TEMP_REGNUM): Document
            the SIBCALL_REGS restriction.
            (REG_CLASS_CONTENTS): Remove t1 from SIBCALL_REGS.
    
    gcc/testsuite/ChangeLog:
    
            * g++.target/riscv/pr97682.C: Accept registers in SIBCALL_REGS.
            * gcc.target/riscv/rvv/base/sibcall-scalable-frame-indirect.c:
            New test.
            * gcc.target/riscv/rvv/base/sibcall-scalable-frame-weak.c: New test.

Diff:
---
 gcc/config/riscv/riscv.cc                          |  2 +-
 gcc/config/riscv/riscv.h                           | 11 ++++----
 gcc/testsuite/g++.target/riscv/pr97682.C           |  4 +--
 .../rvv/base/sibcall-scalable-frame-indirect.c     | 28 +++++++++++++++++++
 .../riscv/rvv/base/sibcall-scalable-frame-weak.c   | 32 ++++++++++++++++++++++
 5 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 55567cb281f7..596145ca19c1 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -346,7 +346,7 @@ bool riscv_registering_builtins;
 /* Index R is the smallest register class that contains register R.  */
 const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
   GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,
-  GR_REGS,	GR_REGS,	SIBCALL_REGS,	SIBCALL_REGS,
+  GR_REGS,	GR_REGS,	JALR_REGS,	SIBCALL_REGS,
   JALR_REGS,	JALR_REGS,	SIBCALL_REGS,	SIBCALL_REGS,
   SIBCALL_REGS,	SIBCALL_REGS,	SIBCALL_REGS,	SIBCALL_REGS,
   SIBCALL_REGS,	SIBCALL_REGS,	JALR_REGS,	JALR_REGS,
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 7eb85d654a7e..4ba6ad260e55 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -430,10 +430,11 @@ ARCH_UNSET_CLEANUP_SPECS \
 
 /* Registers used as temporaries in prologue/epilogue code.
 
-   The prologue registers mustn't conflict with any
-   incoming arguments, the static chain pointer, or the frame pointer.
-   The epilogue temporary mustn't conflict with the return registers,
-   the frame pointer, the EH stack adjustment, or the EH data registers. */
+   The prologue temporaries mustn't conflict with any incoming arguments,
+   the static chain pointer, or the frame pointer.
+   The epilogue temporaries mustn't conflict with the return registers,
+   the frame pointer, the EH stack adjustment, the EH data registers, or
+   any register in SIBCALL_REGS.  */
 
 #define RISCV_PROLOGUE_TEMP_REGNUM (GP_TEMP_FIRST)
 #define RISCV_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_PROLOGUE_TEMP_REGNUM)
@@ -572,7 +573,7 @@ enum reg_class
 #define REG_CLASS_CONTENTS						\
 {									\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* NO_REGS */		\
-  { 0xf003fcc0, 0x00000000, 0x00000000, 0x00000000 },	/* SIBCALL_REGS */	\
+  { 0xf003fc80, 0x00000000, 0x00000000, 0x00000000 },	/* SIBCALL_REGS */	\
   { 0x0000ff00, 0x00000000, 0x00000000, 0x00000000 },	/* RVC_GR_REGS */	\
   { 0xffffffc0, 0x00000000, 0x00000000, 0x00000000 },	/* JALR_REGS */		\
   { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 },	/* GR_REGS */		\
diff --git a/gcc/testsuite/g++.target/riscv/pr97682.C b/gcc/testsuite/g++.target/riscv/pr97682.C
index 68e332a9993d..2c68507f467a 100644
--- a/gcc/testsuite/g++.target/riscv/pr97682.C
+++ b/gcc/testsuite/g++.target/riscv/pr97682.C
@@ -156,5 +156,5 @@ namespace llvm
   void bm::bl() { bk->bl(); }
 }
 
-/* The t1 register is to initial symbol reference for call instruction.  */
-/* { dg-final { scan-assembler "la\tt1,.*FrequencyData.*_M_default_append.*" } } */
+/* A register in SIBCALL_REGS is used for the call address.  */
+/* { dg-final { scan-assembler {la\t(t[2-6]|a[0-7]),.*FrequencyData.*_M_default_append.*} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-indirect.c b/gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-indirect.c
new file mode 100644
index 000000000000..1cc1dda3bc01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-indirect.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gcv -mabi=lp64d" } */
+
+#include <riscv_vector.h>
+
+typedef int (*fn_t) (int);
+
+int __attribute__ ((noinline))
+victim (float *p, int n, fn_t fn)
+{
+  register fn_t target asm ("t1") = fn;
+
+  size_t vl = __riscv_vsetvl_e32m4 (n);
+  volatile vfloat32m4_t v0 = __riscv_vle32_v_f32m4 (p, vl);
+  volatile vfloat32m4_t v1 = __riscv_vle32_v_f32m4 (p + vl, vl);
+  vfloat32m4_t x0 = v0;
+  vfloat32m4_t x1 = v1;
+
+  x0 = __riscv_vfadd_vv_f32m4 (x0, x1, vl);
+  __riscv_vse32_v_f32m4 (p, x0, vl);
+  asm volatile ("" : "+r" (target));
+
+  return target (n);
+}
+
+/* { dg-final { scan-assembler {csrr\t[^,]+,vlenb} } } */
+/* { dg-final { scan-assembler {\tjr\t(t[2-6]|a[0-7])\n} } } */
+/* { dg-final { scan-assembler-not {\tjr\tt[01]\n} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-weak.c b/gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-weak.c
new file mode 100644
index 000000000000..24136ce06c47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-weak.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -march=rv64gcv -mabi=lp64d" } */
+
+#include <riscv_vector.h>
+
+extern int wrap (int (*)(int), int) __attribute__ ((weak));
+
+static int __attribute__ ((noinline))
+kernel (int x)
+{
+  return x + 1;
+}
+
+int __attribute__ ((noinline))
+victim (float *p, int n)
+{
+  size_t vl = __riscv_vsetvl_e32m4 (n);
+  volatile vfloat32m4_t v0 = __riscv_vle32_v_f32m4 (p, vl);
+  volatile vfloat32m4_t v1 = __riscv_vle32_v_f32m4 (p + vl, vl);
+  vfloat32m4_t x0 = v0;
+  vfloat32m4_t x1 = v1;
+
+  x0 = __riscv_vfadd_vv_f32m4 (x0, x1, vl);
+  __riscv_vse32_v_f32m4 (p, x0, vl);
+
+  return wrap (kernel, n);
+}
+
+/* { dg-final { scan-assembler "wrap" } } */
+/* { dg-final { scan-assembler {csrr\t[^,]+,vlenb} } } */
+/* { dg-final { scan-assembler {\tjr\t(t[2-6]|a[0-7])\n} } } */
+/* { dg-final { scan-assembler-not {\tjr\tt[01]\n} } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.