diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -135,6 +135,7 @@ None, // Omit all frame pointers. NonLeaf, // Keep non-leaf frame pointers. All, // Keep all frame pointers. + ShrinkWrap, // Shrink wrap frame pointers. }; static StringRef getFramePointerKindName(FramePointerKind Kind) { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2536,6 +2536,7 @@ def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group; def fno_objc_weak : Flag<["-"], "fno-objc-weak">, Group, Flags<[CC1Option]>; def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group; +def fno_frame_pointer_shrink_wrap : Flag<["-"], "fno-frame-pointer-shrink-wrap">, Group; defm operator_names : BoolFOption<"operator-names", LangOpts<"CXXOperatorNames">, Default, NegFlag, @@ -2639,6 +2640,7 @@ BothFlags<[CC1Option, NoDriverOption], " to avoid heapifying local blocks">>; def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group; +def fframe_pointer_shrink_wrap : Flag<["-"], "fframe-pointer-shrink-wrap">, Group; def fopenmp : Flag<["-"], "fopenmp">, Group, Flags<[CC1Option, NoArgumentUnused, FlangOption, FC1Option]>, HelpText<"Parse OpenMP pragmas and generate parallel code.">; def fno_openmp : Flag<["-"], "fno-openmp">, Group, Flags<[NoArgumentUnused]>; @@ -5600,8 +5602,8 @@ HelpText<"Enable additional debug output">, MarshallingInfoString>; def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">, - HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,none">, - NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "None"]>, + HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,none,shrink-wrap">, + NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "None", "ShrinkWrap"]>, MarshallingInfoEnum, "None">; def mabi_EQ_ieeelongdouble : Flag<["-"], "mabi=ieeelongdouble">, HelpText<"Use IEEE 754 quadruple-precision for long double">, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1862,6 +1862,11 @@ // This is the default behavior. break; case CodeGenOptions::FramePointerKind::NonLeaf: + FpKind = "non-leaf"; + break; + case CodeGenOptions::FramePointerKind::ShrinkWrap: + FpKind = "shrink-wrap"; + break; case CodeGenOptions::FramePointerKind::All: FuncAttrs.addAttribute("frame-pointer", CodeGenOptions::getFramePointerKindName( diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -915,6 +915,9 @@ case CodeGenOptions::FramePointerKind::NonLeaf: getModule().setFramePointer(llvm::FramePointerKind::NonLeaf); break; + case CodeGenOptions::FramePointerKind::ShrinkWrap: + getModule().setFramePointer(llvm::FramePointerKind::ShrinkWrap); + break; case CodeGenOptions::FramePointerKind::All: getModule().setFramePointer(llvm::FramePointerKind::All); break; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -532,12 +532,18 @@ Args.hasFlag(options::OPT_momit_leaf_frame_pointer, options::OPT_mno_omit_leaf_frame_pointer, Triple.isAArch64() || Triple.isPS() || Triple.isVE()); + bool ShrinkWrap = + Args.hasFlag(options::OPT_fframe_pointer_shrink_wrap, + options::OPT_fno_frame_pointer_shrink_wrap, false); if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) || (!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) { if (OmitLeafFP) return CodeGenOptions::FramePointerKind::NonLeaf; return CodeGenOptions::FramePointerKind::All; } + // TODO: Revistit this ordering. + if (ShrinkWrap) + return CodeGenOptions::FramePointerKind::ShrinkWrap; return CodeGenOptions::FramePointerKind::None; } @@ -5314,9 +5320,13 @@ case CodeGenOptions::FramePointerKind::NonLeaf: FPKeepKindStr = "-mframe-pointer=non-leaf"; break; + case CodeGenOptions::FramePointerKind::ShrinkWrap: + FPKeepKindStr = "-mframe-pointer=shrink-wrap"; + break; case CodeGenOptions::FramePointerKind::All: FPKeepKindStr = "-mframe-pointer=all"; break; + } assert(FPKeepKindStr && "unknown FramePointerKind"); CmdArgs.push_back(FPKeepKindStr); diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -72,6 +72,8 @@ /// stack frame to the given stream as a debugging tool. MachineFunctionPass *createStackFrameLayoutAnalysisPass(); + MachineFunctionPass* createFramePointerShrinkWrapPass(); + /// MIRPrinting pass - this pass prints out the LLVM IR into the given stream /// using the MIR serialization format. MachineFunctionPass *createPrintMIRPass(raw_ostream &OS); @@ -241,6 +243,8 @@ /// MachineFunctionPrinterPass - This pass prints out MachineInstr's. extern char &MachineFunctionPrinterPassID; + extern char &FramePointerShrinkWrapPassID; + /// MIRPrintingPass - this pass prints out the LLVM IR using the MIR /// serialization format. extern char &MIRPrintingPassID; diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -279,6 +279,12 @@ /// has variable sized allocas or if frame pointer elimination is disabled. virtual bool hasFP(const MachineFunction &MF) const = 0; + /// hasFPShrinkWrap - Return true if the specified function should shrink wrap + /// the frame pointer register. This is true only if the function has frame + /// pointers and the FP shrink wrap option is set. + virtual bool hasFPShrinkWrap(const MachineFunction &MF) const {return false;} + + /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is /// not required, we reserve argument space for call sites in the function /// immediately on entry to the current function. This eliminates the need for diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -1129,6 +1129,8 @@ /// for values allocated in the current stack frame. virtual Register getFrameRegister(const MachineFunction &MF) const = 0; + virtual Register getFPReg(const MachineFunction &MF) const{return getFrameRegister(MF);} + /// Mark a register and all its aliases as reserved in the given set. void markSuperRegs(BitVector &RegisterSet, MCRegister Reg) const; diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -137,6 +137,8 @@ void initializeFixupStatepointCallerSavedPass(PassRegistry&); void initializeFlattenCFGLegacyPassPass(PassRegistry &); void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&); +void initializeForwardControlFlowIntegrityPass(PassRegistry&); +void initializeFramePointerShrinkWrapPassPass(PassRegistry &); void initializeFuncletLayoutPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); diff --git a/llvm/include/llvm/Support/CodeGen.h b/llvm/include/llvm/Support/CodeGen.h --- a/llvm/include/llvm/Support/CodeGen.h +++ b/llvm/include/llvm/Support/CodeGen.h @@ -88,7 +88,7 @@ }; // Specify what functions should keep the frame pointer. - enum class FramePointerKind { None, NonLeaf, All }; + enum class FramePointerKind { None, NonLeaf, All, ShrinkWrap }; // Specify what type of zeroing callee-used registers. namespace ZeroCallUsedRegs { diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -65,6 +65,7 @@ FEntryInserter.cpp FinalizeISel.cpp FixupStatepointCallerSaved.cpp + FramePointerShrinkWrap.cpp FuncletLayout.cpp GCMetadata.cpp GCMetadataPrinter.cpp diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -199,7 +199,9 @@ clEnumValN(FramePointerKind::NonLeaf, "non-leaf", "Disable frame pointer elimination for non-leaf frame"), clEnumValN(FramePointerKind::None, "none", - "Enable frame pointer elimination"))); + "Enable frame pointer elimination"), + clEnumValN(FramePointerKind::ShrinkWrap, "shrink-wrap", + "Enable frame pointer shrink-wrap"))); CGBINDOPT(FramePointerUsage); static cl::opt EnableUnsafeFPMath( @@ -653,6 +655,8 @@ NewAttrs.addAttribute("frame-pointer", "all"); else if (getFramePointerUsage() == FramePointerKind::NonLeaf) NewAttrs.addAttribute("frame-pointer", "non-leaf"); + else if (getFramePointerUsage() == FramePointerKind::ShrinkWrap) + NewAttrs.addAttribute("frame-pointer", "shrink-wrap"); else if (getFramePointerUsage() == FramePointerKind::None) NewAttrs.addAttribute("frame-pointer", "none"); } diff --git a/llvm/lib/CodeGen/FramePointerShrinkWrap.cpp b/llvm/lib/CodeGen/FramePointerShrinkWrap.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/FramePointerShrinkWrap.cpp @@ -0,0 +1,136 @@ +//===-- MachineFunctionPrinterPass.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// MachineFunctionPrinterPass implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/PrintPasses.h" +#include "llvm/InitializePasses.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +namespace { +/// FramePointerShrinkWrapPass - Pass marks the frame pointer as a live register +/// +struct FramePointerShrinkWrapPass : public MachineFunctionPass { + static char ID; + + FramePointerShrinkWrapPass() : MachineFunctionPass(ID) {} + + StringRef getPassName() const override { + return "Frame Pointer Shrink Wrappng Pass"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addUsedIfAvailable(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + // TODO: don't copy these functions from target/x86 + + bool hasFP(const MachineFunction &MF) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + auto &STI = MF.getSubtarget(); + auto *TRI = STI.getRegisterInfo(); + return (MF.getTarget().Options.DisableFramePointerElim(MF) || + TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || + MFI.isFrameAddressTaken() || MFI.hasOpaqueSPAdjustment() || + MF.callsUnwindInit() || MF.hasEHFunclets() || MF.callsEHReturn() || + MFI.hasStackMap() || MFI.hasPatchPoint() || + (MF.getTarget().getMCAsmInfo()->usesWindowsCFI() && + MFI.hasCopyImplyingStackAdjustment())); + } + + bool hasFPShrinkWrap(const MachineFunction &MF) const { + if (hasFP(MF)) + return false; + const Function &F = MF.getFunction(); + if (!F.hasFnAttribute("frame-pointer")) + return false; + StringRef FP = F.getFnAttribute("frame-pointer").getValueAsString(); + return FP == "shrink-wrap"; + } + + bool runOnMachineFunction(MachineFunction &MF) override { + // only modify functions when shrink warp is enabled + if (!hasFPShrinkWrap(MF)) + return false; + + auto &STI = MF.getSubtarget(); + auto *TII = STI.getInstrInfo(); + auto *TRI = STI.getRegisterInfo(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + Register FramePtr = TRI->getFPReg(MF); + + // TODO: Rematerialize FP instead. + + // add virtual reg in entry block, this is going to hold FP + const TargetRegisterClass *RegClass = TRI->getPointerRegClass(MF); + auto VReg = MRI.createVirtualRegister(RegClass); + auto &Entry = MF.front(); + auto I = Entry.begin(); + + Entry.addLiveIn(FramePtr); + + auto DL = I->getDebugLoc(); + BuildMI(Entry, Entry.begin(), DL, TII->get(TargetOpcode::COPY), VReg) + .addReg(FramePtr); + + // iterate over blocks + for (auto &MBB : MF) { + // iterate over instructions + for (MachineBasicBlock::iterator MBBI = MBB.begin(); MBBI != MBB.end(); + ++MBBI) { + if (MBBI->isCall()) { + DL = MBBI->getDebugLoc(); + MBBI = BuildMI(MBB, *MBBI, DL, TII->get(TargetOpcode::COPY), FramePtr) + .addReg(VReg); + MBBI++; + } + } + } + + return true; + } +}; + +char FramePointerShrinkWrapPass::ID = 0; +} // namespace + +char &llvm::FramePointerShrinkWrapPassID = FramePointerShrinkWrapPass::ID; +INITIALIZE_PASS(FramePointerShrinkWrapPass, "frame-pointer-shrink-wrap", + "Frame Pointer Shrink Wrap", false, false) + +namespace llvm { +/// Returns a newly-created MachineFunction Printer pass. The +/// default banner is empty. +/// +MachineFunctionPass *createFramePointerShrinkWrapPass() { + return new FramePointerShrinkWrapPass(); +} + +} // namespace llvm diff --git a/llvm/lib/CodeGen/TargetOptionsImpl.cpp b/llvm/lib/CodeGen/TargetOptionsImpl.cpp --- a/llvm/lib/CodeGen/TargetOptionsImpl.cpp +++ b/llvm/lib/CodeGen/TargetOptionsImpl.cpp @@ -32,6 +32,8 @@ StringRef FP = F.getFnAttribute("frame-pointer").getValueAsString(); if (FP == "all") return true; + if (FP == "shrink-wrap") + return false; if (FP == "non-leaf") return MF.getFrameInfo().hasCalls(); if (FP == "none") diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -1136,6 +1136,8 @@ if (TM->Options.EnableIPRA) addPass(createRegUsageInfoPropPass()); + addPass(createFramePointerShrinkWrapPass()); + // Run pre-ra passes. addPreRegAlloc(); diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -349,6 +349,9 @@ case FramePointerKind::NonLeaf: B.addAttribute("frame-pointer", "non-leaf"); break; + case FramePointerKind::ShrinkWrap: + B.addAttribute("frame-pointer", "shrink-wrap"); + break; case FramePointerKind::All: B.addAttribute("frame-pointer", "all"); break; diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2187,7 +2187,7 @@ if (Attrs.hasFnAttr("frame-pointer")) { StringRef FP = Attrs.getFnAttr("frame-pointer").getValueAsString(); - if (FP != "all" && FP != "non-leaf" && FP != "none") + if (FP != "all" && FP != "non-leaf" && FP != "shrink-wrap" && FP != "none") CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V); } diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h --- a/llvm/lib/Target/X86/X86FrameLowering.h +++ b/llvm/lib/Target/X86/X86FrameLowering.h @@ -104,6 +104,7 @@ const TargetRegisterInfo *TRI) const override; bool hasFP(const MachineFunction &MF) const override; + bool hasFPShrinkWrap(const MachineFunction &MF) const override; bool hasReservedCallFrame(const MachineFunction &MF) const override; bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override; bool needsFrameIndexResolution(const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -104,6 +104,16 @@ (isWin64Prologue(MF) && MFI.hasCopyImplyingStackAdjustment())); } +bool X86FrameLowering::hasFPShrinkWrap(const MachineFunction &MF) const { + if (hasFP(MF)) + return false; + const Function &F = MF.getFunction(); + if (!F.hasFnAttribute("frame-pointer")) + return false; + StringRef FP = F.getFnAttribute("frame-pointer").getValueAsString(); + return FP == "shrink-wrap"; +} + static unsigned getSUBriOpcode(bool IsLP64, int64_t Imm) { if (IsLP64) { if (isInt<8>(Imm)) @@ -1492,6 +1502,7 @@ MF.hasEHFunclets() && Personality == EHPersonality::CoreCLR; bool IsClrFunclet = IsFunclet && FnHasClrFunclet; bool HasFP = hasFP(MF); + bool HasFPShrinkWrap = hasFPShrinkWrap(MF); bool IsWin64Prologue = isWin64Prologue(MF); bool NeedsWin64CFI = IsWin64Prologue && Fn.needsUnwindTableEntry(); // FIXME: Emit FPO data for EH funclets. @@ -1573,7 +1584,7 @@ !MF.shouldSplitStack()) { // Regular stack uint64_t MinSize = X86FI->getCalleeSavedFrameSize() - X86FI->getTCReturnAddrDelta(); - if (HasFP) MinSize += SlotSize; + if (HasFP || HasFPShrinkWrap) MinSize += SlotSize; X86FI->setUsesRedZone(MinSize > 0 || StackSize > 0); StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0); MFI.setStackSize(StackSize); @@ -1740,6 +1751,36 @@ assert(!IsFunclet && "funclets without FPs not yet implemented"); NumBytes = StackSize - (X86FI->getCalleeSavedFrameSize() + TailCallArgReserveSize); + + if (HasFPShrinkWrap) { + NumBytes -= SlotSize; + // Callee-saved registers are pushed on stack before the stack is + // realigned. + if (TRI->hasStackRealignment(MF) && !IsWin64Prologue) + NumBytes = alignTo(NumBytes, MaxAlign); + + // Save EBP/RBP into the appropriate stack slot. + Register FP = Is64Bit ? X86::RBP : X86::EBP; + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) + .addReg(FP, RegState::Kill) + .setMIFlag(MachineInstr::FrameSetup); + + if (NeedsDwarfCFI) { + // Mark the place where EBP/RBP was saved. + // Define the current CFA rule to use the provided offset. + assert(StackSize); + BuildCFI(MBB, MBBI, DL, + MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth), + MachineInstr::FrameSetup); + + // Change the rule for the FramePtr to be an "offset" rule. + unsigned DwarfFramePtr = TRI->getDwarfRegNum(FP, true); + BuildCFI(MBB, MBBI, DL, + MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, + 2 * stackGrowth), + MachineInstr::FrameSetup); + } + } } // Update the offset adjustment, which is mainly used by codeview to translate @@ -1769,7 +1810,7 @@ Register Reg = MBBI->getOperand(0).getReg(); ++MBBI; - if (!HasFP && NeedsDwarfCFI) { + if (( !HasFP && !HasFPShrinkWrap )&& NeedsDwarfCFI) { // Mark callee-saved push instruction. // Define the current CFA rule to use the provided offset. assert(StackSize); @@ -2064,6 +2105,18 @@ emitCalleeSavedFrameMoves(MBB, MBBI, DL, true); } + if (HasFPShrinkWrap) { + Register FP = Is64Bit ? X86::RBP : X86::EBP; + MBBI = BuildMI(MBB, MBBI, DL, TII.get(IsLP64 ? X86::LEA64r : X86::LEA64_32r), + FP) + .addReg(X86::RSP) + .addImm(1) + .addReg(0) + .addImm(-StackSize) + .addReg(0); + MBBI++; + } + // X86 Interrupt handling function cannot assume anything about the direction // flag (DF in EFLAGS register). Clear this flag by creating "cld" instruction // in each prologue of interrupt handler function. @@ -2190,6 +2243,7 @@ unsigned CSSize = X86FI->getCalleeSavedFrameSize(); unsigned TailCallArgReserveSize = -X86FI->getTCReturnAddrDelta(); bool HasFP = hasFP(MF); + bool HasFPShrinkWrap = hasFPShrinkWrap(MF); uint64_t NumBytes = 0; bool NeedsDwarfCFI = (!MF.getTarget().getTargetTriple().isOSDarwin() && @@ -2199,7 +2253,7 @@ if (IsFunclet) { assert(HasFP && "EH funclets without FP not yet implemented"); NumBytes = getWinEHFuncletFrameSize(MF); - } else if (HasFP) { + } else if (HasFP || HasFPShrinkWrap) { // Calculate required stack adjustment. uint64_t FrameSize = StackSize - SlotSize; NumBytes = FrameSize - CSSize - TailCallArgReserveSize; @@ -2254,6 +2308,31 @@ } } + if(HasFPShrinkWrap){ + Register FP = Is64Bit ? X86::RBP : X86::EBP; + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + FP) + .setMIFlag(MachineInstr::FrameDestroy); + + if (NeedsDwarfCFI) { + unsigned DwarfStackPtr = + TRI->getDwarfRegNum(Is64Bit ? X86::RSP : X86::ESP, true); + BuildCFI(MBB, MBBI, DL, + MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, SlotSize), + MachineInstr::FrameDestroy); + if (!MBB.succ_empty() && !MBB.isReturnBlock()) { + unsigned DwarfFramePtr = TRI->getDwarfRegNum(FP, true); + BuildCFI(MBB, AfterPop, DL, + MCCFIInstruction::createRestore(nullptr, DwarfFramePtr), + MachineInstr::FrameDestroy); + --MBBI; + --AfterPop; + } + --MBBI; + } + } + MachineBasicBlock::iterator FirstCSPop = MBBI; // Skip the callee-saved pop instructions. while (MBBI != MBB.begin()) { @@ -2605,7 +2684,7 @@ } } - if (hasFP(MF)) { + if (hasFP(MF) || hasFPShrinkWrap(MF)) { // emitPrologue always spills frame register the first thing. SpillSlotOffset -= SlotSize; MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); @@ -2621,7 +2700,7 @@ // Since emitPrologue and emitEpilogue will handle spilling and restoring of // the frame register, we can delete it from CSI list and not have to worry // about avoiding it later. - Register FPReg = TRI->getFrameRegister(MF); + Register FPReg = hasFPShrinkWrap(MF) ? (Is64Bit ? X86::RBP :X86::EBP) : TRI->getFrameRegister(MF); for (unsigned i = 0; i < CSI.size(); ++i) { if (TRI->regsOverlap(CSI[i].getReg(),FPReg)) { CSI.erase(CSI.begin() + i); diff --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h --- a/llvm/lib/Target/X86/X86RegisterInfo.h +++ b/llvm/lib/Target/X86/X86RegisterInfo.h @@ -145,6 +145,7 @@ // Debug information queries. Register getFrameRegister(const MachineFunction &MF) const override; + Register getFPReg(const MachineFunction &MF) const override; unsigned getPtrSizedFrameRegister(const MachineFunction &MF) const; unsigned getPtrSizedStackRegister(const MachineFunction &MF) const; Register getStackRegister() const { return StackPtr; } diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -913,6 +913,10 @@ return TFI->hasFP(MF) ? FramePtr : StackPtr; } +Register X86RegisterInfo::getFPReg(const MachineFunction &MF) const { + return getFramePtr(); +} + unsigned X86RegisterInfo::getPtrSizedFrameRegister(const MachineFunction &MF) const { const X86Subtarget &Subtarget = MF.getSubtarget();