52#define DEBUG_TYPE "x86-cf-opt" 
   56               cl::desc(
"Avoid optimizing x86 call frames for size"),
 
   65  bool runOnMachineFunction(MachineFunction &MF) 
override;
 
   72    CallContext() : FrameSetup(nullptr), ArgStoreVector(4, nullptr) {}
 
   78    MachineInstr *Call = 
nullptr;
 
   81    MachineInstr *SPCopy = 
nullptr;
 
   84    int64_t ExpectedDist = 0;
 
   87    SmallVector<MachineInstr *, 4> ArgStoreVector;
 
   90    bool NoStackParams = 
false;
 
   96  typedef SmallVector<CallContext, 8> ContextVector;
 
   98  bool isLegal(MachineFunction &MF);
 
  100  bool isProfitable(MachineFunction &MF, ContextVector &CallSeqMap);
 
  102  void collectCallInfo(MachineFunction &MF, MachineBasicBlock &
MBB,
 
  105  void adjustCallSequence(MachineFunction &MF, 
const CallContext &
Context);
 
  110  enum InstClassification { Convert, Skip, Exit };
 
  112  InstClassification classifyInstruction(MachineBasicBlock &
MBB,
 
  114                                         const X86RegisterInfo &RegInfo,
 
  115                                         const DenseSet<MCRegister> &UsedRegs);
 
  117  StringRef getPassName()
 const override { 
return "X86 Optimize Call Frame"; }
 
  119  const X86InstrInfo *TII = 
nullptr;
 
  120  const X86FrameLowering *TFL = 
nullptr;
 
  121  const X86Subtarget *STI = 
nullptr;
 
  122  MachineRegisterInfo *MRI = 
nullptr;
 
  123  unsigned SlotSize = 0;
 
  124  unsigned Log2SlotSize = 0;
 
  128char X86CallFrameOptimization::ID = 0;
 
  130                "X86 Call Frame Optimization", 
false, 
false)
 
  142  if (STI->isTargetDarwin() &&
 
  143      (!MF.getLandingPads().empty() ||
 
  144       (MF.getFunction().needsUnwindTableEntry() && !TFL->hasFP(MF))))
 
  149  if (STI->isTargetWin64())
 
  164  unsigned FrameSetupOpcode = 
TII->getCallFrameSetupOpcode();
 
  165  unsigned FrameDestroyOpcode = 
TII->getCallFrameDestroyOpcode();
 
  166  bool EmitStackProbeCall = STI->getTargetLowering()->hasStackProbeSymbol(MF);
 
  167  unsigned StackProbeSize = STI->getTargetLowering()->getStackProbeSize(MF);
 
  169    bool InsideFrameSequence = 
false;
 
  171      if (
MI.getOpcode() == FrameSetupOpcode) {
 
  172        if (
TII->getFrameSize(
MI) >= StackProbeSize && EmitStackProbeCall)
 
  174        if (InsideFrameSequence)
 
  176        InsideFrameSequence = 
true;
 
  177      } 
else if (
MI.getOpcode() == FrameDestroyOpcode) {
 
  178        if (!InsideFrameSequence)
 
  180        InsideFrameSequence = 
false;
 
  184    if (InsideFrameSequence)
 
 
  194                                            ContextVector &CallSeqVector) {
 
  199  if (CannotReserveFrame)
 
  204  int64_t Advantage = 0;
 
  205  for (
const auto &CC : CallSeqVector) {
 
  209    if (CC.NoStackParams)
 
  225      if (!
isAligned(StackAlign, CC.ExpectedDist))
 
  229      Advantage += (CC.ExpectedDist >> Log2SlotSize) * 3;
 
  233  return Advantage >= 0;
 
  236bool X86CallFrameOptimization::runOnMachineFunction(MachineFunction &MF) {
 
  245  Log2SlotSize = 
Log2_32(SlotSize);
 
  247  if (skipFunction(MF.
getFunction()) || !isLegal(MF))
 
  250  unsigned FrameSetupOpcode = 
TII->getCallFrameSetupOpcode();
 
  254  ContextVector CallSeqVector;
 
  258      if (
MI.getOpcode() == FrameSetupOpcode) {
 
  261        CallSeqVector.push_back(
Context);
 
  267  for (
const auto &CC : CallSeqVector) {
 
  269      adjustCallSequence(MF, CC);
 
  277X86CallFrameOptimization::InstClassification
 
  278X86CallFrameOptimization::classifyInstruction(
 
  280    const X86RegisterInfo &RegInfo, 
const DenseSet<MCRegister> &UsedRegs) {
 
  286  switch (
MI->getOpcode()) {
 
  289    case X86::AND64mi32: {
 
  291      return ImmOp.
getImm() == 0 ? Convert : Exit;
 
  295    case X86::OR64mi32: {
 
  297      return ImmOp.
getImm() == -1 ? Convert : Exit;
 
  331  if (
MI->isCall() || 
MI->mayStore())
 
  334  for (
const MachineOperand &MO : 
MI->operands()) {
 
  343      for (MCRegister U : UsedRegs)
 
  344        if (RegInfo.regsOverlap(
Reg, U))
 
  352void X86CallFrameOptimization::collectCallInfo(MachineFunction &MF,
 
  353                                               MachineBasicBlock &
MBB,
 
  361  assert(
I->getOpcode() == 
TII->getCallFrameSetupOpcode());
 
  363  Context.FrameSetup = FrameSetup;
 
  367  unsigned int MaxAdjust = 
TII->getFrameSize(*FrameSetup) >> Log2SlotSize;
 
  378  while (
I->getOpcode() == X86::LEA32r || 
I->isDebugInstr())
 
  382  auto StackPtrCopyInst = 
MBB.
end();
 
  391  for (
auto J = 
I; !J->isCall(); ++J)
 
  392    if (J->isCopy() && J->getOperand(0).isReg() && J->getOperand(1).isReg() &&
 
  393        J->getOperand(1).getReg() == StackPtr) {
 
  394      StackPtrCopyInst = J;
 
  405    Context.ArgStoreVector.resize(MaxAdjust, 
nullptr);
 
  407  DenseSet<MCRegister> UsedRegs;
 
  409  for (InstClassification Classification = Skip; Classification != Exit; ++
I) {
 
  411    if (
I == StackPtrCopyInst)
 
  413    Classification = classifyInstruction(
MBB, 
I, RegInfo, UsedRegs);
 
  414    if (Classification != Convert)
 
  436           "Negative stack displacement when passing parameters");
 
  439    if (StackDisp & (SlotSize - 1))
 
  441    StackDisp >>= Log2SlotSize;
 
  444           "Function call has more parameters than the stack is adjusted for.");
 
  447    if (
Context.ArgStoreVector[StackDisp] != 
nullptr)
 
  449    Context.ArgStoreVector[StackDisp] = &*
I;
 
  451    for (
const MachineOperand &MO : 
I->uses()) {
 
  474  for (; MMI != MME; ++MMI, 
Context.ExpectedDist += SlotSize)
 
  479  if (MMI == 
Context.ArgStoreVector.begin())
 
  484  for (; MMI != MME; ++MMI)
 
  491void X86CallFrameOptimization::adjustCallSequence(MachineFunction &MF,
 
  497  MachineBasicBlock &
MBB = *(FrameSetup->getParent());
 
  498  TII->setFrameAdjustment(*FrameSetup, 
Context.ExpectedDist);
 
  500  const DebugLoc &
DL = FrameSetup->getDebugLoc();
 
  501  bool Is64Bit = STI->is64Bit();
 
  505  for (
int Idx = (
Context.ExpectedDist >> Log2SlotSize) - 1; Idx >= 0; --Idx) {
 
  510    switch (
Store->getOpcode()) {
 
  521      PushOpcode = Is64Bit ? X86::PUSH64i32 : X86::PUSH32i;
 
  523      Push->cloneMemRefs(MF, *Store);
 
  531      if (Is64Bit && 
Store->getOpcode() == X86::MOV32mr) {
 
  532        Register UndefReg = 
MRI->createVirtualRegister(&X86::GR64RegClass);
 
  533        Reg = 
MRI->createVirtualRegister(&X86::GR64RegClass);
 
  543      bool SlowPUSHrmm = STI->slowTwoMemOps();
 
  547      MachineInstr *DefMov = 
nullptr;
 
  548      if (!SlowPUSHrmm && (DefMov = canFoldIntoRegPush(FrameSetup, 
Reg))) {
 
  549        PushOpcode = Is64Bit ? X86::PUSH64rmm : X86::PUSH32rmm;
 
  555        Push->cloneMergedMemRefs(MF, {DefMov, &*
Store});
 
  558        PushOpcode = Is64Bit ? X86::PUSH64r : X86::PUSH32r;
 
  562        Push->cloneMemRefs(MF, *Store);
 
  573          MBB, std::next(Push), 
DL,
 
  582    Context.SPCopy->eraseFromParent();
 
  586  X86MachineFunctionInfo *FuncInfo = MF.
getInfo<X86MachineFunctionInfo>();
 
  590MachineInstr *X86CallFrameOptimization::canFoldIntoRegPush(
 
  606  if (!
MRI->hasOneNonDBGUse(
Reg))
 
  613  if ((
DefMI.getOpcode() != X86::MOV32rm &&
 
  614       DefMI.getOpcode() != X86::MOV64rm) ||
 
  615      DefMI.getParent() != FrameSetup->getParent())
 
  621    if (
I->isLoadFoldBarrier())
 
  628  return new X86CallFrameOptimization();
 
 
unsigned const MachineRegisterInfo * MRI
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 std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
static cl::opt< bool > NoX86CFOpt("no-x86-call-frame-opt", cl::desc("Avoid optimizing x86 call frames for size"), cl::init(false), cl::Hidden)
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...
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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
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...
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
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.
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 * createX86CallFrameOptimization()
Return a pass that optimizes the code-size of x86 call sequences.