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} } } */
