Skip to content

Commit

Permalink
[RISCV] fix SP recovery in the function epilogue
Browse files Browse the repository at this point in the history
This patch fixes SP register recovery in the function epilogue.
  • Loading branch information
dlav-sc committed Oct 2, 2024
1 parent d0f6777 commit b51b26e
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 37 deletions.
105 changes: 68 additions & 37 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,19 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
}
}

void RISCVFrameLowering::deallocateStack(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, uint64_t StackSize,
int64_t CFAOffset) const {
const RISCVRegisterInfo *RI = STI.getRegisterInfo();

Register SPReg = getSPReg(STI);

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

void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
Expand Down Expand Up @@ -786,20 +799,51 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
--MBBI;
}

const auto &CSI = getUnmanagedCSI(MF, MFI.getCalleeSavedInfo());
const auto &CSI = MFI.getCalleeSavedInfo();

// Skip to before the restores of scalar callee-saved registers
// FIXME: assumes exactly one instruction is used to restore each
// callee-saved register.
auto LastFrameDestroy = MBBI;
if (!CSI.empty())
LastFrameDestroy = std::prev(MBBI, CSI.size());
auto LastFrameDestroy = std::prev(MBBI, getUnmanagedCSI(MF, CSI).size());

uint64_t RealStackSize = getStackSizeWithRVVPadding(MF);
uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize();
uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
: getStackSizeWithRVVPadding(MF);
uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
: getStackSizeWithRVVPadding(MF) -
RVFI->getReservedSpillsSize();
uint64_t FPOffset = FirstSPAdjustAmount ? FirstSPAdjustAmount
: getStackSizeWithRVVPadding(MF) -
RVFI->getVarArgsSaveSize();
uint64_t RVVStackSize = RVFI->getRVVStackSize();

bool RestoreFP = RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
!hasReservedCallFrame(MF);

if (RVVStackSize) {
// If restoreFP the stack pointer will be restored using the frame pointer
// value.
if (!RestoreFP) {
adjustStackForRVV(MF, MBB, LastFrameDestroy, DL, RVVStackSize,
MachineInstr::FrameDestroy);
}
}

if (FirstSPAdjustAmount) {
uint64_t SecondSPAdjustAmount =
getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount;
assert(SecondSPAdjustAmount > 0 &&
"SecondSPAdjustAmount should be greater than zero");

// If restoreFP the stack pointer will be restored using the frame pointer
// value.
if (!RestoreFP) {
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg,
StackOffset::getFixed(SecondSPAdjustAmount),
MachineInstr::FrameDestroy, getStackAlign());
}
}

// Restore the stack pointer using the value of the frame pointer. Only
// necessary if the stack pointer was modified, meaning the stack size is
// unknown.
Expand All @@ -810,50 +854,37 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
// normally it's just checking the variable sized object is present or not
// is enough, but we also don't preserve that at prologue/epilogue when
// have vector objects in stack.
if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
!hasReservedCallFrame(MF)) {
if (RestoreFP) {
assert(hasFP(MF) && "frame pointer should not have been eliminated");
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg,
StackOffset::getFixed(-FPOffset),
MachineInstr::FrameDestroy, getStackAlign());
} else {
if (RVVStackSize)
adjustStackForRVV(MF, MBB, LastFrameDestroy, DL, RVVStackSize,
MachineInstr::FrameDestroy);
}

uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
if (FirstSPAdjustAmount) {
uint64_t SecondSPAdjustAmount =
getStackSizeWithRVVPadding(MF) - FirstSPAdjustAmount;
assert(SecondSPAdjustAmount > 0 &&
"SecondSPAdjustAmount should be greater than zero");

RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg,
StackOffset::getFixed(SecondSPAdjustAmount),
MachineInstr::FrameDestroy, getStackAlign());
RI->adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg,
StackOffset::getFixed(-FPOffset), MachineInstr::FrameDestroy,
getStackAlign());
}

if (FirstSPAdjustAmount)
StackSize = FirstSPAdjustAmount;

if (RVFI->isPushable(MF) && MBBI != MBB.end() &&
MBBI->getOpcode() == RISCV::CM_POP) {
bool ApplyPop = RVFI->isPushable(MF) && MBBI != MBB.end() &&
MBBI->getOpcode() == RISCV::CM_POP;
if (ApplyPop) {
// Use available stack adjustment in pop instruction to deallocate stack
// space. Align the stack size down to a multiple of 16. This is needed for
// RVE.
// FIXME: Can we increase the stack size to a multiple of 16 instead?
uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48);
MBBI->getOperand(1).setImm(Spimm);
StackSize -= Spimm;
}

// Deallocate stack
if (StackSize != 0) {
RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(StackSize),
MachineInstr::FrameDestroy, getStackAlign());
if (StackSize != 0)
deallocateStack(MF, MBB, MBBI, DL, StackSize,
/*stack_adj of cm.pop instr*/ RealStackSize - StackSize);

++MBBI;
}

// Deallocate stack if StackSize isn't a zero and if we didn't already do it
// during cm.pop handling.
if (StackSize != 0 && !ApplyPop)
deallocateStack(MF, MBB, MBBI, DL, StackSize, 0);

// Emit epilogue for shadow call stack.
emitSCSEpilogue(MF, MBB, MBBI, DL);
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ class RISCVFrameLowering : public TargetFrameLowering {
void emitCalleeSavedRVVPrologCFI(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
bool HasFP) const;
void deallocateStack(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
uint64_t StackSize, int64_t CFAOffset) const;

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

0 comments on commit b51b26e

Please sign in to comment.