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