Skip to content

Commit 058d96f

Browse files
authored
[RISCV] Support PreserveMost calling convention (#148214)
This adds the simplest implementation of `PreserveMost` calling convention and we preserve `x5-x31` (except x6/x7/x28) registers. Fixes #148147.
1 parent 7a0024d commit 058d96f

File tree

5 files changed

+466
-1
lines changed

5 files changed

+466
-1
lines changed

llvm/docs/LangRef.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,8 @@ added in the future:
413413
- On AArch64 the callee preserves all general purpose registers, except
414414
X0-X8 and X16-X18. Not allowed with ``nest``.
415415

416+
- On RISC-V the callee preserve x5-x31 except x6, x7 and x28 registers.
417+
416418
The idea behind this convention is to support calls to runtime functions
417419
that have a hot path and a cold path. The hot path is usually a small piece
418420
of code that doesn't use many registers. The cold path might need to call out to

llvm/lib/Target/RISCV/RISCVCallingConv.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,7 @@ def CSR_XLEN_F32_V_Interrupt_RVE: CalleeSavedRegs<(sub CSR_XLEN_F32_V_Interrupt,
9595
// Same as CSR_XLEN_F64_V_Interrupt, but excluding X16-X31.
9696
def CSR_XLEN_F64_V_Interrupt_RVE: CalleeSavedRegs<(sub CSR_XLEN_F64_V_Interrupt,
9797
(sequence "X%u", 16, 31))>;
98+
99+
def CSR_RT_MostRegs : CalleeSavedRegs<(sub CSR_Interrupt, X6, X7, X28)>;
100+
def CSR_RT_MostRegs_RVE : CalleeSavedRegs<(sub CSR_RT_MostRegs,
101+
(sequence "X%u", 16, 31))>;

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22455,6 +22455,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
2245522455
case CallingConv::C:
2245622456
case CallingConv::Fast:
2245722457
case CallingConv::SPIR_KERNEL:
22458+
case CallingConv::PreserveMost:
2245822459
case CallingConv::GRAAL:
2245922460
case CallingConv::RISCV_VectorCall:
2246022461
#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:

llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
6868
auto &Subtarget = MF->getSubtarget<RISCVSubtarget>();
6969
if (MF->getFunction().getCallingConv() == CallingConv::GHC)
7070
return CSR_NoRegs_SaveList;
71+
if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)
72+
return Subtarget.hasStdExtE() ? CSR_RT_MostRegs_RVE_SaveList
73+
: CSR_RT_MostRegs_SaveList;
7174
if (MF->getFunction().hasFnAttribute("interrupt")) {
7275
if (Subtarget.hasVInstructions()) {
7376
if (Subtarget.hasStdExtD())
@@ -811,7 +814,13 @@ RISCVRegisterInfo::getCallPreservedMask(const MachineFunction & MF,
811814

812815
if (CC == CallingConv::GHC)
813816
return CSR_NoRegs_RegMask;
814-
switch (Subtarget.getTargetABI()) {
817+
RISCVABI::ABI ABI = Subtarget.getTargetABI();
818+
if (CC == CallingConv::PreserveMost) {
819+
if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
820+
return CSR_RT_MostRegs_RVE_RegMask;
821+
return CSR_RT_MostRegs_RegMask;
822+
}
823+
switch (ABI) {
815824
default:
816825
llvm_unreachable("Unrecognized ABI");
817826
case RISCVABI::ABI_ILP32E:

0 commit comments

Comments
 (0)