1*9880d681SAndroid Build Coastguard Worker //===-- NVPTXPrologEpilogPass.cpp - NVPTX prolog/epilog inserter ----------===//
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 is a copy of the generic LLVM PrologEpilogInserter pass, modified
11*9880d681SAndroid Build Coastguard Worker // to remove unneeded functionality and to handle virtual registers. Most code
12*9880d681SAndroid Build Coastguard Worker // here is a copy of PrologEpilogInserter.cpp.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "NVPTX.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetFrameLowering.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "nvptx-prolog-epilog"
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker namespace {
32*9880d681SAndroid Build Coastguard Worker class NVPTXPrologEpilogPass : public MachineFunctionPass {
33*9880d681SAndroid Build Coastguard Worker public:
34*9880d681SAndroid Build Coastguard Worker static char ID;
NVPTXPrologEpilogPass()35*9880d681SAndroid Build Coastguard Worker NVPTXPrologEpilogPass() : MachineFunctionPass(ID) {}
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &MF) override;
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker private:
40*9880d681SAndroid Build Coastguard Worker void calculateFrameObjectOffsets(MachineFunction &Fn);
41*9880d681SAndroid Build Coastguard Worker };
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker
createNVPTXPrologEpilogPass()44*9880d681SAndroid Build Coastguard Worker MachineFunctionPass *llvm::createNVPTXPrologEpilogPass() {
45*9880d681SAndroid Build Coastguard Worker return new NVPTXPrologEpilogPass();
46*9880d681SAndroid Build Coastguard Worker }
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker char NVPTXPrologEpilogPass::ID = 0;
49*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)50*9880d681SAndroid Build Coastguard Worker bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) {
51*9880d681SAndroid Build Coastguard Worker const TargetSubtargetInfo &STI = MF.getSubtarget();
52*9880d681SAndroid Build Coastguard Worker const TargetFrameLowering &TFI = *STI.getFrameLowering();
53*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
54*9880d681SAndroid Build Coastguard Worker bool Modified = false;
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker calculateFrameObjectOffsets(MF);
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock &MBB : MF) {
59*9880d681SAndroid Build Coastguard Worker for (MachineInstr &MI : MBB) {
60*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
61*9880d681SAndroid Build Coastguard Worker if (!MI.getOperand(i).isFI())
62*9880d681SAndroid Build Coastguard Worker continue;
63*9880d681SAndroid Build Coastguard Worker TRI.eliminateFrameIndex(MI, 0, i, nullptr);
64*9880d681SAndroid Build Coastguard Worker Modified = true;
65*9880d681SAndroid Build Coastguard Worker }
66*9880d681SAndroid Build Coastguard Worker }
67*9880d681SAndroid Build Coastguard Worker }
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker // Add function prolog/epilog
70*9880d681SAndroid Build Coastguard Worker TFI.emitPrologue(MF, MF.front());
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
73*9880d681SAndroid Build Coastguard Worker // If last instruction is a return instruction, add an epilogue
74*9880d681SAndroid Build Coastguard Worker if (I->isReturnBlock())
75*9880d681SAndroid Build Coastguard Worker TFI.emitEpilogue(MF, *I);
76*9880d681SAndroid Build Coastguard Worker }
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker return Modified;
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker /// AdjustStackOffset - Helper function used to adjust the stack frame offset.
82*9880d681SAndroid Build Coastguard Worker static inline void
AdjustStackOffset(MachineFrameInfo * MFI,int FrameIdx,bool StackGrowsDown,int64_t & Offset,unsigned & MaxAlign)83*9880d681SAndroid Build Coastguard Worker AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx,
84*9880d681SAndroid Build Coastguard Worker bool StackGrowsDown, int64_t &Offset,
85*9880d681SAndroid Build Coastguard Worker unsigned &MaxAlign) {
86*9880d681SAndroid Build Coastguard Worker // If the stack grows down, add the object size to find the lowest address.
87*9880d681SAndroid Build Coastguard Worker if (StackGrowsDown)
88*9880d681SAndroid Build Coastguard Worker Offset += MFI->getObjectSize(FrameIdx);
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker unsigned Align = MFI->getObjectAlignment(FrameIdx);
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker // If the alignment of this object is greater than that of the stack, then
93*9880d681SAndroid Build Coastguard Worker // increase the stack alignment to match.
94*9880d681SAndroid Build Coastguard Worker MaxAlign = std::max(MaxAlign, Align);
95*9880d681SAndroid Build Coastguard Worker
96*9880d681SAndroid Build Coastguard Worker // Adjust to alignment boundary.
97*9880d681SAndroid Build Coastguard Worker Offset = (Offset + Align - 1) / Align * Align;
98*9880d681SAndroid Build Coastguard Worker
99*9880d681SAndroid Build Coastguard Worker if (StackGrowsDown) {
100*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n");
101*9880d681SAndroid Build Coastguard Worker MFI->setObjectOffset(FrameIdx, -Offset); // Set the computed offset
102*9880d681SAndroid Build Coastguard Worker } else {
103*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset << "]\n");
104*9880d681SAndroid Build Coastguard Worker MFI->setObjectOffset(FrameIdx, Offset);
105*9880d681SAndroid Build Coastguard Worker Offset += MFI->getObjectSize(FrameIdx);
106*9880d681SAndroid Build Coastguard Worker }
107*9880d681SAndroid Build Coastguard Worker }
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker void
calculateFrameObjectOffsets(MachineFunction & Fn)110*9880d681SAndroid Build Coastguard Worker NVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
111*9880d681SAndroid Build Coastguard Worker const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering();
112*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo();
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker bool StackGrowsDown =
115*9880d681SAndroid Build Coastguard Worker TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown;
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker // Loop over all of the stack objects, assigning sequential addresses...
118*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = Fn.getFrameInfo();
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker // Start at the beginning of the local area.
121*9880d681SAndroid Build Coastguard Worker // The Offset is the distance from the stack top in the direction
122*9880d681SAndroid Build Coastguard Worker // of stack growth -- so it's always nonnegative.
123*9880d681SAndroid Build Coastguard Worker int LocalAreaOffset = TFI.getOffsetOfLocalArea();
124*9880d681SAndroid Build Coastguard Worker if (StackGrowsDown)
125*9880d681SAndroid Build Coastguard Worker LocalAreaOffset = -LocalAreaOffset;
126*9880d681SAndroid Build Coastguard Worker assert(LocalAreaOffset >= 0
127*9880d681SAndroid Build Coastguard Worker && "Local area offset should be in direction of stack growth");
128*9880d681SAndroid Build Coastguard Worker int64_t Offset = LocalAreaOffset;
129*9880d681SAndroid Build Coastguard Worker
130*9880d681SAndroid Build Coastguard Worker // If there are fixed sized objects that are preallocated in the local area,
131*9880d681SAndroid Build Coastguard Worker // non-fixed objects can't be allocated right at the start of local area.
132*9880d681SAndroid Build Coastguard Worker // We currently don't support filling in holes in between fixed sized
133*9880d681SAndroid Build Coastguard Worker // objects, so we adjust 'Offset' to point to the end of last fixed sized
134*9880d681SAndroid Build Coastguard Worker // preallocated object.
135*9880d681SAndroid Build Coastguard Worker for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) {
136*9880d681SAndroid Build Coastguard Worker int64_t FixedOff;
137*9880d681SAndroid Build Coastguard Worker if (StackGrowsDown) {
138*9880d681SAndroid Build Coastguard Worker // The maximum distance from the stack pointer is at lower address of
139*9880d681SAndroid Build Coastguard Worker // the object -- which is given by offset. For down growing stack
140*9880d681SAndroid Build Coastguard Worker // the offset is negative, so we negate the offset to get the distance.
141*9880d681SAndroid Build Coastguard Worker FixedOff = -MFI->getObjectOffset(i);
142*9880d681SAndroid Build Coastguard Worker } else {
143*9880d681SAndroid Build Coastguard Worker // The maximum distance from the start pointer is at the upper
144*9880d681SAndroid Build Coastguard Worker // address of the object.
145*9880d681SAndroid Build Coastguard Worker FixedOff = MFI->getObjectOffset(i) + MFI->getObjectSize(i);
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker if (FixedOff > Offset) Offset = FixedOff;
148*9880d681SAndroid Build Coastguard Worker }
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker // NOTE: We do not have a call stack
151*9880d681SAndroid Build Coastguard Worker
152*9880d681SAndroid Build Coastguard Worker unsigned MaxAlign = MFI->getMaxAlignment();
153*9880d681SAndroid Build Coastguard Worker
154*9880d681SAndroid Build Coastguard Worker // No scavenger
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker // FIXME: Once this is working, then enable flag will change to a target
157*9880d681SAndroid Build Coastguard Worker // check for whether the frame is large enough to want to use virtual
158*9880d681SAndroid Build Coastguard Worker // frame index registers. Functions which don't want/need this optimization
159*9880d681SAndroid Build Coastguard Worker // will continue to use the existing code path.
160*9880d681SAndroid Build Coastguard Worker if (MFI->getUseLocalStackAllocationBlock()) {
161*9880d681SAndroid Build Coastguard Worker unsigned Align = MFI->getLocalFrameMaxAlign();
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker // Adjust to alignment boundary.
164*9880d681SAndroid Build Coastguard Worker Offset = (Offset + Align - 1) / Align * Align;
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker // Resolve offsets for objects in the local block.
169*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) {
170*9880d681SAndroid Build Coastguard Worker std::pair<int, int64_t> Entry = MFI->getLocalFrameObjectMap(i);
171*9880d681SAndroid Build Coastguard Worker int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;
172*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" <<
173*9880d681SAndroid Build Coastguard Worker FIOffset << "]\n");
174*9880d681SAndroid Build Coastguard Worker MFI->setObjectOffset(Entry.first, FIOffset);
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker // Allocate the local block
177*9880d681SAndroid Build Coastguard Worker Offset += MFI->getLocalFrameSize();
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker MaxAlign = std::max(Align, MaxAlign);
180*9880d681SAndroid Build Coastguard Worker }
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker // No stack protector
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker // Then assign frame offsets to stack objects that are not used to spill
185*9880d681SAndroid Build Coastguard Worker // callee saved registers.
186*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) {
187*9880d681SAndroid Build Coastguard Worker if (MFI->isObjectPreAllocated(i) &&
188*9880d681SAndroid Build Coastguard Worker MFI->getUseLocalStackAllocationBlock())
189*9880d681SAndroid Build Coastguard Worker continue;
190*9880d681SAndroid Build Coastguard Worker if (MFI->isDeadObjectIndex(i))
191*9880d681SAndroid Build Coastguard Worker continue;
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker // No scavenger
197*9880d681SAndroid Build Coastguard Worker
198*9880d681SAndroid Build Coastguard Worker if (!TFI.targetHandlesStackFrameRounding()) {
199*9880d681SAndroid Build Coastguard Worker // If we have reserved argument space for call sites in the function
200*9880d681SAndroid Build Coastguard Worker // immediately on entry to the current function, count it as part of the
201*9880d681SAndroid Build Coastguard Worker // overall stack size.
202*9880d681SAndroid Build Coastguard Worker if (MFI->adjustsStack() && TFI.hasReservedCallFrame(Fn))
203*9880d681SAndroid Build Coastguard Worker Offset += MFI->getMaxCallFrameSize();
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker // Round up the size to a multiple of the alignment. If the function has
206*9880d681SAndroid Build Coastguard Worker // any calls or alloca's, align to the target's StackAlignment value to
207*9880d681SAndroid Build Coastguard Worker // ensure that the callee's frame or the alloca data is suitably aligned;
208*9880d681SAndroid Build Coastguard Worker // otherwise, for leaf functions, align to the TransientStackAlignment
209*9880d681SAndroid Build Coastguard Worker // value.
210*9880d681SAndroid Build Coastguard Worker unsigned StackAlign;
211*9880d681SAndroid Build Coastguard Worker if (MFI->adjustsStack() || MFI->hasVarSizedObjects() ||
212*9880d681SAndroid Build Coastguard Worker (RegInfo->needsStackRealignment(Fn) && MFI->getObjectIndexEnd() != 0))
213*9880d681SAndroid Build Coastguard Worker StackAlign = TFI.getStackAlignment();
214*9880d681SAndroid Build Coastguard Worker else
215*9880d681SAndroid Build Coastguard Worker StackAlign = TFI.getTransientStackAlignment();
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker // If the frame pointer is eliminated, all frame offsets will be relative to
218*9880d681SAndroid Build Coastguard Worker // SP not FP. Align to MaxAlign so this works.
219*9880d681SAndroid Build Coastguard Worker StackAlign = std::max(StackAlign, MaxAlign);
220*9880d681SAndroid Build Coastguard Worker unsigned AlignMask = StackAlign - 1;
221*9880d681SAndroid Build Coastguard Worker Offset = (Offset + AlignMask) & ~uint64_t(AlignMask);
222*9880d681SAndroid Build Coastguard Worker }
223*9880d681SAndroid Build Coastguard Worker
224*9880d681SAndroid Build Coastguard Worker // Update frame info to pretend that this is part of the stack...
225*9880d681SAndroid Build Coastguard Worker int64_t StackSize = Offset - LocalAreaOffset;
226*9880d681SAndroid Build Coastguard Worker MFI->setStackSize(StackSize);
227*9880d681SAndroid Build Coastguard Worker }
228