Skip to content

Commit

Permalink
[RISCV][CFI] update prolog
Browse files Browse the repository at this point in the history
  • Loading branch information
dlav-sc committed Oct 30, 2024
1 parent 4f4ff18 commit b0227fb
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 47 deletions.
165 changes: 119 additions & 46 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,23 @@ getRVVCalleeSavedInfo(const MachineFunction &MF,
return RVVCSI;
}

static SmallVector<CalleeSavedInfo, 8> getPushOrLibCallsSavedInfo(const MachineFunction &MF, const std::vector<CalleeSavedInfo> &CSI) {
auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();

SmallVector<CalleeSavedInfo, 8> PushPopOrLibCallsCSI;
if (!RVFI->useSaveRestoreLibCalls(MF) && !RVFI->isPushable(MF))
return PushPopOrLibCallsCSI;

for (auto &CS : CSI) {
const auto *FII = llvm::find_if(
FixedCSRFIMap, [&](auto P) { return P.first == CS.getReg(); });
if (FII != std::end(FixedCSRFIMap))
PushPopOrLibCallsCSI.push_back(CS);
}

return PushPopOrLibCallsCSI;
}

void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
Expand Down Expand Up @@ -557,6 +574,8 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
// Determine the correct frame layout
determineFrameLayout(MF);

const auto &CSI = MFI.getCalleeSavedInfo();

// If libcalls are used to spill and restore callee-saved registers, the frame
// has two sections; the opaque section managed by the libcalls, and the
// section managed by MachineFrameInfo which can also hold callee saved
Expand All @@ -582,6 +601,23 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
unsigned LibCallFrameSize =
alignTo((STI.getXLen() / 8) * LibCallRegs, getStackAlign());
RVFI->setLibCallStackSize(LibCallFrameSize);

unsigned CFIIndex = MF.addFrameInst(
MCCFIInstruction::cfiDefCfaOffset(nullptr, LibCallFrameSize));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameSetup);

for (const auto &Entry : getPushOrLibCallsSavedInfo(MF, CSI)) {
int FrameIdx = Entry.getFrameIdx();
int64_t Offset = MFI.getObjectOffset(FrameIdx);
Register Reg = Entry.getReg();
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
nullptr, RI->getDwarfRegNum(Reg, true), Offset));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameSetup);
}
}

// FIXME (note copied from Lanai): This appears to be overallocating. Needs
Expand Down Expand Up @@ -616,23 +652,38 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48);
FirstFrameSetup->getOperand(1).setImm(Spimm);
StackSize -= Spimm;

unsigned CFIIndex = MF.addFrameInst(
MCCFIInstruction::cfiDefCfaOffset(nullptr, RealStackSize - StackSize));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameSetup);

for (const auto &Entry : getPushOrLibCallsSavedInfo(MF, CSI)) {
int FrameIdx = Entry.getFrameIdx();
int64_t Offset = MFI.getObjectOffset(FrameIdx);
Register Reg = Entry.getReg();
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
nullptr, RI->getDwarfRegNum(Reg, true), Offset));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameSetup);
}
}

if (StackSize != 0) {
// Allocate space on the stack if necessary.
RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg,
StackOffset::getFixed(-StackSize), MachineInstr::FrameSetup,
getStackAlign());
}

// Emit ".cfi_def_cfa_offset RealStackSize"
unsigned CFIIndex = MF.addFrameInst(
MCCFIInstruction::cfiDefCfaOffset(nullptr, RealStackSize));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameSetup);

const auto &CSI = MFI.getCalleeSavedInfo();
// Emit ".cfi_def_cfa_offset RealStackSize"
unsigned CFIIndex = MF.addFrameInst(
MCCFIInstruction::cfiDefCfaOffset(nullptr, RealStackSize));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameSetup);
}

// The frame pointer is callee-saved, and code has been generated for us to
// save it to the stack. We need to skip over the storing of callee-saved
Expand All @@ -644,7 +695,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,

// Iterate over list of callee-saved registers and emit .cfi_offset
// directives.
for (const auto &Entry : CSI) {
for (const auto &Entry : getUnmanagedCSI(MF, CSI)) {
int FrameIdx = Entry.getFrameIdx();
if (FrameIdx >= 0 &&
MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector)
Expand Down Expand Up @@ -759,13 +810,14 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
void RISCVFrameLowering::deallocateStack(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, uint64_t StackSize,
const DebugLoc &DL, uint64_t &StackSize,
int64_t CFAOffset) const {
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
const RISCVInstrInfo *TII = STI.getInstrInfo();

RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize),
MachineInstr::FrameDestroy, getStackAlign());
StackSize = 0;

unsigned CFIIndex =
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset));
Expand Down Expand Up @@ -878,7 +930,6 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
// have vector objects in stack.
if (RestoreSPFromFP) {
assert(hasFP(MF) && "frame pointer should not have been eliminated");

RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg,
StackOffset::getFixed(-FPOffset), MachineInstr::FrameDestroy,
getStackAlign());
Expand All @@ -905,6 +956,16 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
return;
}

// Recover callee-saved registers.
for (const auto &Entry : getUnmanagedCSI(MF, CSI)) {
Register Reg = Entry.getReg();
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
nullptr, RI->getDwarfRegNum(Reg, true)));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameDestroy);
}

bool ApplyPop = RVFI->isPushable(MF) && MBBI != MBB.end() &&
MBBI->getOpcode() == RISCV::CM_POP;
if (ApplyPop) {
Expand All @@ -920,29 +981,31 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
deallocateStack(MF, MBB, MBBI, DL, StackSize,
/*stack_adj of cm.pop instr*/ RealStackSize - StackSize);

++MBBI;
// Update CFA offset. After CM_POP SP should be equal to CFA, so CFA offset
// should be a zero.
unsigned CFIIndex =
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 0));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameDestroy);
}
auto NextI = next_nodbg(MBBI, MBB.end());
if (NextI == MBB.end() || NextI->getOpcode() != RISCV::PseudoRET) {
++MBBI;

// Recover callee-saved registers.
for (const auto &Entry : CSI) {
Register Reg = Entry.getReg();
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
nullptr, RI->getDwarfRegNum(Reg, true)));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameDestroy);
}
for (const auto &Entry : getPushOrLibCallsSavedInfo(MF, CSI)) {
Register Reg = Entry.getReg();
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore(
nullptr, RI->getDwarfRegNum(Reg, true)));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameDestroy);
}

// Deallocate stack if we didn't already do it during cm.pop handling and
// StackSize isn't a zero
if (StackSize != 0 && !ApplyPop)
// Update CFA offset. After CM_POP SP should be equal to CFA, so CFA offset
// should be a zero.
unsigned CFIIndex =
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 0));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameDestroy);
}
}

// Deallocate stack if StackSize isn't a zero yet
if (StackSize != 0)
deallocateStack(MF, MBB, MBBI, DL, StackSize, 0);

// Emit epilogue for shadow call stack.
Expand Down Expand Up @@ -1629,6 +1692,22 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters(
return true;
}

static unsigned getCaleeSavedRVVNumRegs(const Register &BaseReg) {
return RISCV::VRRegClass.contains(BaseReg) ? 1
: RISCV::VRM2RegClass.contains(BaseReg) ? 2
: RISCV::VRM4RegClass.contains(BaseReg) ? 4
: 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 All @@ -1655,15 +1734,8 @@ void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
// Insert the spill to the stack frame.
int FI = CS.getFrameIdx();
if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) {
MCRegister BaseReg = TRI.getSubReg(CS.getReg(), 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 = CS.getReg();
unsigned NumRegs = RISCV::VRRegClass.contains(CS.getReg()) ? 1
: RISCV::VRM2RegClass.contains(CS.getReg()) ? 2
: RISCV::VRM4RegClass.contains(CS.getReg()) ? 4
: 8;
MCRegister BaseReg = getRVVBaseRegister(TRI, CS.getReg());
unsigned NumRegs = getCaleeSavedRVVNumRegs(CS.getReg());
for (unsigned i = 0; i < NumRegs; ++i) {
unsigned CFIIndex = MF->addFrameInst(createDefCFAOffset(
TRI, BaseReg + i, -FixedSize, MFI.getObjectOffset(FI) / 8 + i));
Expand All @@ -1681,15 +1753,16 @@ void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
const MachineFrameInfo &MFI = MF->getFrameInfo();
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
const TargetInstrInfo &TII = *STI.getInstrInfo();
const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
DebugLoc DL = MBB.findDebugLoc(MI);

const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, MFI.getCalleeSavedInfo());
for (auto &CS : RVVCSI) {
int FI = CS.getFrameIdx();
if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) {
Register Reg = CS.getReg();
MCRegister BaseReg = getRVVBaseRegister(TRI, CS.getReg());
unsigned NumRegs = getCaleeSavedRVVNumRegs(CS.getReg());
for (unsigned i = 0; i < NumRegs; ++i) {
unsigned CFIIndex = MF->addFrameInst(MCCFIInstruction::createRestore(
nullptr, RI->getDwarfRegNum(Reg, true)));
nullptr, RI->getDwarfRegNum(BaseReg + i, true)));
BuildMI(MBB, MI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlag(MachineInstr::FrameDestroy);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVFrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class RISCVFrameLowering : public TargetFrameLowering {
MachineBasicBlock::iterator MI) const;
void deallocateStack(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
uint64_t StackSize, int64_t CFAOffset) const;
uint64_t &StackSize, int64_t CFAOffset) const;

std::pair<int64_t, Align>
assignRVVStackObjectOffsets(MachineFunction &MF) const;
Expand Down

0 comments on commit b0227fb

Please sign in to comment.