LLVM 20.0.0git
NVPTXPrologEpilogPass.cpp
Go to the documentation of this file.
1//===-- NVPTXPrologEpilogPass.cpp - NVPTX prolog/epilog inserter ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a copy of the generic LLVM PrologEpilogInserter pass, modified
10// to remove unneeded functionality and to handle virtual registers. Most code
11// here is a copy of PrologEpilogInserter.cpp.
12//
13//===----------------------------------------------------------------------===//
14
15#include "NVPTX.h"
23#include "llvm/Pass.h"
24#include "llvm/Support/Debug.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "nvptx-prolog-epilog"
30
31namespace {
32class NVPTXPrologEpilogPass : public MachineFunctionPass {
33public:
34 static char ID;
35 NVPTXPrologEpilogPass() : MachineFunctionPass(ID) {}
36
37 bool runOnMachineFunction(MachineFunction &MF) override;
38
39 StringRef getPassName() const override { return "NVPTX Prolog Epilog Pass"; }
40
41private:
42 void calculateFrameObjectOffsets(MachineFunction &Fn);
43};
44}
45
47 return new NVPTXPrologEpilogPass();
48}
49
50char NVPTXPrologEpilogPass::ID = 0;
51
52bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) {
53 const TargetSubtargetInfo &STI = MF.getSubtarget();
54 const TargetFrameLowering &TFI = *STI.getFrameLowering();
56 bool Modified = false;
57
58 calculateFrameObjectOffsets(MF);
59
60 for (MachineBasicBlock &MBB : MF) {
61 for (MachineInstr &MI : MBB) {
62 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
63 if (!MI.getOperand(i).isFI())
64 continue;
65
66 // Frame indices in debug values are encoded in a target independent
67 // way with simply the frame index and offset rather than any
68 // target-specific addressing mode.
69 if (MI.isDebugValue()) {
70 MachineOperand &Op = MI.getOperand(i);
71 assert(
72 MI.isDebugOperand(&Op) &&
73 "Frame indices can only appear as a debug operand in a DBG_VALUE*"
74 " machine instruction");
75 Register Reg;
76 auto Offset =
77 TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);
78 Op.ChangeToRegister(Reg, /*isDef=*/false);
79 const DIExpression *DIExpr = MI.getDebugExpression();
80 if (MI.isNonListDebugValue()) {
81 DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
82 } else {
84 TRI.getOffsetOpcodes(Offset, Ops);
85 unsigned OpIdx = MI.getDebugOperandIndex(&Op);
86 DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, OpIdx);
87 }
88 MI.getDebugExpressionOp().setMetadata(DIExpr);
89 continue;
90 }
91
92 TRI.eliminateFrameIndex(MI, 0, i, nullptr);
93 Modified = true;
94 }
95 }
96 }
97
98 // Add function prolog/epilog
99 TFI.emitPrologue(MF, MF.front());
100
101 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
102 // If last instruction is a return instruction, add an epilogue
103 if (I->isReturnBlock())
104 TFI.emitEpilogue(MF, *I);
105 }
106
107 return Modified;
108}
109
110/// AdjustStackOffset - Helper function used to adjust the stack frame offset.
111static inline void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx,
112 bool StackGrowsDown, int64_t &Offset,
113 Align &MaxAlign) {
114 // If the stack grows down, add the object size to find the lowest address.
115 if (StackGrowsDown)
116 Offset += MFI.getObjectSize(FrameIdx);
117
118 Align Alignment = MFI.getObjectAlign(FrameIdx);
119
120 // If the alignment of this object is greater than that of the stack, then
121 // increase the stack alignment to match.
122 MaxAlign = std::max(MaxAlign, Alignment);
123
124 // Adjust to alignment boundary.
125 Offset = alignTo(Offset, Alignment);
126
127 if (StackGrowsDown) {
128 LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset
129 << "]\n");
130 MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset
131 } else {
132 LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset
133 << "]\n");
134 MFI.setObjectOffset(FrameIdx, Offset);
135 Offset += MFI.getObjectSize(FrameIdx);
136 }
137}
138
139void
140NVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
143
144 bool StackGrowsDown =
146
147 // Loop over all of the stack objects, assigning sequential addresses...
148 MachineFrameInfo &MFI = Fn.getFrameInfo();
149
150 // Start at the beginning of the local area.
151 // The Offset is the distance from the stack top in the direction
152 // of stack growth -- so it's always nonnegative.
153 int LocalAreaOffset = TFI.getOffsetOfLocalArea();
154 if (StackGrowsDown)
155 LocalAreaOffset = -LocalAreaOffset;
156 assert(LocalAreaOffset >= 0
157 && "Local area offset should be in direction of stack growth");
158 int64_t Offset = LocalAreaOffset;
159
160 // If there are fixed sized objects that are preallocated in the local area,
161 // non-fixed objects can't be allocated right at the start of local area.
162 // We currently don't support filling in holes in between fixed sized
163 // objects, so we adjust 'Offset' to point to the end of last fixed sized
164 // preallocated object.
165 for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) {
166 int64_t FixedOff;
167 if (StackGrowsDown) {
168 // The maximum distance from the stack pointer is at lower address of
169 // the object -- which is given by offset. For down growing stack
170 // the offset is negative, so we negate the offset to get the distance.
171 FixedOff = -MFI.getObjectOffset(i);
172 } else {
173 // The maximum distance from the start pointer is at the upper
174 // address of the object.
175 FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i);
176 }
177 if (FixedOff > Offset) Offset = FixedOff;
178 }
179
180 // NOTE: We do not have a call stack
181
182 Align MaxAlign = MFI.getMaxAlign();
183
184 // No scavenger
185
186 // FIXME: Once this is working, then enable flag will change to a target
187 // check for whether the frame is large enough to want to use virtual
188 // frame index registers. Functions which don't want/need this optimization
189 // will continue to use the existing code path.
191 Align Alignment = MFI.getLocalFrameMaxAlign();
192
193 // Adjust to alignment boundary.
194 Offset = alignTo(Offset, Alignment);
195
196 LLVM_DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
197
198 // Resolve offsets for objects in the local block.
199 for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) {
200 std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i);
201 int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;
202 LLVM_DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << FIOffset
203 << "]\n");
204 MFI.setObjectOffset(Entry.first, FIOffset);
205 }
206 // Allocate the local block
207 Offset += MFI.getLocalFrameSize();
208
209 MaxAlign = std::max(Alignment, MaxAlign);
210 }
211
212 // No stack protector
213
214 // Then assign frame offsets to stack objects that are not used to spill
215 // callee saved registers.
216 for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
217 if (MFI.isObjectPreAllocated(i) &&
219 continue;
220 if (MFI.isDeadObjectIndex(i))
221 continue;
222
223 AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
224 }
225
226 // No scavenger
227
229 // If we have reserved argument space for call sites in the function
230 // immediately on entry to the current function, count it as part of the
231 // overall stack size.
232 if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn))
234
235 // Round up the size to a multiple of the alignment. If the function has
236 // any calls or alloca's, align to the target's StackAlignment value to
237 // ensure that the callee's frame or the alloca data is suitably aligned;
238 // otherwise, for leaf functions, align to the TransientStackAlignment
239 // value.
240 Align StackAlign;
241 if (MFI.adjustsStack() || MFI.hasVarSizedObjects() ||
242 (RegInfo->hasStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0))
243 StackAlign = TFI.getStackAlign();
244 else
245 StackAlign = TFI.getTransientStackAlign();
246
247 // If the frame pointer is eliminated, all frame offsets will be relative to
248 // SP not FP. Align to MaxAlign so this works.
249 Offset = alignTo(Offset, std::max(StackAlign, MaxAlign));
250 }
251
252 // Update frame info to pretend that this is part of the stack...
253 int64_t StackSize = Offset - LocalAreaOffset;
254 MFI.setStackSize(StackSize);
255}
MachineBasicBlock & MBB
#define LLVM_DEBUG(...)
Definition: Debug.h:106
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
static void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, bool StackGrowsDown, int64_t &Offset, Align &MaxAlign)
AdjustStackOffset - Helper function used to adjust the stack frame offset.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
DWARF expression.
static DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
This class represents an Operation in the Expression.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
int64_t getLocalFrameObjectCount() const
Return the number of objects allocated into the local object block.
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
Align getLocalFrameMaxAlign() const
Return the required alignment of the local object blob.
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
std::pair< int, int64_t > getLocalFrameObjectMap(int i) const
Get the local offset mapping for a for an object.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
bool getUseLocalStackAllocationBlock() const
Get whether the local allocation blob should be allocated together or let PEI allocate the locals in ...
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
int64_t getLocalFrameSize() const
Get the size of the local object blob.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
void setStackSize(uint64_t Size)
Set the size of the stack.
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineOperand class - Representation of each machine instruction operand.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Information about stack frame layout on the target.
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
virtual bool hasReservedCallFrame(const MachineFunction &MF) const
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
Align getTransientStackAlign() const
getTransientStackAlignment - This method returns the number of bytes to which the stack pointer must ...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
virtual bool targetHandlesStackFrameRounding() const
targetHandlesStackFrameRounding - Returns true if the target is responsible for rounding up the stack...
virtual void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
@ Entry
Definition: COFF.h:844
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
MachineFunctionPass * createNVPTXPrologEpilogPass()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39