xref: /aosp_15_r20/external/llvm/lib/Target/X86/X86CallFrameOptimization.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===----- X86CallFrameOptimization.cpp - Optimize x86 call sequences -----===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file defines a pass that optimizes call sequences on x86.
11*9880d681SAndroid Build Coastguard Worker // Currently, it converts movs of function parameters onto the stack into
12*9880d681SAndroid Build Coastguard Worker // pushes. This is beneficial for two main reasons:
13*9880d681SAndroid Build Coastguard Worker // 1) The push instruction encoding is much smaller than a stack-ptr-based mov.
14*9880d681SAndroid Build Coastguard Worker // 2) It is possible to push memory arguments directly. So, if the
15*9880d681SAndroid Build Coastguard Worker //    the transformation is performed pre-reg-alloc, it can help relieve
16*9880d681SAndroid Build Coastguard Worker //    register pressure.
17*9880d681SAndroid Build Coastguard Worker //
18*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker #include <algorithm>
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker #include "X86.h"
23*9880d681SAndroid Build Coastguard Worker #include "X86InstrInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "X86MachineFunctionInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "X86Subtarget.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineModuleInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker using namespace llvm;
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "x86-cf-opt"
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
42*9880d681SAndroid Build Coastguard Worker     NoX86CFOpt("no-x86-call-frame-opt",
43*9880d681SAndroid Build Coastguard Worker                cl::desc("Avoid optimizing x86 call frames for size"),
44*9880d681SAndroid Build Coastguard Worker                cl::init(false), cl::Hidden);
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker namespace {
47*9880d681SAndroid Build Coastguard Worker class X86CallFrameOptimization : public MachineFunctionPass {
48*9880d681SAndroid Build Coastguard Worker public:
X86CallFrameOptimization()49*9880d681SAndroid Build Coastguard Worker   X86CallFrameOptimization() : MachineFunctionPass(ID) {}
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override;
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker private:
54*9880d681SAndroid Build Coastguard Worker   // Information we know about a particular call site
55*9880d681SAndroid Build Coastguard Worker   struct CallContext {
CallContext__anon857e8a070111::X86CallFrameOptimization::CallContext56*9880d681SAndroid Build Coastguard Worker     CallContext()
57*9880d681SAndroid Build Coastguard Worker         : FrameSetup(nullptr), Call(nullptr), SPCopy(nullptr), ExpectedDist(0),
58*9880d681SAndroid Build Coastguard Worker           MovVector(4, nullptr), NoStackParams(false), UsePush(false) {}
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker     // Iterator referring to the frame setup instruction
61*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator FrameSetup;
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker     // Actual call instruction
64*9880d681SAndroid Build Coastguard Worker     MachineInstr *Call;
65*9880d681SAndroid Build Coastguard Worker 
66*9880d681SAndroid Build Coastguard Worker     // A copy of the stack pointer
67*9880d681SAndroid Build Coastguard Worker     MachineInstr *SPCopy;
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker     // The total displacement of all passed parameters
70*9880d681SAndroid Build Coastguard Worker     int64_t ExpectedDist;
71*9880d681SAndroid Build Coastguard Worker 
72*9880d681SAndroid Build Coastguard Worker     // The sequence of movs used to pass the parameters
73*9880d681SAndroid Build Coastguard Worker     SmallVector<MachineInstr *, 4> MovVector;
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker     // True if this call site has no stack parameters
76*9880d681SAndroid Build Coastguard Worker     bool NoStackParams;
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker     // True if this call site can use push instructions
79*9880d681SAndroid Build Coastguard Worker     bool UsePush;
80*9880d681SAndroid Build Coastguard Worker   };
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker   typedef SmallVector<CallContext, 8> ContextVector;
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker   bool isLegal(MachineFunction &MF);
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker   bool isProfitable(MachineFunction &MF, ContextVector &CallSeqMap);
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   void collectCallInfo(MachineFunction &MF, MachineBasicBlock &MBB,
89*9880d681SAndroid Build Coastguard Worker                        MachineBasicBlock::iterator I, CallContext &Context);
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker   void adjustCallSequence(MachineFunction &MF, const CallContext &Context);
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker   MachineInstr *canFoldIntoRegPush(MachineBasicBlock::iterator FrameSetup,
94*9880d681SAndroid Build Coastguard Worker                                    unsigned Reg);
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   enum InstClassification { Convert, Skip, Exit };
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker   InstClassification classifyInstruction(MachineBasicBlock &MBB,
99*9880d681SAndroid Build Coastguard Worker                                          MachineBasicBlock::iterator MI,
100*9880d681SAndroid Build Coastguard Worker                                          const X86RegisterInfo &RegInfo,
101*9880d681SAndroid Build Coastguard Worker                                          DenseSet<unsigned int> &UsedRegs);
102*9880d681SAndroid Build Coastguard Worker 
getPassName() const103*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override { return "X86 Optimize Call Frame"; }
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker   const TargetInstrInfo *TII;
106*9880d681SAndroid Build Coastguard Worker   const X86FrameLowering *TFL;
107*9880d681SAndroid Build Coastguard Worker   const X86Subtarget *STI;
108*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo *MRI;
109*9880d681SAndroid Build Coastguard Worker   unsigned SlotSize;
110*9880d681SAndroid Build Coastguard Worker   unsigned Log2SlotSize;
111*9880d681SAndroid Build Coastguard Worker   static char ID;
112*9880d681SAndroid Build Coastguard Worker };
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker char X86CallFrameOptimization::ID = 0;
115*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
116*9880d681SAndroid Build Coastguard Worker 
createX86CallFrameOptimization()117*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createX86CallFrameOptimization() {
118*9880d681SAndroid Build Coastguard Worker   return new X86CallFrameOptimization();
119*9880d681SAndroid Build Coastguard Worker }
120*9880d681SAndroid Build Coastguard Worker 
121*9880d681SAndroid Build Coastguard Worker // This checks whether the transformation is legal.
122*9880d681SAndroid Build Coastguard Worker // Also returns false in cases where it's potentially legal, but
123*9880d681SAndroid Build Coastguard Worker // we don't even want to try.
isLegal(MachineFunction & MF)124*9880d681SAndroid Build Coastguard Worker bool X86CallFrameOptimization::isLegal(MachineFunction &MF) {
125*9880d681SAndroid Build Coastguard Worker   if (NoX86CFOpt.getValue())
126*9880d681SAndroid Build Coastguard Worker     return false;
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker   // We can't encode multiple DW_CFA_GNU_args_size or DW_CFA_def_cfa_offset
129*9880d681SAndroid Build Coastguard Worker   // in the compact unwind encoding that Darwin uses. So, bail if there
130*9880d681SAndroid Build Coastguard Worker   // is a danger of that being generated.
131*9880d681SAndroid Build Coastguard Worker   if (STI->isTargetDarwin() &&
132*9880d681SAndroid Build Coastguard Worker       (!MF.getMMI().getLandingPads().empty() ||
133*9880d681SAndroid Build Coastguard Worker        (MF.getFunction()->needsUnwindTableEntry() && !TFL->hasFP(MF))))
134*9880d681SAndroid Build Coastguard Worker     return false;
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker   // It is not valid to change the stack pointer outside the prolog/epilog
137*9880d681SAndroid Build Coastguard Worker   // on 64-bit Windows.
138*9880d681SAndroid Build Coastguard Worker   if (STI->isTargetWin64())
139*9880d681SAndroid Build Coastguard Worker     return false;
140*9880d681SAndroid Build Coastguard Worker 
141*9880d681SAndroid Build Coastguard Worker   // You would expect straight-line code between call-frame setup and
142*9880d681SAndroid Build Coastguard Worker   // call-frame destroy. You would be wrong. There are circumstances (e.g.
143*9880d681SAndroid Build Coastguard Worker   // CMOV_GR8 expansion of a select that feeds a function call!) where we can
144*9880d681SAndroid Build Coastguard Worker   // end up with the setup and the destroy in different basic blocks.
145*9880d681SAndroid Build Coastguard Worker   // This is bad, and breaks SP adjustment.
146*9880d681SAndroid Build Coastguard Worker   // So, check that all of the frames in the function are closed inside
147*9880d681SAndroid Build Coastguard Worker   // the same block, and, for good measure, that there are no nested frames.
148*9880d681SAndroid Build Coastguard Worker   unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode();
149*9880d681SAndroid Build Coastguard Worker   unsigned FrameDestroyOpcode = TII->getCallFrameDestroyOpcode();
150*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock &BB : MF) {
151*9880d681SAndroid Build Coastguard Worker     bool InsideFrameSequence = false;
152*9880d681SAndroid Build Coastguard Worker     for (MachineInstr &MI : BB) {
153*9880d681SAndroid Build Coastguard Worker       if (MI.getOpcode() == FrameSetupOpcode) {
154*9880d681SAndroid Build Coastguard Worker         if (InsideFrameSequence)
155*9880d681SAndroid Build Coastguard Worker           return false;
156*9880d681SAndroid Build Coastguard Worker         InsideFrameSequence = true;
157*9880d681SAndroid Build Coastguard Worker       } else if (MI.getOpcode() == FrameDestroyOpcode) {
158*9880d681SAndroid Build Coastguard Worker         if (!InsideFrameSequence)
159*9880d681SAndroid Build Coastguard Worker           return false;
160*9880d681SAndroid Build Coastguard Worker         InsideFrameSequence = false;
161*9880d681SAndroid Build Coastguard Worker       }
162*9880d681SAndroid Build Coastguard Worker     }
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker     if (InsideFrameSequence)
165*9880d681SAndroid Build Coastguard Worker       return false;
166*9880d681SAndroid Build Coastguard Worker   }
167*9880d681SAndroid Build Coastguard Worker 
168*9880d681SAndroid Build Coastguard Worker   return true;
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker // Check whether this transformation is profitable for a particular
172*9880d681SAndroid Build Coastguard Worker // function - in terms of code size.
isProfitable(MachineFunction & MF,ContextVector & CallSeqVector)173*9880d681SAndroid Build Coastguard Worker bool X86CallFrameOptimization::isProfitable(MachineFunction &MF,
174*9880d681SAndroid Build Coastguard Worker                                             ContextVector &CallSeqVector) {
175*9880d681SAndroid Build Coastguard Worker   // This transformation is always a win when we do not expect to have
176*9880d681SAndroid Build Coastguard Worker   // a reserved call frame. Under other circumstances, it may be either
177*9880d681SAndroid Build Coastguard Worker   // a win or a loss, and requires a heuristic.
178*9880d681SAndroid Build Coastguard Worker   bool CannotReserveFrame = MF.getFrameInfo()->hasVarSizedObjects();
179*9880d681SAndroid Build Coastguard Worker   if (CannotReserveFrame)
180*9880d681SAndroid Build Coastguard Worker     return true;
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker   unsigned StackAlign = TFL->getStackAlignment();
183*9880d681SAndroid Build Coastguard Worker 
184*9880d681SAndroid Build Coastguard Worker   int64_t Advantage = 0;
185*9880d681SAndroid Build Coastguard Worker   for (auto CC : CallSeqVector) {
186*9880d681SAndroid Build Coastguard Worker     // Call sites where no parameters are passed on the stack
187*9880d681SAndroid Build Coastguard Worker     // do not affect the cost, since there needs to be no
188*9880d681SAndroid Build Coastguard Worker     // stack adjustment.
189*9880d681SAndroid Build Coastguard Worker     if (CC.NoStackParams)
190*9880d681SAndroid Build Coastguard Worker       continue;
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker     if (!CC.UsePush) {
193*9880d681SAndroid Build Coastguard Worker       // If we don't use pushes for a particular call site,
194*9880d681SAndroid Build Coastguard Worker       // we pay for not having a reserved call frame with an
195*9880d681SAndroid Build Coastguard Worker       // additional sub/add esp pair. The cost is ~3 bytes per instruction,
196*9880d681SAndroid Build Coastguard Worker       // depending on the size of the constant.
197*9880d681SAndroid Build Coastguard Worker       // TODO: Callee-pop functions should have a smaller penalty, because
198*9880d681SAndroid Build Coastguard Worker       // an add is needed even with a reserved call frame.
199*9880d681SAndroid Build Coastguard Worker       Advantage -= 6;
200*9880d681SAndroid Build Coastguard Worker     } else {
201*9880d681SAndroid Build Coastguard Worker       // We can use pushes. First, account for the fixed costs.
202*9880d681SAndroid Build Coastguard Worker       // We'll need a add after the call.
203*9880d681SAndroid Build Coastguard Worker       Advantage -= 3;
204*9880d681SAndroid Build Coastguard Worker       // If we have to realign the stack, we'll also need a sub before
205*9880d681SAndroid Build Coastguard Worker       if (CC.ExpectedDist % StackAlign)
206*9880d681SAndroid Build Coastguard Worker         Advantage -= 3;
207*9880d681SAndroid Build Coastguard Worker       // Now, for each push, we save ~3 bytes. For small constants, we actually,
208*9880d681SAndroid Build Coastguard Worker       // save more (up to 5 bytes), but 3 should be a good approximation.
209*9880d681SAndroid Build Coastguard Worker       Advantage += (CC.ExpectedDist >> Log2SlotSize) * 3;
210*9880d681SAndroid Build Coastguard Worker     }
211*9880d681SAndroid Build Coastguard Worker   }
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker   return Advantage >= 0;
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & MF)216*9880d681SAndroid Build Coastguard Worker bool X86CallFrameOptimization::runOnMachineFunction(MachineFunction &MF) {
217*9880d681SAndroid Build Coastguard Worker   STI = &MF.getSubtarget<X86Subtarget>();
218*9880d681SAndroid Build Coastguard Worker   TII = STI->getInstrInfo();
219*9880d681SAndroid Build Coastguard Worker   TFL = STI->getFrameLowering();
220*9880d681SAndroid Build Coastguard Worker   MRI = &MF.getRegInfo();
221*9880d681SAndroid Build Coastguard Worker 
222*9880d681SAndroid Build Coastguard Worker   const X86RegisterInfo &RegInfo =
223*9880d681SAndroid Build Coastguard Worker       *static_cast<const X86RegisterInfo *>(STI->getRegisterInfo());
224*9880d681SAndroid Build Coastguard Worker   SlotSize = RegInfo.getSlotSize();
225*9880d681SAndroid Build Coastguard Worker   assert(isPowerOf2_32(SlotSize) && "Expect power of 2 stack slot size");
226*9880d681SAndroid Build Coastguard Worker   Log2SlotSize = Log2_32(SlotSize);
227*9880d681SAndroid Build Coastguard Worker 
228*9880d681SAndroid Build Coastguard Worker   if (!isLegal(MF))
229*9880d681SAndroid Build Coastguard Worker     return false;
230*9880d681SAndroid Build Coastguard Worker 
231*9880d681SAndroid Build Coastguard Worker   unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode();
232*9880d681SAndroid Build Coastguard Worker 
233*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
234*9880d681SAndroid Build Coastguard Worker 
235*9880d681SAndroid Build Coastguard Worker   ContextVector CallSeqVector;
236*9880d681SAndroid Build Coastguard Worker 
237*9880d681SAndroid Build Coastguard Worker   for (auto &MBB : MF)
238*9880d681SAndroid Build Coastguard Worker     for (auto &MI : MBB)
239*9880d681SAndroid Build Coastguard Worker       if (MI.getOpcode() == FrameSetupOpcode) {
240*9880d681SAndroid Build Coastguard Worker         CallContext Context;
241*9880d681SAndroid Build Coastguard Worker         collectCallInfo(MF, MBB, MI, Context);
242*9880d681SAndroid Build Coastguard Worker         CallSeqVector.push_back(Context);
243*9880d681SAndroid Build Coastguard Worker       }
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker   if (!isProfitable(MF, CallSeqVector))
246*9880d681SAndroid Build Coastguard Worker     return false;
247*9880d681SAndroid Build Coastguard Worker 
248*9880d681SAndroid Build Coastguard Worker   for (auto CC : CallSeqVector) {
249*9880d681SAndroid Build Coastguard Worker     if (CC.UsePush) {
250*9880d681SAndroid Build Coastguard Worker       adjustCallSequence(MF, CC);
251*9880d681SAndroid Build Coastguard Worker       Changed = true;
252*9880d681SAndroid Build Coastguard Worker     }
253*9880d681SAndroid Build Coastguard Worker   }
254*9880d681SAndroid Build Coastguard Worker 
255*9880d681SAndroid Build Coastguard Worker   return Changed;
256*9880d681SAndroid Build Coastguard Worker }
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker X86CallFrameOptimization::InstClassification
classifyInstruction(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const X86RegisterInfo & RegInfo,DenseSet<unsigned int> & UsedRegs)259*9880d681SAndroid Build Coastguard Worker X86CallFrameOptimization::classifyInstruction(
260*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
261*9880d681SAndroid Build Coastguard Worker     const X86RegisterInfo &RegInfo, DenseSet<unsigned int> &UsedRegs) {
262*9880d681SAndroid Build Coastguard Worker   if (MI == MBB.end())
263*9880d681SAndroid Build Coastguard Worker     return Exit;
264*9880d681SAndroid Build Coastguard Worker 
265*9880d681SAndroid Build Coastguard Worker   // The instructions we actually care about are movs onto the stack
266*9880d681SAndroid Build Coastguard Worker   int Opcode = MI->getOpcode();
267*9880d681SAndroid Build Coastguard Worker   if (Opcode == X86::MOV32mi   || Opcode == X86::MOV32mr ||
268*9880d681SAndroid Build Coastguard Worker       Opcode == X86::MOV64mi32 || Opcode == X86::MOV64mr)
269*9880d681SAndroid Build Coastguard Worker     return Convert;
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker   // Not all calling conventions have only stack MOVs between the stack
272*9880d681SAndroid Build Coastguard Worker   // adjust and the call.
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   // We want to tolerate other instructions, to cover more cases.
275*9880d681SAndroid Build Coastguard Worker   // In particular:
276*9880d681SAndroid Build Coastguard Worker   // a) PCrel calls, where we expect an additional COPY of the basereg.
277*9880d681SAndroid Build Coastguard Worker   // b) Passing frame-index addresses.
278*9880d681SAndroid Build Coastguard Worker   // c) Calling conventions that have inreg parameters. These generate
279*9880d681SAndroid Build Coastguard Worker   //    both copies and movs into registers.
280*9880d681SAndroid Build Coastguard Worker   // To avoid creating lots of special cases, allow any instruction
281*9880d681SAndroid Build Coastguard Worker   // that does not write into memory, does not def or use the stack
282*9880d681SAndroid Build Coastguard Worker   // pointer, and does not def any register that was used by a preceding
283*9880d681SAndroid Build Coastguard Worker   // push.
284*9880d681SAndroid Build Coastguard Worker   // (Reading from memory is allowed, even if referenced through a
285*9880d681SAndroid Build Coastguard Worker   // frame index, since these will get adjusted properly in PEI)
286*9880d681SAndroid Build Coastguard Worker 
287*9880d681SAndroid Build Coastguard Worker   // The reason for the last condition is that the pushes can't replace
288*9880d681SAndroid Build Coastguard Worker   // the movs in place, because the order must be reversed.
289*9880d681SAndroid Build Coastguard Worker   // So if we have a MOV32mr that uses EDX, then an instruction that defs
290*9880d681SAndroid Build Coastguard Worker   // EDX, and then the call, after the transformation the push will use
291*9880d681SAndroid Build Coastguard Worker   // the modified version of EDX, and not the original one.
292*9880d681SAndroid Build Coastguard Worker   // Since we are still in SSA form at this point, we only need to
293*9880d681SAndroid Build Coastguard Worker   // make sure we don't clobber any *physical* registers that were
294*9880d681SAndroid Build Coastguard Worker   // used by an earlier mov that will become a push.
295*9880d681SAndroid Build Coastguard Worker 
296*9880d681SAndroid Build Coastguard Worker   if (MI->isCall() || MI->mayStore())
297*9880d681SAndroid Build Coastguard Worker     return Exit;
298*9880d681SAndroid Build Coastguard Worker 
299*9880d681SAndroid Build Coastguard Worker   for (const MachineOperand &MO : MI->operands()) {
300*9880d681SAndroid Build Coastguard Worker     if (!MO.isReg())
301*9880d681SAndroid Build Coastguard Worker       continue;
302*9880d681SAndroid Build Coastguard Worker     unsigned int Reg = MO.getReg();
303*9880d681SAndroid Build Coastguard Worker     if (!RegInfo.isPhysicalRegister(Reg))
304*9880d681SAndroid Build Coastguard Worker       continue;
305*9880d681SAndroid Build Coastguard Worker     if (RegInfo.regsOverlap(Reg, RegInfo.getStackRegister()))
306*9880d681SAndroid Build Coastguard Worker       return Exit;
307*9880d681SAndroid Build Coastguard Worker     if (MO.isDef()) {
308*9880d681SAndroid Build Coastguard Worker       for (unsigned int U : UsedRegs)
309*9880d681SAndroid Build Coastguard Worker         if (RegInfo.regsOverlap(Reg, U))
310*9880d681SAndroid Build Coastguard Worker           return Exit;
311*9880d681SAndroid Build Coastguard Worker     }
312*9880d681SAndroid Build Coastguard Worker   }
313*9880d681SAndroid Build Coastguard Worker 
314*9880d681SAndroid Build Coastguard Worker   return Skip;
315*9880d681SAndroid Build Coastguard Worker }
316*9880d681SAndroid Build Coastguard Worker 
collectCallInfo(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I,CallContext & Context)317*9880d681SAndroid Build Coastguard Worker void X86CallFrameOptimization::collectCallInfo(MachineFunction &MF,
318*9880d681SAndroid Build Coastguard Worker                                                MachineBasicBlock &MBB,
319*9880d681SAndroid Build Coastguard Worker                                                MachineBasicBlock::iterator I,
320*9880d681SAndroid Build Coastguard Worker                                                CallContext &Context) {
321*9880d681SAndroid Build Coastguard Worker   // Check that this particular call sequence is amenable to the
322*9880d681SAndroid Build Coastguard Worker   // transformation.
323*9880d681SAndroid Build Coastguard Worker   const X86RegisterInfo &RegInfo =
324*9880d681SAndroid Build Coastguard Worker       *static_cast<const X86RegisterInfo *>(STI->getRegisterInfo());
325*9880d681SAndroid Build Coastguard Worker   unsigned FrameDestroyOpcode = TII->getCallFrameDestroyOpcode();
326*9880d681SAndroid Build Coastguard Worker 
327*9880d681SAndroid Build Coastguard Worker   // We expect to enter this at the beginning of a call sequence
328*9880d681SAndroid Build Coastguard Worker   assert(I->getOpcode() == TII->getCallFrameSetupOpcode());
329*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator FrameSetup = I++;
330*9880d681SAndroid Build Coastguard Worker   Context.FrameSetup = FrameSetup;
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker   // How much do we adjust the stack? This puts an upper bound on
333*9880d681SAndroid Build Coastguard Worker   // the number of parameters actually passed on it.
334*9880d681SAndroid Build Coastguard Worker   unsigned int MaxAdjust =
335*9880d681SAndroid Build Coastguard Worker       FrameSetup->getOperand(0).getImm() >> Log2SlotSize;
336*9880d681SAndroid Build Coastguard Worker 
337*9880d681SAndroid Build Coastguard Worker   // A zero adjustment means no stack parameters
338*9880d681SAndroid Build Coastguard Worker   if (!MaxAdjust) {
339*9880d681SAndroid Build Coastguard Worker     Context.NoStackParams = true;
340*9880d681SAndroid Build Coastguard Worker     return;
341*9880d681SAndroid Build Coastguard Worker   }
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   // For globals in PIC mode, we can have some LEAs here.
344*9880d681SAndroid Build Coastguard Worker   // Ignore them, they don't bother us.
345*9880d681SAndroid Build Coastguard Worker   // TODO: Extend this to something that covers more cases.
346*9880d681SAndroid Build Coastguard Worker   while (I->getOpcode() == X86::LEA32r)
347*9880d681SAndroid Build Coastguard Worker     ++I;
348*9880d681SAndroid Build Coastguard Worker 
349*9880d681SAndroid Build Coastguard Worker   unsigned StackPtr = RegInfo.getStackRegister();
350*9880d681SAndroid Build Coastguard Worker   // SelectionDAG (but not FastISel) inserts a copy of ESP into a virtual
351*9880d681SAndroid Build Coastguard Worker   // register here.  If it's there, use that virtual register as stack pointer
352*9880d681SAndroid Build Coastguard Worker   // instead.
353*9880d681SAndroid Build Coastguard Worker   if (I->isCopy() && I->getOperand(0).isReg() && I->getOperand(1).isReg() &&
354*9880d681SAndroid Build Coastguard Worker       I->getOperand(1).getReg() == StackPtr) {
355*9880d681SAndroid Build Coastguard Worker     Context.SPCopy = &*I++;
356*9880d681SAndroid Build Coastguard Worker     StackPtr = Context.SPCopy->getOperand(0).getReg();
357*9880d681SAndroid Build Coastguard Worker   }
358*9880d681SAndroid Build Coastguard Worker 
359*9880d681SAndroid Build Coastguard Worker   // Scan the call setup sequence for the pattern we're looking for.
360*9880d681SAndroid Build Coastguard Worker   // We only handle a simple case - a sequence of store instructions that
361*9880d681SAndroid Build Coastguard Worker   // push a sequence of stack-slot-aligned values onto the stack, with
362*9880d681SAndroid Build Coastguard Worker   // no gaps between them.
363*9880d681SAndroid Build Coastguard Worker   if (MaxAdjust > 4)
364*9880d681SAndroid Build Coastguard Worker     Context.MovVector.resize(MaxAdjust, nullptr);
365*9880d681SAndroid Build Coastguard Worker 
366*9880d681SAndroid Build Coastguard Worker   InstClassification Classification;
367*9880d681SAndroid Build Coastguard Worker   DenseSet<unsigned int> UsedRegs;
368*9880d681SAndroid Build Coastguard Worker 
369*9880d681SAndroid Build Coastguard Worker   while ((Classification = classifyInstruction(MBB, I, RegInfo, UsedRegs)) !=
370*9880d681SAndroid Build Coastguard Worker          Exit) {
371*9880d681SAndroid Build Coastguard Worker     if (Classification == Skip) {
372*9880d681SAndroid Build Coastguard Worker       ++I;
373*9880d681SAndroid Build Coastguard Worker       continue;
374*9880d681SAndroid Build Coastguard Worker     }
375*9880d681SAndroid Build Coastguard Worker 
376*9880d681SAndroid Build Coastguard Worker     // We know the instruction has a supported store opcode.
377*9880d681SAndroid Build Coastguard Worker     // We only want movs of the form:
378*9880d681SAndroid Build Coastguard Worker     // mov imm/reg, k(%StackPtr)
379*9880d681SAndroid Build Coastguard Worker     // If we run into something else, bail.
380*9880d681SAndroid Build Coastguard Worker     // Note that AddrBaseReg may, counter to its name, not be a register,
381*9880d681SAndroid Build Coastguard Worker     // but rather a frame index.
382*9880d681SAndroid Build Coastguard Worker     // TODO: Support the fi case. This should probably work now that we
383*9880d681SAndroid Build Coastguard Worker     // have the infrastructure to track the stack pointer within a call
384*9880d681SAndroid Build Coastguard Worker     // sequence.
385*9880d681SAndroid Build Coastguard Worker     if (!I->getOperand(X86::AddrBaseReg).isReg() ||
386*9880d681SAndroid Build Coastguard Worker         (I->getOperand(X86::AddrBaseReg).getReg() != StackPtr) ||
387*9880d681SAndroid Build Coastguard Worker         !I->getOperand(X86::AddrScaleAmt).isImm() ||
388*9880d681SAndroid Build Coastguard Worker         (I->getOperand(X86::AddrScaleAmt).getImm() != 1) ||
389*9880d681SAndroid Build Coastguard Worker         (I->getOperand(X86::AddrIndexReg).getReg() != X86::NoRegister) ||
390*9880d681SAndroid Build Coastguard Worker         (I->getOperand(X86::AddrSegmentReg).getReg() != X86::NoRegister) ||
391*9880d681SAndroid Build Coastguard Worker         !I->getOperand(X86::AddrDisp).isImm())
392*9880d681SAndroid Build Coastguard Worker       return;
393*9880d681SAndroid Build Coastguard Worker 
394*9880d681SAndroid Build Coastguard Worker     int64_t StackDisp = I->getOperand(X86::AddrDisp).getImm();
395*9880d681SAndroid Build Coastguard Worker     assert(StackDisp >= 0 &&
396*9880d681SAndroid Build Coastguard Worker            "Negative stack displacement when passing parameters");
397*9880d681SAndroid Build Coastguard Worker 
398*9880d681SAndroid Build Coastguard Worker     // We really don't want to consider the unaligned case.
399*9880d681SAndroid Build Coastguard Worker     if (StackDisp & (SlotSize - 1))
400*9880d681SAndroid Build Coastguard Worker       return;
401*9880d681SAndroid Build Coastguard Worker     StackDisp >>= Log2SlotSize;
402*9880d681SAndroid Build Coastguard Worker 
403*9880d681SAndroid Build Coastguard Worker     assert((size_t)StackDisp < Context.MovVector.size() &&
404*9880d681SAndroid Build Coastguard Worker            "Function call has more parameters than the stack is adjusted for.");
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker     // If the same stack slot is being filled twice, something's fishy.
407*9880d681SAndroid Build Coastguard Worker     if (Context.MovVector[StackDisp] != nullptr)
408*9880d681SAndroid Build Coastguard Worker       return;
409*9880d681SAndroid Build Coastguard Worker     Context.MovVector[StackDisp] = &*I;
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker     for (const MachineOperand &MO : I->uses()) {
412*9880d681SAndroid Build Coastguard Worker       if (!MO.isReg())
413*9880d681SAndroid Build Coastguard Worker         continue;
414*9880d681SAndroid Build Coastguard Worker       unsigned int Reg = MO.getReg();
415*9880d681SAndroid Build Coastguard Worker       if (RegInfo.isPhysicalRegister(Reg))
416*9880d681SAndroid Build Coastguard Worker         UsedRegs.insert(Reg);
417*9880d681SAndroid Build Coastguard Worker     }
418*9880d681SAndroid Build Coastguard Worker 
419*9880d681SAndroid Build Coastguard Worker     ++I;
420*9880d681SAndroid Build Coastguard Worker   }
421*9880d681SAndroid Build Coastguard Worker 
422*9880d681SAndroid Build Coastguard Worker   // We now expect the end of the sequence. If we stopped early,
423*9880d681SAndroid Build Coastguard Worker   // or reached the end of the block without finding a call, bail.
424*9880d681SAndroid Build Coastguard Worker   if (I == MBB.end() || !I->isCall())
425*9880d681SAndroid Build Coastguard Worker     return;
426*9880d681SAndroid Build Coastguard Worker 
427*9880d681SAndroid Build Coastguard Worker   Context.Call = &*I;
428*9880d681SAndroid Build Coastguard Worker   if ((++I)->getOpcode() != FrameDestroyOpcode)
429*9880d681SAndroid Build Coastguard Worker     return;
430*9880d681SAndroid Build Coastguard Worker 
431*9880d681SAndroid Build Coastguard Worker   // Now, go through the vector, and see that we don't have any gaps,
432*9880d681SAndroid Build Coastguard Worker   // but only a series of MOVs.
433*9880d681SAndroid Build Coastguard Worker   auto MMI = Context.MovVector.begin(), MME = Context.MovVector.end();
434*9880d681SAndroid Build Coastguard Worker   for (; MMI != MME; ++MMI, Context.ExpectedDist += SlotSize)
435*9880d681SAndroid Build Coastguard Worker     if (*MMI == nullptr)
436*9880d681SAndroid Build Coastguard Worker       break;
437*9880d681SAndroid Build Coastguard Worker 
438*9880d681SAndroid Build Coastguard Worker   // If the call had no parameters, do nothing
439*9880d681SAndroid Build Coastguard Worker   if (MMI == Context.MovVector.begin())
440*9880d681SAndroid Build Coastguard Worker     return;
441*9880d681SAndroid Build Coastguard Worker 
442*9880d681SAndroid Build Coastguard Worker   // We are either at the last parameter, or a gap.
443*9880d681SAndroid Build Coastguard Worker   // Make sure it's not a gap
444*9880d681SAndroid Build Coastguard Worker   for (; MMI != MME; ++MMI)
445*9880d681SAndroid Build Coastguard Worker     if (*MMI != nullptr)
446*9880d681SAndroid Build Coastguard Worker       return;
447*9880d681SAndroid Build Coastguard Worker 
448*9880d681SAndroid Build Coastguard Worker   Context.UsePush = true;
449*9880d681SAndroid Build Coastguard Worker }
450*9880d681SAndroid Build Coastguard Worker 
adjustCallSequence(MachineFunction & MF,const CallContext & Context)451*9880d681SAndroid Build Coastguard Worker void X86CallFrameOptimization::adjustCallSequence(MachineFunction &MF,
452*9880d681SAndroid Build Coastguard Worker                                                   const CallContext &Context) {
453*9880d681SAndroid Build Coastguard Worker   // Ok, we can in fact do the transformation for this call.
454*9880d681SAndroid Build Coastguard Worker   // Do not remove the FrameSetup instruction, but adjust the parameters.
455*9880d681SAndroid Build Coastguard Worker   // PEI will end up finalizing the handling of this.
456*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator FrameSetup = Context.FrameSetup;
457*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock &MBB = *(FrameSetup->getParent());
458*9880d681SAndroid Build Coastguard Worker   FrameSetup->getOperand(1).setImm(Context.ExpectedDist);
459*9880d681SAndroid Build Coastguard Worker 
460*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = FrameSetup->getDebugLoc();
461*9880d681SAndroid Build Coastguard Worker   bool Is64Bit = STI->is64Bit();
462*9880d681SAndroid Build Coastguard Worker   // Now, iterate through the vector in reverse order, and replace the movs
463*9880d681SAndroid Build Coastguard Worker   // with pushes. MOVmi/MOVmr doesn't have any defs, so no need to
464*9880d681SAndroid Build Coastguard Worker   // replace uses.
465*9880d681SAndroid Build Coastguard Worker   for (int Idx = (Context.ExpectedDist >> Log2SlotSize) - 1; Idx >= 0; --Idx) {
466*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator MOV = *Context.MovVector[Idx];
467*9880d681SAndroid Build Coastguard Worker     MachineOperand PushOp = MOV->getOperand(X86::AddrNumOperands);
468*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator Push = nullptr;
469*9880d681SAndroid Build Coastguard Worker     unsigned PushOpcode;
470*9880d681SAndroid Build Coastguard Worker     switch (MOV->getOpcode()) {
471*9880d681SAndroid Build Coastguard Worker     default:
472*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Unexpected Opcode!");
473*9880d681SAndroid Build Coastguard Worker     case X86::MOV32mi:
474*9880d681SAndroid Build Coastguard Worker     case X86::MOV64mi32:
475*9880d681SAndroid Build Coastguard Worker       PushOpcode = Is64Bit ? X86::PUSH64i32 : X86::PUSHi32;
476*9880d681SAndroid Build Coastguard Worker       // If the operand is a small (8-bit) immediate, we can use a
477*9880d681SAndroid Build Coastguard Worker       // PUSH instruction with a shorter encoding.
478*9880d681SAndroid Build Coastguard Worker       // Note that isImm() may fail even though this is a MOVmi, because
479*9880d681SAndroid Build Coastguard Worker       // the operand can also be a symbol.
480*9880d681SAndroid Build Coastguard Worker       if (PushOp.isImm()) {
481*9880d681SAndroid Build Coastguard Worker         int64_t Val = PushOp.getImm();
482*9880d681SAndroid Build Coastguard Worker         if (isInt<8>(Val))
483*9880d681SAndroid Build Coastguard Worker           PushOpcode = Is64Bit ? X86::PUSH64i8 : X86::PUSH32i8;
484*9880d681SAndroid Build Coastguard Worker       }
485*9880d681SAndroid Build Coastguard Worker       Push = BuildMI(MBB, Context.Call, DL, TII->get(PushOpcode))
486*9880d681SAndroid Build Coastguard Worker                  .addOperand(PushOp);
487*9880d681SAndroid Build Coastguard Worker       break;
488*9880d681SAndroid Build Coastguard Worker     case X86::MOV32mr:
489*9880d681SAndroid Build Coastguard Worker     case X86::MOV64mr:
490*9880d681SAndroid Build Coastguard Worker       unsigned int Reg = PushOp.getReg();
491*9880d681SAndroid Build Coastguard Worker 
492*9880d681SAndroid Build Coastguard Worker       // If storing a 32-bit vreg on 64-bit targets, extend to a 64-bit vreg
493*9880d681SAndroid Build Coastguard Worker       // in preparation for the PUSH64. The upper 32 bits can be undef.
494*9880d681SAndroid Build Coastguard Worker       if (Is64Bit && MOV->getOpcode() == X86::MOV32mr) {
495*9880d681SAndroid Build Coastguard Worker         unsigned UndefReg = MRI->createVirtualRegister(&X86::GR64RegClass);
496*9880d681SAndroid Build Coastguard Worker         Reg = MRI->createVirtualRegister(&X86::GR64RegClass);
497*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, Context.Call, DL, TII->get(X86::IMPLICIT_DEF), UndefReg);
498*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, Context.Call, DL, TII->get(X86::INSERT_SUBREG), Reg)
499*9880d681SAndroid Build Coastguard Worker           .addReg(UndefReg)
500*9880d681SAndroid Build Coastguard Worker           .addOperand(PushOp)
501*9880d681SAndroid Build Coastguard Worker           .addImm(X86::sub_32bit);
502*9880d681SAndroid Build Coastguard Worker       }
503*9880d681SAndroid Build Coastguard Worker 
504*9880d681SAndroid Build Coastguard Worker       // If PUSHrmm is not slow on this target, try to fold the source of the
505*9880d681SAndroid Build Coastguard Worker       // push into the instruction.
506*9880d681SAndroid Build Coastguard Worker       bool SlowPUSHrmm = STI->isAtom() || STI->isSLM();
507*9880d681SAndroid Build Coastguard Worker 
508*9880d681SAndroid Build Coastguard Worker       // Check that this is legal to fold. Right now, we're extremely
509*9880d681SAndroid Build Coastguard Worker       // conservative about that.
510*9880d681SAndroid Build Coastguard Worker       MachineInstr *DefMov = nullptr;
511*9880d681SAndroid Build Coastguard Worker       if (!SlowPUSHrmm && (DefMov = canFoldIntoRegPush(FrameSetup, Reg))) {
512*9880d681SAndroid Build Coastguard Worker         PushOpcode = Is64Bit ? X86::PUSH64rmm : X86::PUSH32rmm;
513*9880d681SAndroid Build Coastguard Worker         Push = BuildMI(MBB, Context.Call, DL, TII->get(PushOpcode));
514*9880d681SAndroid Build Coastguard Worker 
515*9880d681SAndroid Build Coastguard Worker         unsigned NumOps = DefMov->getDesc().getNumOperands();
516*9880d681SAndroid Build Coastguard Worker         for (unsigned i = NumOps - X86::AddrNumOperands; i != NumOps; ++i)
517*9880d681SAndroid Build Coastguard Worker           Push->addOperand(DefMov->getOperand(i));
518*9880d681SAndroid Build Coastguard Worker 
519*9880d681SAndroid Build Coastguard Worker         DefMov->eraseFromParent();
520*9880d681SAndroid Build Coastguard Worker       } else {
521*9880d681SAndroid Build Coastguard Worker         PushOpcode = Is64Bit ? X86::PUSH64r : X86::PUSH32r;
522*9880d681SAndroid Build Coastguard Worker         Push = BuildMI(MBB, Context.Call, DL, TII->get(PushOpcode))
523*9880d681SAndroid Build Coastguard Worker                    .addReg(Reg)
524*9880d681SAndroid Build Coastguard Worker                    .getInstr();
525*9880d681SAndroid Build Coastguard Worker       }
526*9880d681SAndroid Build Coastguard Worker       break;
527*9880d681SAndroid Build Coastguard Worker     }
528*9880d681SAndroid Build Coastguard Worker 
529*9880d681SAndroid Build Coastguard Worker     // For debugging, when using SP-based CFA, we need to adjust the CFA
530*9880d681SAndroid Build Coastguard Worker     // offset after each push.
531*9880d681SAndroid Build Coastguard Worker     // TODO: This is needed only if we require precise CFA.
532*9880d681SAndroid Build Coastguard Worker     if (!TFL->hasFP(MF))
533*9880d681SAndroid Build Coastguard Worker       TFL->BuildCFI(
534*9880d681SAndroid Build Coastguard Worker           MBB, std::next(Push), DL,
535*9880d681SAndroid Build Coastguard Worker           MCCFIInstruction::createAdjustCfaOffset(nullptr, SlotSize));
536*9880d681SAndroid Build Coastguard Worker 
537*9880d681SAndroid Build Coastguard Worker     MBB.erase(MOV);
538*9880d681SAndroid Build Coastguard Worker   }
539*9880d681SAndroid Build Coastguard Worker 
540*9880d681SAndroid Build Coastguard Worker   // The stack-pointer copy is no longer used in the call sequences.
541*9880d681SAndroid Build Coastguard Worker   // There should not be any other users, but we can't commit to that, so:
542*9880d681SAndroid Build Coastguard Worker   if (Context.SPCopy && MRI->use_empty(Context.SPCopy->getOperand(0).getReg()))
543*9880d681SAndroid Build Coastguard Worker     Context.SPCopy->eraseFromParent();
544*9880d681SAndroid Build Coastguard Worker 
545*9880d681SAndroid Build Coastguard Worker   // Once we've done this, we need to make sure PEI doesn't assume a reserved
546*9880d681SAndroid Build Coastguard Worker   // frame.
547*9880d681SAndroid Build Coastguard Worker   X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
548*9880d681SAndroid Build Coastguard Worker   FuncInfo->setHasPushSequences(true);
549*9880d681SAndroid Build Coastguard Worker }
550*9880d681SAndroid Build Coastguard Worker 
canFoldIntoRegPush(MachineBasicBlock::iterator FrameSetup,unsigned Reg)551*9880d681SAndroid Build Coastguard Worker MachineInstr *X86CallFrameOptimization::canFoldIntoRegPush(
552*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator FrameSetup, unsigned Reg) {
553*9880d681SAndroid Build Coastguard Worker   // Do an extremely restricted form of load folding.
554*9880d681SAndroid Build Coastguard Worker   // ISel will often create patterns like:
555*9880d681SAndroid Build Coastguard Worker   // movl    4(%edi), %eax
556*9880d681SAndroid Build Coastguard Worker   // movl    8(%edi), %ecx
557*9880d681SAndroid Build Coastguard Worker   // movl    12(%edi), %edx
558*9880d681SAndroid Build Coastguard Worker   // movl    %edx, 8(%esp)
559*9880d681SAndroid Build Coastguard Worker   // movl    %ecx, 4(%esp)
560*9880d681SAndroid Build Coastguard Worker   // movl    %eax, (%esp)
561*9880d681SAndroid Build Coastguard Worker   // call
562*9880d681SAndroid Build Coastguard Worker   // Get rid of those with prejudice.
563*9880d681SAndroid Build Coastguard Worker   if (!TargetRegisterInfo::isVirtualRegister(Reg))
564*9880d681SAndroid Build Coastguard Worker     return nullptr;
565*9880d681SAndroid Build Coastguard Worker 
566*9880d681SAndroid Build Coastguard Worker   // Make sure this is the only use of Reg.
567*9880d681SAndroid Build Coastguard Worker   if (!MRI->hasOneNonDBGUse(Reg))
568*9880d681SAndroid Build Coastguard Worker     return nullptr;
569*9880d681SAndroid Build Coastguard Worker 
570*9880d681SAndroid Build Coastguard Worker   MachineInstr &DefMI = *MRI->getVRegDef(Reg);
571*9880d681SAndroid Build Coastguard Worker 
572*9880d681SAndroid Build Coastguard Worker   // Make sure the def is a MOV from memory.
573*9880d681SAndroid Build Coastguard Worker   // If the def is in another block, give up.
574*9880d681SAndroid Build Coastguard Worker   if ((DefMI.getOpcode() != X86::MOV32rm &&
575*9880d681SAndroid Build Coastguard Worker        DefMI.getOpcode() != X86::MOV64rm) ||
576*9880d681SAndroid Build Coastguard Worker       DefMI.getParent() != FrameSetup->getParent())
577*9880d681SAndroid Build Coastguard Worker     return nullptr;
578*9880d681SAndroid Build Coastguard Worker 
579*9880d681SAndroid Build Coastguard Worker   // Make sure we don't have any instructions between DefMI and the
580*9880d681SAndroid Build Coastguard Worker   // push that make folding the load illegal.
581*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::iterator I = DefMI; I != FrameSetup; ++I)
582*9880d681SAndroid Build Coastguard Worker     if (I->isLoadFoldBarrier())
583*9880d681SAndroid Build Coastguard Worker       return nullptr;
584*9880d681SAndroid Build Coastguard Worker 
585*9880d681SAndroid Build Coastguard Worker   return &DefMI;
586*9880d681SAndroid Build Coastguard Worker }
587