Skip to content

[RISCV] Guard CFI emission code with MF.needsFrameMoves() #136060

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
107 changes: 67 additions & 40 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ static const std::pair<MCPhysReg, int8_t> FixedCSRFIQCIInterruptMap[] = {
/* -21, -22, -23, -24 are reserved */
};

/// Returns true if DWARF CFI instructions ("frame moves") should be emitted.
static bool needsDwarfCFI(const MachineFunction &MF) {
return MF.needsFrameMoves();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extracted this into a separate method because the check will need to be amended when/if Windows support arrives,
and/or if RISC-V backend learns to emit asynchronous (instruction precise) unwind info.

}

// For now we use x3, a.k.a gp, as pointer to shadow call stack.
// User should not use x3 in their asm.
static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
Expand Down Expand Up @@ -138,6 +143,9 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
.addImm(-SlotSize)
.setMIFlag(MachineInstr::FrameSetup);

if (!needsDwarfCFI(MF))
return;

// Emit a CFI instruction that causes SlotSize to be subtracted from the value
// of the shadow stack pointer when unwinding past this frame.
char DwarfSCSReg = TRI->getDwarfRegNum(SCSPReg, /*IsEH*/ true);
Expand Down Expand Up @@ -196,8 +204,10 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
.addReg(SCSPReg)
.addImm(-SlotSize)
.setMIFlag(MachineInstr::FrameDestroy);
// Restore the SCS pointer
CFIInstBuilder(MBB, MI, MachineInstr::FrameDestroy).buildRestore(SCSPReg);
if (needsDwarfCFI(MF)) {
// Restore the SCS pointer
CFIInstBuilder(MBB, MI, MachineInstr::FrameDestroy).buildRestore(SCSPReg);
}
}

// Get the ID of the libcall used for spilling and restoring callee saved
Expand Down Expand Up @@ -782,6 +792,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
MBBI = std::prev(MBBI, getRVVCalleeSavedInfo(MF, CSI).size() +
getUnmanagedCSI(MF, CSI).size());
CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
bool NeedsDwarfCFI = needsDwarfCFI(MF);

// 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
Expand Down Expand Up @@ -809,10 +820,12 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
alignTo((STI.getXLen() / 8) * LibCallRegs, getStackAlign());
RVFI->setLibCallStackSize(LibCallFrameSize);

CFIBuilder.buildDefCFAOffset(LibCallFrameSize);
for (const CalleeSavedInfo &CS : getPushOrLibCallsSavedInfo(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(),
MFI.getObjectOffset(CS.getFrameIdx()));
if (NeedsDwarfCFI) {
CFIBuilder.buildDefCFAOffset(LibCallFrameSize);
for (const CalleeSavedInfo &CS : getPushOrLibCallsSavedInfo(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(),
MFI.getObjectOffset(CS.getFrameIdx()));
}
}

// FIXME (note copied from Lanai): This appears to be overallocating. Needs
Expand All @@ -839,10 +852,12 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
}

if (RVFI->useQCIInterrupt(MF)) {
CFIBuilder.buildDefCFAOffset(QCIInterruptPushAmount);
for (const CalleeSavedInfo &CS : getQCISavedInfo(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(),
MFI.getObjectOffset(CS.getFrameIdx()));
if (NeedsDwarfCFI) {
CFIBuilder.buildDefCFAOffset(QCIInterruptPushAmount);
for (const CalleeSavedInfo &CS : getQCISavedInfo(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(),
MFI.getObjectOffset(CS.getFrameIdx()));
}
} else if (RVFI->isPushable(MF) && FirstFrameSetup != MBB.end() &&
isPush(FirstFrameSetup->getOpcode())) {
// Use available stack adjustment in push instruction to allocate additional
Expand All @@ -854,10 +869,12 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
FirstFrameSetup->getOperand(1).setImm(StackAdj);
StackSize -= StackAdj;

CFIBuilder.buildDefCFAOffset(RealStackSize - StackSize);
for (const CalleeSavedInfo &CS : getPushOrLibCallsSavedInfo(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(),
MFI.getObjectOffset(CS.getFrameIdx()));
if (NeedsDwarfCFI) {
CFIBuilder.buildDefCFAOffset(RealStackSize - StackSize);
for (const CalleeSavedInfo &CS : getPushOrLibCallsSavedInfo(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(),
MFI.getObjectOffset(CS.getFrameIdx()));
}
}

// Allocate space on the stack if necessary.
Expand All @@ -868,7 +885,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
bool DynAllocation =
MF.getInfo<RISCVMachineFunctionInfo>()->hasDynamicAllocation();
if (StackSize != 0)
allocateStack(MBB, MBBI, MF, StackSize, RealStackSize, /*EmitCFI=*/true,
allocateStack(MBB, MBBI, MF, StackSize, RealStackSize, NeedsDwarfCFI,
NeedProbe, ProbeSize, DynAllocation);

// The frame pointer is callee-saved, and code has been generated for us to
Expand All @@ -882,8 +899,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,

// Iterate over list of callee-saved registers and emit .cfi_offset
// directives.
for (const CalleeSavedInfo &CS : getUnmanagedCSI(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(), MFI.getObjectOffset(CS.getFrameIdx()));
if (NeedsDwarfCFI)
for (const CalleeSavedInfo &CS : getUnmanagedCSI(MF, CSI))
CFIBuilder.buildOffset(CS.getReg(),
MFI.getObjectOffset(CS.getFrameIdx()));

// Generate new FP.
if (hasFP(MF)) {
Expand All @@ -902,7 +921,8 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
MachineInstr::FrameSetup, getStackAlign());
}

CFIBuilder.buildDefCFA(FPReg, RVFI->getVarArgsSaveSize());
if (NeedsDwarfCFI)
CFIBuilder.buildDefCFA(FPReg, RVFI->getVarArgsSaveSize());
}

uint64_t SecondSPAdjustAmount = 0;
Expand All @@ -913,15 +933,15 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
"SecondSPAdjustAmount should be greater than zero");

allocateStack(MBB, MBBI, MF, SecondSPAdjustAmount,
getStackSizeWithRVVPadding(MF), !hasFP(MF), NeedProbe,
ProbeSize, DynAllocation);
getStackSizeWithRVVPadding(MF), NeedsDwarfCFI && !hasFP(MF),
NeedProbe, ProbeSize, DynAllocation);
}

if (RVVStackSize) {
if (NeedProbe) {
allocateAndProbeStackForRVV(MF, MBB, MBBI, DL, RVVStackSize,
MachineInstr::FrameSetup, !hasFP(MF),
DynAllocation);
MachineInstr::FrameSetup,
NeedsDwarfCFI && !hasFP(MF), DynAllocation);
} else {
// We must keep the stack pointer aligned through any intermediate
// updates.
Expand All @@ -930,14 +950,15 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
MachineInstr::FrameSetup, getStackAlign());
}

if (!hasFP(MF)) {
if (NeedsDwarfCFI && !hasFP(MF)) {
// Emit .cfi_def_cfa_expression "sp + StackSize + RVVStackSize * vlenb".
CFIBuilder.insertCFIInst(createDefCFAExpression(
*RI, SPReg, getStackSizeWithRVVPadding(MF), RVVStackSize / 8));
}

std::advance(MBBI, getRVVCalleeSavedInfo(MF, CSI).size());
emitCalleeSavedRVVPrologCFI(MBB, MBBI, hasFP(MF));
if (NeedsDwarfCFI)
emitCalleeSavedRVVPrologCFI(MBB, MBBI, hasFP(MF));
}

if (hasFP(MF)) {
Expand Down Expand Up @@ -1004,8 +1025,9 @@ void RISCVFrameLowering::deallocateStack(MachineFunction &MF,
MachineInstr::FrameDestroy, getStackAlign());
StackSize = 0;

CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
.buildDefCFAOffset(CFAOffset);
if (needsDwarfCFI(MF))
CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
.buildDefCFAOffset(CFAOffset);
}

void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
Expand Down Expand Up @@ -1045,6 +1067,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
std::next(MBBI, getRVVCalleeSavedInfo(MF, CSI).size());
CFIInstBuilder CFIBuilder(MBB, FirstScalarCSRRestoreInsn,
MachineInstr::FrameDestroy);
bool NeedsDwarfCFI = needsDwarfCFI(MF);

uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
Expand All @@ -1065,10 +1088,11 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
StackOffset::getScalable(RVVStackSize),
MachineInstr::FrameDestroy, getStackAlign());

if (!hasFP(MF))
CFIBuilder.buildDefCFA(SPReg, RealStackSize);

emitCalleeSavedRVVEpilogCFI(MBB, FirstScalarCSRRestoreInsn);
if (NeedsDwarfCFI) {
if (!hasFP(MF))
CFIBuilder.buildDefCFA(SPReg, RealStackSize);
emitCalleeSavedRVVEpilogCFI(MBB, FirstScalarCSRRestoreInsn);
}
}

if (FirstSPAdjustAmount) {
Expand All @@ -1084,7 +1108,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
StackOffset::getFixed(SecondSPAdjustAmount),
MachineInstr::FrameDestroy, getStackAlign());

if (!hasFP(MF))
if (NeedsDwarfCFI && !hasFP(MF))
CFIBuilder.buildDefCFAOffset(FirstSPAdjustAmount);
}

Expand All @@ -1105,7 +1129,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
getStackAlign());
}

if (hasFP(MF))
if (NeedsDwarfCFI && hasFP(MF))
CFIBuilder.buildDefCFA(SPReg, RealStackSize);

// Skip to after the restores of scalar callee-saved registers
Expand All @@ -1128,8 +1152,9 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
}

// Recover callee-saved registers.
for (const CalleeSavedInfo &CS : getUnmanagedCSI(MF, CSI))
CFIBuilder.buildRestore(CS.getReg());
if (NeedsDwarfCFI)
for (const CalleeSavedInfo &CS : getUnmanagedCSI(MF, CSI))
CFIBuilder.buildRestore(CS.getReg());

if (RVFI->isPushable(MF) && MBBI != MBB.end() && isPop(MBBI->getOpcode())) {
// Use available stack adjustment in pop instruction to deallocate stack
Expand All @@ -1148,14 +1173,16 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
auto NextI = next_nodbg(MBBI, MBB.end());
if (NextI == MBB.end() || NextI->getOpcode() != RISCV::PseudoRET) {
++MBBI;
CFIBuilder.setInsertPoint(MBBI);
if (NeedsDwarfCFI) {
CFIBuilder.setInsertPoint(MBBI);

for (const CalleeSavedInfo &CS : getPushOrLibCallsSavedInfo(MF, CSI))
CFIBuilder.buildRestore(CS.getReg());
for (const CalleeSavedInfo &CS : getPushOrLibCallsSavedInfo(MF, CSI))
CFIBuilder.buildRestore(CS.getReg());

// Update CFA offset. After CM_POP SP should be equal to CFA, so CFA
// offset should be a zero.
CFIBuilder.buildDefCFAOffset(0);
// Update CFA offset. After CM_POP SP should be equal to CFA, so CFA
// offset should be a zero.
CFIBuilder.buildDefCFAOffset(0);
}
}
}

Expand Down
24 changes: 12 additions & 12 deletions llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
Original file line number Diff line number Diff line change
Expand Up @@ -444,11 +444,11 @@ define void @sextw_removal_ccor(i1 %c, i32 signext %arg, i32 signext %arg1, i32
; RV64SFB-LABEL: sextw_removal_ccor:
; RV64SFB: # %bb.0: # %bb
; RV64SFB-NEXT: addi sp, sp, -32
; RV64SFB-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: mv s0, a3
; RV64SFB-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: andi a0, a0, 1
; RV64SFB-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: mv s1, a2
; RV64SFB-NEXT: beqz a0, .LBB15_4
; RV64SFB-NEXT: # %bb.3: # %bb
Expand All @@ -470,11 +470,11 @@ define void @sextw_removal_ccor(i1 %c, i32 signext %arg, i32 signext %arg1, i32
; ZICOND-LABEL: sextw_removal_ccor:
; ZICOND: # %bb.0: # %bb
; ZICOND-NEXT: addi sp, sp, -32
; ZICOND-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; ZICOND-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; ZICOND-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; ZICOND-NEXT: mv s0, a3
; ZICOND-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; ZICOND-NEXT: andi a0, a0, 1
; ZICOND-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; ZICOND-NEXT: mv s1, a2
; ZICOND-NEXT: beqz a0, .LBB15_4
; ZICOND-NEXT: # %bb.3: # %bb
Expand All @@ -496,11 +496,11 @@ define void @sextw_removal_ccor(i1 %c, i32 signext %arg, i32 signext %arg1, i32
; RV32SFB-LABEL: sextw_removal_ccor:
; RV32SFB: # %bb.0: # %bb
; RV32SFB-NEXT: addi sp, sp, -16
; RV32SFB-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: mv s0, a3
; RV32SFB-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: andi a0, a0, 1
; RV32SFB-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: mv s1, a2
; RV32SFB-NEXT: beqz a0, .LBB15_4
; RV32SFB-NEXT: # %bb.3: # %bb
Expand Down Expand Up @@ -563,11 +563,11 @@ define void @sextw_removal_ccaddw(i1 %c, i32 signext %arg, i32 signext %arg1, i3
; RV64SFB-LABEL: sextw_removal_ccaddw:
; RV64SFB: # %bb.0: # %bb
; RV64SFB-NEXT: addi sp, sp, -32
; RV64SFB-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: mv s1, a1
; RV64SFB-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: andi a0, a0, 1
; RV64SFB-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64SFB-NEXT: mv s0, a2
; RV64SFB-NEXT: beqz a0, .LBB16_4
; RV64SFB-NEXT: # %bb.3: # %bb
Expand All @@ -589,11 +589,11 @@ define void @sextw_removal_ccaddw(i1 %c, i32 signext %arg, i32 signext %arg1, i3
; ZICOND-LABEL: sextw_removal_ccaddw:
; ZICOND: # %bb.0: # %bb
; ZICOND-NEXT: addi sp, sp, -32
; ZICOND-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; ZICOND-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; ZICOND-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; ZICOND-NEXT: mv s1, a1
; ZICOND-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; ZICOND-NEXT: andi a0, a0, 1
; ZICOND-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; ZICOND-NEXT: mv s0, a2
; ZICOND-NEXT: beqz a0, .LBB16_4
; ZICOND-NEXT: # %bb.3: # %bb
Expand All @@ -615,11 +615,11 @@ define void @sextw_removal_ccaddw(i1 %c, i32 signext %arg, i32 signext %arg1, i3
; RV32SFB-LABEL: sextw_removal_ccaddw:
; RV32SFB: # %bb.0: # %bb
; RV32SFB-NEXT: addi sp, sp, -16
; RV32SFB-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: mv s1, a1
; RV32SFB-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: andi a0, a0, 1
; RV32SFB-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32SFB-NEXT: mv s0, a2
; RV32SFB-NEXT: beqz a0, .LBB16_4
; RV32SFB-NEXT: # %bb.3: # %bb
Expand Down
Loading