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.
---
gcc/config/riscv/riscv.cc | 2 +-
gcc/config/riscv/riscv.h | 11 ++++---
gcc/testsuite/g++.target/riscv/pr97682.C | 4 +--
.../base/sibcall-scalable-frame-indirect.c | 28 ++++++++++++++++
.../rvv/base/sibcall-scalable-frame-weak.c | 32 +++++++++++++++++++
5 files changed, 69 insertions(+), 8 deletions(-)
create mode 100644
gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-indirect.c
create mode 100644
gcc/testsuite/gcc.target/riscv/rvv/base/sibcall-scalable-frame-weak.c
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 6eeaa11caab..450a0825072 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 7eb85d654a7..4ba6ad260e5 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 68e332a9993..2c68507f467 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 00000000000..1cc1dda3bc0
--- /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 00000000000..24136ce06c4
--- /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} } } */
--
2.52.0