xref: /aosp_15_r20/external/llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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