53#define DEBUG_TYPE "x86-cf-opt"
57 cl::desc(
"Avoid optimizing x86 call frames for size"),
62class X86CallFrameOptimizationImpl {
69 CallContext() : FrameSetup(nullptr), ArgStoreVector(4, nullptr) {}
75 MachineInstr *Call =
nullptr;
78 MachineInstr *SPCopy =
nullptr;
81 int64_t ExpectedDist = 0;
84 SmallVector<MachineInstr *, 4> ArgStoreVector;
87 bool NoStackParams =
false;
93 typedef SmallVector<CallContext, 8> ContextVector;
95 bool isLegal(MachineFunction &MF);
97 bool isProfitable(MachineFunction &MF, ContextVector &CallSeqMap);
99 void collectCallInfo(MachineFunction &MF, MachineBasicBlock &
MBB,
102 void adjustCallSequence(MachineFunction &MF,
const CallContext &
Context);
107 enum InstClassification { Convert, Skip, Exit };
109 InstClassification classifyInstruction(MachineBasicBlock &
MBB,
111 const X86RegisterInfo &RegInfo,
112 const DenseSet<MCRegister> &UsedRegs);
114 const X86InstrInfo *TII =
nullptr;
115 const X86FrameLowering *TFL =
nullptr;
116 const X86Subtarget *STI =
nullptr;
117 MachineRegisterInfo *MRI =
nullptr;
118 unsigned SlotSize = 0;
119 unsigned Log2SlotSize = 0;
124 X86CallFrameOptimizationLegacy() : MachineFunctionPass(ID) {}
126 bool runOnMachineFunction(MachineFunction &MF)
override;
128 void getAnalysisUsage(AnalysisUsage &AU)
const override {
136 StringRef getPassName()
const override {
return "X86 Optimize Call Frame"; }
140char X86CallFrameOptimizationLegacy::ID = 0;
142 "X86 Call Frame Optimization",
false,
false)
154 if (STI->isTargetDarwin() &&
155 (!MF.getLandingPads().empty() ||
156 (MF.getFunction().needsUnwindTableEntry() && !TFL->hasFP(MF))))
161 if (STI->isTargetWin64())
176 unsigned FrameSetupOpcode =
TII->getCallFrameSetupOpcode();
177 unsigned FrameDestroyOpcode =
TII->getCallFrameDestroyOpcode();
178 bool EmitStackProbeCall = STI->getTargetLowering()->hasStackProbeSymbol(MF);
179 unsigned StackProbeSize = STI->getTargetLowering()->getStackProbeSize(MF);
181 bool InsideFrameSequence =
false;
183 if (
MI.getOpcode() == FrameSetupOpcode) {
184 if (
TII->getFrameSize(
MI) >= StackProbeSize && EmitStackProbeCall)
186 if (InsideFrameSequence)
188 InsideFrameSequence =
true;
189 }
else if (
MI.getOpcode() == FrameDestroyOpcode) {
190 if (!InsideFrameSequence)
192 InsideFrameSequence =
false;
196 if (InsideFrameSequence)
206 ContextVector &CallSeqVector) {
211 if (CannotReserveFrame)
216 int64_t Advantage = 0;
217 for (
const auto &CC : CallSeqVector) {
221 if (CC.NoStackParams)
237 if (!
isAligned(StackAlign, CC.ExpectedDist))
241 Advantage += (CC.ExpectedDist >> Log2SlotSize) * 3;
245 return Advantage >= 0;
248bool X86CallFrameOptimizationImpl::runOnMachineFunction(MachineFunction &MF) {
257 Log2SlotSize =
Log2_32(SlotSize);
262 unsigned FrameSetupOpcode =
TII->getCallFrameSetupOpcode();
266 ContextVector CallSeqVector;
270 if (
MI.getOpcode() == FrameSetupOpcode) {
273 CallSeqVector.push_back(
Context);
279 for (
const auto &CC : CallSeqVector) {
281 adjustCallSequence(MF, CC);
289X86CallFrameOptimizationImpl::InstClassification
290X86CallFrameOptimizationImpl::classifyInstruction(
292 const X86RegisterInfo &RegInfo,
const DenseSet<MCRegister> &UsedRegs) {
298 switch (
MI->getOpcode()) {
301 case X86::AND64mi32: {
303 return ImmOp.
getImm() == 0 ? Convert : Exit;
307 case X86::OR64mi32: {
309 return ImmOp.
getImm() == -1 ? Convert : Exit;
343 if (
MI->isCall() ||
MI->mayStore())
346 for (
const MachineOperand &MO :
MI->operands()) {
355 for (MCRegister U : UsedRegs)
356 if (RegInfo.regsOverlap(
Reg, U))
364void X86CallFrameOptimizationImpl::collectCallInfo(
372 assert(
I->getOpcode() ==
TII->getCallFrameSetupOpcode());
374 Context.FrameSetup = FrameSetup;
378 unsigned int MaxAdjust =
TII->getFrameSize(*FrameSetup) >> Log2SlotSize;
389 while (
I->getOpcode() == X86::LEA32r ||
I->isDebugInstr())
393 auto StackPtrCopyInst =
MBB.
end();
402 for (
auto J =
I; !J->isCall(); ++J)
403 if (J->isCopy() && J->getOperand(0).isReg() && J->getOperand(1).isReg() &&
404 J->getOperand(1).getReg() == StackPtr) {
405 StackPtrCopyInst = J;
416 Context.ArgStoreVector.resize(MaxAdjust,
nullptr);
418 DenseSet<MCRegister> UsedRegs;
420 for (InstClassification Classification = Skip; Classification != Exit; ++
I) {
422 if (
I == StackPtrCopyInst)
424 Classification = classifyInstruction(
MBB,
I, RegInfo, UsedRegs);
425 if (Classification != Convert)
447 "Negative stack displacement when passing parameters");
450 if (StackDisp & (SlotSize - 1))
452 StackDisp >>= Log2SlotSize;
455 "Function call has more parameters than the stack is adjusted for.");
458 if (
Context.ArgStoreVector[StackDisp] !=
nullptr)
460 Context.ArgStoreVector[StackDisp] = &*
I;
462 for (
const MachineOperand &MO :
I->uses()) {
485 for (; MMI != MME; ++MMI,
Context.ExpectedDist += SlotSize)
490 if (MMI ==
Context.ArgStoreVector.begin())
495 for (; MMI != MME; ++MMI)
502void X86CallFrameOptimizationImpl::adjustCallSequence(
503 MachineFunction &MF,
const CallContext &
Context) {
508 MachineBasicBlock &
MBB = *(FrameSetup->getParent());
509 TII->setFrameAdjustment(*FrameSetup,
Context.ExpectedDist);
511 const DebugLoc &
DL = FrameSetup->getDebugLoc();
512 bool Is64Bit = STI->is64Bit();
516 for (
int Idx = (
Context.ExpectedDist >> Log2SlotSize) - 1; Idx >= 0; --Idx) {
521 switch (
Store->getOpcode()) {
532 PushOpcode = Is64Bit ? X86::PUSH64i32 : X86::PUSH32i;
534 Push->cloneMemRefs(MF, *
Store);
542 if (Is64Bit &&
Store->getOpcode() == X86::MOV32mr) {
554 bool SlowPUSHrmm = STI->slowTwoMemOps();
558 MachineInstr *DefMov =
nullptr;
559 if (!SlowPUSHrmm && (DefMov = canFoldIntoRegPush(FrameSetup,
Reg))) {
560 PushOpcode = Is64Bit ? X86::PUSH64rmm : X86::PUSH32rmm;
566 Push->cloneMergedMemRefs(MF, {DefMov, &*
Store});
569 PushOpcode = Is64Bit ? X86::PUSH64r : X86::PUSH32r;
573 Push->cloneMemRefs(MF, *
Store);
584 MBB, std::next(Push),
DL,
593 Context.SPCopy->eraseFromParent();
597 X86MachineFunctionInfo *FuncInfo = MF.
getInfo<X86MachineFunctionInfo>();
601MachineInstr *X86CallFrameOptimizationImpl::canFoldIntoRegPush(
624 if ((
DefMI.getOpcode() != X86::MOV32rm &&
625 DefMI.getOpcode() != X86::MOV64rm) ||
626 DefMI.getParent() != FrameSetup->getParent())
632 if (
I->isLoadFoldBarrier())
639 return new X86CallFrameOptimizationLegacy();
642bool X86CallFrameOptimizationLegacy::runOnMachineFunction(
MachineFunction &MF) {
645 X86CallFrameOptimizationImpl Impl;
646 return Impl.runOnMachineFunction(MF);
652 X86CallFrameOptimizationImpl Impl;
653 bool Changed = Impl.runOnMachineFunction(MF);
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseSet and SmallDenseSet classes.
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
static bool isProfitable(const StableFunctionMap::StableFunctionEntries &SFS)
static cl::opt< bool > NoX86CFOpt("no-x86-call-frame-opt", cl::desc("Avoid optimizing x86 call frames for size"), cl::init(false), cl::Hidden)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int64_t Adjustment, SMLoc Loc={})
.cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but Offset is a relative value that is added/subt...
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const MCCFIInstruction &CFIInst, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
Wraps up getting a CFI index and building a MachineInstr for it.
void setHasPushSequences(bool HasPush)
Register getStackRegister() const
unsigned getSlotSize() const
const X86InstrInfo * getInstrInfo() const override
const X86RegisterInfo * getRegisterInfo() const override
const X86FrameLowering * getFrameLowering() const override
std::pair< iterator, bool > insert(const ValueT &V)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
initializer< Ty > init(const Ty &Val)
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
@ Store
The extracted value is stored (ExtractElement only).
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FunctionPass * createX86CallFrameOptimizationLegacyPass()