[llvm] Spill/restore FP/BP around instructions in which they are clobbered (PR #81048)
Eli Friedman via llvm-commits
llvm-commits at lists.llvm.org
Tue May 28 19:30:26 PDT 2024
================
@@ -4178,3 +4178,158 @@ void X86FrameLowering::restoreWinEHStackPointersInParent(
/*RestoreSP=*/IsSEH);
}
}
+
+static int computeSPAdjust4SpillFPBP(MachineFunction &MF,
+ const TargetRegisterClass *RC,
+ unsigned SpillRegNum) {
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+ unsigned AllocSize = TRI->getSpillSize(*RC) * SpillRegNum;
+ Align StackAlign = MF.getFrameInfo().getStackAlignment();
+ unsigned AlignedSize = alignTo(AllocSize, StackAlign);
+ return AlignedSize - AllocSize;
+}
+
+void X86FrameLowering::spillFPBPUsingSP(MachineFunction &MF,
+ MachineBasicBlock::iterator BeforeMI,
+ bool SpillFP, bool SpillBP) const {
+ const TargetRegisterClass *RC;
+ unsigned RegNum = 0;
+ MachineBasicBlock *MBB = BeforeMI->getParent();
+ DebugLoc DL = BeforeMI->getDebugLoc();
+
+ // Spill FP.
+ if (SpillFP) {
+ Register FP = TRI->getFrameRegister(MF);
+ if (STI.isTarget64BitILP32())
+ FP = Register(getX86SubSuperRegister(FP, 64));
+ RC = TRI->getMinimalPhysRegClass(FP);
+ ++RegNum;
+
+ BuildMI(*MBB, BeforeMI, DL,
+ TII.get(getPUSHOpcode(MF.getSubtarget<X86Subtarget>())))
+ .addReg(FP);
+ }
+
+ // Spill BP.
+ if (SpillBP) {
+ Register BP = TRI->getBaseRegister(MF);
+ if (STI.isTarget64BitILP32())
+ BP = Register(getX86SubSuperRegister(BP, 64));
+ RC = TRI->getMinimalPhysRegClass(BP);
+ ++RegNum;
+
+ BuildMI(*MBB, BeforeMI, DL,
+ TII.get(getPUSHOpcode(MF.getSubtarget<X86Subtarget>())))
+ .addReg(BP);
+ }
+
+ // Make sure SP is aligned.
+ int SPAdjust = computeSPAdjust4SpillFPBP(MF, RC, RegNum);
+ if (SPAdjust)
+ emitSPUpdate(*MBB, BeforeMI, DL, -SPAdjust, false);
+
+ // Emit unwinding information.
+ if (SpillFP && needsDwarfCFI(MF)) {
+ // Emit .cfi_remember_state to remember old frame.
+ unsigned CFIIndex =
+ MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr));
+ BuildMI(*MBB, BeforeMI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(CFIIndex);
+
+ // Setup new CFA value with DW_CFA_def_cfa_expression:
----------------
efriedma-quic wrote:
If you're spilling the base pointer, you shouldn't need to touch the unwind: we normally restore the stack pointer from fp, anyway.
If you're spilling the frame pointer, you'd have to do something complicated to get correct unwind; probably represent it as a separate function (.seh_endproc/.seh_startproc/etc.). You can't specify unwind opcodes outside the prolog.
https://github.com/llvm/llvm-project/pull/81048
More information about the llvm-commits
mailing list