Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions llvm/lib/Target/RISCV/RISCVCallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,21 @@ def CSR_XLEN_F32_Interrupt: CalleeSavedRegs<(add CSR_Interrupt,
def CSR_XLEN_F64_Interrupt: CalleeSavedRegs<(add CSR_Interrupt,
(sequence "F%u_D", 0, 31))>;

defvar VREGS = (add (sequence "V%u", 0, 31),
(sequence "V%uM2", 0, 31, 2),
(sequence "V%uM4", 0, 31, 4),
(sequence "V%uM8", 0, 31, 8));

// Same as CSR_Interrupt, but including all vector registers.
def CSR_XLEN_V_Interrupt: CalleeSavedRegs<(add CSR_Interrupt,
(sequence "V%u", 0, 31))>;
def CSR_XLEN_V_Interrupt: CalleeSavedRegs<(add CSR_Interrupt, VREGS)>;

// Same as CSR_Interrupt, but including all 32-bit FP registers and all vector
// registers.
def CSR_XLEN_F32_V_Interrupt: CalleeSavedRegs<(add CSR_XLEN_F32_Interrupt,
(sequence "V%u", 0, 31))>;
def CSR_XLEN_F32_V_Interrupt: CalleeSavedRegs<(add CSR_XLEN_F32_Interrupt, VREGS)>;

// Same as CSR_Interrupt, but including all 64-bit FP registers and all vector
// registers.
def CSR_XLEN_F64_V_Interrupt: CalleeSavedRegs<(add CSR_XLEN_F64_Interrupt,
(sequence "V%u", 0, 31))>;
def CSR_XLEN_F64_V_Interrupt: CalleeSavedRegs<(add CSR_XLEN_F64_Interrupt, VREGS)>;

// Same as CSR_Interrupt, but excluding X16-X31.
def CSR_Interrupt_RVE : CalleeSavedRegs<(sub CSR_Interrupt,
Expand Down
53 changes: 43 additions & 10 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1515,10 +1515,53 @@ RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
return Offset;
}

static MCRegister getRVVBaseRegister(const RISCVRegisterInfo &TRI,
const Register &Reg) {
MCRegister BaseReg = TRI.getSubReg(Reg, RISCV::sub_vrm1_0);
// If it's not a grouped vector register, it doesn't have subregister, so
// the base register is just itself.
if (BaseReg == RISCV::NoRegister)
BaseReg = Reg;
return BaseReg;
}

void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
BitVector &SavedRegs,
RegScavenger *RS) const {
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);

// In TargetFrameLowering::determineCalleeSaves, any vector register is marked
// as saved if any of its subregister is clobbered, this is not correct in
// vector registers. We only want the vector register to be marked as saved
// only if all of its subregisters are clobbered.
// For example:
// Original behavior: If v24 is marked, v24m2, v24m4, v24m8 are also marked.
// Correct behavior: v24m2 is marked only if v24 and v25 are marked.
const MachineRegisterInfo &MRI = MF.getRegInfo();
const MCPhysReg *CSRegs = MRI.getCalleeSavedRegs();
const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
for (unsigned i = 0; CSRegs[i]; ++i) {
unsigned CSReg = CSRegs[i];
// Only vector registers need special care.
if (!RISCV::VRRegClass.contains(getRVVBaseRegister(TRI, CSReg)))
continue;

SavedRegs.reset(CSReg);

auto SubRegs = TRI.subregs(CSReg);
// Set the register and it's all subregisters.
if (!MRI.def_empty(CSReg) || MRI.getUsedPhysRegsMask().test(CSReg)) {
SavedRegs.set(CSReg);
llvm::for_each(SubRegs, [&](unsigned Reg) { return SavedRegs.set(Reg); });
}

// Combine to super register if all of its subregisters are marked.
if (!SubRegs.empty() && llvm::all_of(SubRegs, [&](unsigned Reg) {
return SavedRegs.test(Reg);
}))
SavedRegs.set(CSReg);
}

// Unconditionally spill RA and FP only if the function uses a frame
// pointer.
if (hasFP(MF)) {
Expand Down Expand Up @@ -2107,16 +2150,6 @@ static unsigned getCalleeSavedRVVNumRegs(const Register &BaseReg) {
: 8;
}

static MCRegister getRVVBaseRegister(const RISCVRegisterInfo &TRI,
const Register &Reg) {
MCRegister BaseReg = TRI.getSubReg(Reg, RISCV::sub_vrm1_0);
// If it's not a grouped vector register, it doesn't have subregister, so
// the base register is just itself.
if (BaseReg == RISCV::NoRegister)
BaseReg = Reg;
return BaseReg;
}

void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, bool HasFP) const {
MachineFunction *MF = MBB.getParent();
Expand Down
Loading
Loading