[llvm] Spill/restore FP/BP around instructions in which they are clobbered (PR #81048)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 2 14:41:27 PDT 2024
================
@@ -4231,3 +4231,325 @@ void X86FrameLowering::restoreWinEHStackPointersInParent(
/*RestoreSP=*/IsSEH);
}
}
+
+static int computeSPAdjust4SpillFPBP(MachineFunction &MF,
+ const TargetRegisterClass *RC,
+ unsigned NumSpilledRegs) {
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+ unsigned AllocSize = TRI->getSpillSize(*RC) * NumSpilledRegs;
+ Align StackAlign = MF.getSubtarget().getFrameLowering()->getStackAlign();
+ unsigned AlignedSize = alignTo(AllocSize, StackAlign);
+ return AlignedSize - AllocSize;
+}
+
+void X86FrameLowering::spillFPBPUsingSP(MachineFunction &MF,
+ MachineBasicBlock::iterator BeforeMI,
+ bool SpillFP, bool SpillBP) const {
+ assert(SpillFP || SpillBP);
+
+ const TargetRegisterClass *RC;
+ unsigned NumRegs = 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);
+ ++NumRegs;
+
+ BuildMI(*MBB, BeforeMI, DL,
+ TII.get(getPUSHOpcode(MF.getSubtarget<X86Subtarget>())))
+ .addReg(FP);
+ }
+
+ // Spill BP.
+ if (SpillBP) {
+ Register BP = TRI->getBaseRegister();
+ if (STI.isTarget64BitILP32())
+ BP = Register(getX86SubSuperRegister(BP, 64));
+ RC = TRI->getMinimalPhysRegClass(BP);
+ ++NumRegs;
+
+ BuildMI(*MBB, BeforeMI, DL,
+ TII.get(getPUSHOpcode(MF.getSubtarget<X86Subtarget>())))
+ .addReg(BP);
+ }
+
+ // Make sure SP is aligned.
+ int SPAdjust = computeSPAdjust4SpillFPBP(MF, RC, NumRegs);
+ 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:
+ // DW_OP_breg7+offset, DW_OP_deref, DW_OP_consts 16, DW_OP_plus
+ SmallString<64> CfaExpr;
+ uint8_t buffer[16];
+ int Offset = SPAdjust;
+ if (SpillBP)
+ Offset += TRI->getSpillSize(*RC);
+ // If BeforeMI is a frame setup instruction, we need to adjust the position
+ // and offset of the new cfi instruction.
+ if (TII.isFrameSetup(*BeforeMI)) {
+ Offset += alignTo(TII.getFrameSize(*BeforeMI), getStackAlign());
+ BeforeMI = std::next(BeforeMI);
+ }
+ Register StackPtr = TRI->getStackRegister();
+ if (STI.isTarget64BitILP32())
+ StackPtr = Register(getX86SubSuperRegister(StackPtr, 64));
+ unsigned DwarfStackPtr = TRI->getDwarfRegNum(StackPtr, true);
+ CfaExpr.push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfStackPtr));
+ CfaExpr.append(buffer, buffer + encodeSLEB128(Offset, buffer));
+ CfaExpr.push_back(dwarf::DW_OP_deref);
+ CfaExpr.push_back(dwarf::DW_OP_consts);
+ CfaExpr.append(buffer, buffer + encodeSLEB128(SlotSize * 2, buffer));
+ CfaExpr.push_back((uint8_t)dwarf::DW_OP_plus);
+
+ SmallString<64> DefCfaExpr;
+ DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
+ DefCfaExpr.append(buffer, buffer + encodeSLEB128(CfaExpr.size(), buffer));
+ DefCfaExpr.append(CfaExpr.str());
+ BuildCFI(*MBB, BeforeMI, DL,
+ MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str()),
+ MachineInstr::FrameSetup);
+ }
+}
+
+void X86FrameLowering::restoreFPBPUsingSP(MachineFunction &MF,
+ MachineBasicBlock::iterator AfterMI,
+ bool SpillFP, bool SpillBP) const {
+ assert(SpillFP || SpillBP);
+
+ Register FP, BP;
+ const TargetRegisterClass *RC;
+ unsigned NumRegs = 0;
+ if (SpillFP) {
+ FP = TRI->getFrameRegister(MF);
+ if (STI.isTarget64BitILP32())
+ FP = Register(getX86SubSuperRegister(FP, 64));
+ RC = TRI->getMinimalPhysRegClass(FP);
+ ++NumRegs;
+ }
+ if (SpillBP) {
+ BP = TRI->getBaseRegister();
+ if (STI.isTarget64BitILP32())
+ BP = Register(getX86SubSuperRegister(BP, 64));
+ RC = TRI->getMinimalPhysRegClass(BP);
+ ++NumRegs;
+ }
+
+ // Adjust SP so it points to spilled FP or BP.
+ MachineBasicBlock *MBB = AfterMI->getParent();
+ MachineBasicBlock::iterator Pos = std::next(AfterMI);
+ DebugLoc DL = AfterMI->getDebugLoc();
+ int SPAdjust = computeSPAdjust4SpillFPBP(MF, RC, NumRegs);
+ if (SPAdjust)
+ emitSPUpdate(*MBB, Pos, DL, SPAdjust, false);
+
+ // Restore BP.
+ if (SpillBP) {
+ BuildMI(*MBB, Pos, DL,
+ TII.get(getPOPOpcode(MF.getSubtarget<X86Subtarget>())), BP);
+ }
+
+ // Restore FP.
+ if (SpillFP) {
+ BuildMI(*MBB, Pos, DL,
+ TII.get(getPOPOpcode(MF.getSubtarget<X86Subtarget>())), FP);
+
+ // Emit unwinding information.
+ if (needsDwarfCFI(MF)) {
+ // Restore original frame with .cfi_restore_state.
+ unsigned CFIIndex =
+ MF.addFrameInst(MCCFIInstruction::createRestoreState(nullptr));
+ BuildMI(*MBB, Pos, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(CFIIndex);
+ }
+ }
+}
+
+bool X86FrameLowering::skipSpillFPBP(
+ MachineFunction &MF, MachineBasicBlock::reverse_iterator &MI) const {
+ if (MI->getOpcode() == X86::LCMPXCHG16B_SAVE_RBX) {
+ // The pseudo instruction LCMPXCHG16B_SAVE_RBX is generated in the form
+ // SaveRbx = COPY RBX
+ // SaveRbx = LCMPXCHG16B_SAVE_RBX ..., SaveRbx, implicit-def rbx
+ // And later LCMPXCHG16B_SAVE_RBX is expanded to restore RBX from SaveRbx.
+ // We should skip this instruction sequence.
+ int FI;
+ unsigned Reg;
+ while (!(MI->getOpcode() == TargetOpcode::COPY &&
+ MI->getOperand(1).getReg() == X86::RBX) &&
+ !((Reg = TII.isStoreToStackSlot(*MI, FI)) && Reg == X86::RBX))
+ ++MI;
+ return true;
+ }
+ return false;
+}
+
+static bool isFPBPAccess(const MachineInstr &MI, Register FP, Register BP,
+ const TargetRegisterInfo *TRI, bool &AccessFP,
+ bool &AccessBP) {
+ AccessFP = AccessBP = false;
+ if (FP) {
+ if (MI.findRegisterUseOperandIdx(FP, TRI, false) != -1 ||
+ MI.findRegisterDefOperandIdx(FP, TRI, false, true) != -1)
+ AccessFP = true;
+ }
+ if (BP) {
+ if (MI.findRegisterUseOperandIdx(BP, TRI, false) != -1 ||
+ MI.findRegisterDefOperandIdx(BP, TRI, false, true) != -1)
+ AccessBP = true;
+ }
+ return AccessFP || AccessBP;
+}
+
+// Invoke instruction has been lowered to normal function call. We try to figure
+// out if MI comes from Invoke.
+// Do we have any better method?
----------------
weiguozhi wrote:
Good point. I will do detection work in a separate patch.
https://github.com/llvm/llvm-project/pull/81048
More information about the llvm-commits
mailing list