LLVM 24.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 NVPTXPrologEpilog {
33public:
34 bool run(MachineFunction &MF);
35
36private:
37 void calculateFrameObjectOffsets(MachineFunction &Fn);
38};
39} // end anonymous namespace
40
42 unsigned OpIdx) {
45 if (MI.isDebugValue()) {
46
47 MachineOperand &Op = MI.getOperand(OpIdx);
48 assert(MI.isDebugOperand(&Op) &&
49 "Frame indices can only appear as a debug operand in a DBG_VALUE*"
50 " machine instruction");
52 unsigned FrameIdx = Op.getIndex();
53
54 StackOffset Offset = TFI->getFrameIndexReference(MF, FrameIdx, Reg);
55 Op.ChangeToRegister(Reg, false /*isDef*/);
56
57 const DIExpression *DIExpr = MI.getDebugExpression();
58 if (MI.isNonListDebugValue()) {
59 DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(),
61 } else {
62 // The debug operand at DebugOpIndex was a frame index at offset
63 // `Offset`; now the operand has been replaced with the frame
64 // register, we must add Offset with `register x, plus Offset`.
65 unsigned DebugOpIndex = MI.getDebugOperandIndex(&Op);
67 TRI.getOffsetOpcodes(Offset, Ops);
68 DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, DebugOpIndex);
69 }
70 MI.getDebugExpressionOp().setMetadata(DIExpr);
71 return true;
72 }
73 return false;
74}
75
76bool NVPTXPrologEpilog::run(MachineFunction &MF) {
77 const TargetSubtargetInfo &STI = MF.getSubtarget();
78 const TargetFrameLowering &TFI = *STI.getFrameLowering();
79 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
80 bool Modified = false;
81
82 calculateFrameObjectOffsets(MF);
83
84 for (MachineBasicBlock &BB : MF) {
85 for (MachineBasicBlock::iterator I = BB.end(); I != BB.begin();) {
86 MachineInstr &MI = *std::prev(I);
87
88 bool RemovedMI = false;
89 for (const auto &[Idx, Op] : enumerate(MI.operands())) {
90 if (!Op.isFI())
91 continue;
92
93 if (replaceFrameIndexDebugInstr(MF, MI, Idx))
94 continue;
95
96 // Eliminate this FrameIndex operand.
97 RemovedMI = TRI.eliminateFrameIndex(MI, 0, Idx, nullptr);
98 Modified = true;
99 if (RemovedMI)
100 break;
101 }
102
103 if (!RemovedMI)
104 --I;
105 }
106 }
107
108 // Add function prolog/epilog
109 TFI.emitPrologue(MF, MF.front());
110
111 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
112 // If last instruction is a return instruction, add an epilogue
113 if (I->isReturnBlock())
114 TFI.emitEpilogue(MF, *I);
115 }
116
117 return Modified;
118}
119
120/// AdjustStackOffset - Helper function used to adjust the stack frame offset.
121static inline void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx,
122 bool StackGrowsDown, int64_t &Offset,
123 Align &MaxAlign) {
124 // If the stack grows down, add the object size to find the lowest address.
125 if (StackGrowsDown)
126 Offset += MFI.getObjectSize(FrameIdx);
127
128 Align Alignment = MFI.getObjectAlign(FrameIdx);
129
130 // If the alignment of this object is greater than that of the stack, then
131 // increase the stack alignment to match.
132 MaxAlign = std::max(MaxAlign, Alignment);
133
134 // Adjust to alignment boundary.
135 Offset = alignTo(Offset, Alignment);
136
137 if (StackGrowsDown) {
138 LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset
139 << "]\n");
140 MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset
141 } else {
142 LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset
143 << "]\n");
144 MFI.setObjectOffset(FrameIdx, Offset);
145 Offset += MFI.getObjectSize(FrameIdx);
146 }
147}
148
149void NVPTXPrologEpilog::calculateFrameObjectOffsets(MachineFunction &Fn) {
150 const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering();
151 const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo();
152
153 bool StackGrowsDown =
155
156 // Loop over all of the stack objects, assigning sequential addresses...
157 MachineFrameInfo &MFI = Fn.getFrameInfo();
158
159 // Start at the beginning of the local area.
160 // The Offset is the distance from the stack top in the direction
161 // of stack growth -- so it's always nonnegative.
162 int LocalAreaOffset = TFI.getOffsetOfLocalArea();
163 if (StackGrowsDown)
164 LocalAreaOffset = -LocalAreaOffset;
165 assert(LocalAreaOffset >= 0
166 && "Local area offset should be in direction of stack growth");
167 int64_t Offset = LocalAreaOffset;
168
169 // If there are fixed sized objects that are preallocated in the local area,
170 // non-fixed objects can't be allocated right at the start of local area.
171 // We currently don't support filling in holes in between fixed sized
172 // objects, so we adjust 'Offset' to point to the end of last fixed sized
173 // preallocated object.
174 for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) {
175 int64_t FixedOff;
176 if (StackGrowsDown) {
177 // The maximum distance from the stack pointer is at lower address of
178 // the object -- which is given by offset. For down growing stack
179 // the offset is negative, so we negate the offset to get the distance.
180 FixedOff = -MFI.getObjectOffset(i);
181 } else {
182 // The maximum distance from the start pointer is at the upper
183 // address of the object.
184 FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i);
185 }
186 if (FixedOff > Offset) Offset = FixedOff;
187 }
188
189 // NOTE: We do not have a call stack
190
191 Align MaxAlign = MFI.getMaxAlign();
192
193 // No scavenger
194
195 // FIXME: Once this is working, then enable flag will change to a target
196 // check for whether the frame is large enough to want to use virtual
197 // frame index registers. Functions which don't want/need this optimization
198 // will continue to use the existing code path.
200 Align Alignment = MFI.getLocalFrameMaxAlign();
201
202 // Adjust to alignment boundary.
203 Offset = alignTo(Offset, Alignment);
204
205 LLVM_DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
206
207 // Resolve offsets for objects in the local block.
208 for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) {
209 std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i);
210 int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;
211 LLVM_DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << FIOffset
212 << "]\n");
213 MFI.setObjectOffset(Entry.first, FIOffset);
214 }
215 // Allocate the local block
216 Offset += MFI.getLocalFrameSize();
217
218 MaxAlign = std::max(Alignment, MaxAlign);
219 }
220
221 // No stack protector
222
223 // Then assign frame offsets to stack objects that are not used to spill
224 // callee saved registers.
225 for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
226 if (MFI.isObjectPreAllocated(i) &&
228 continue;
229 if (MFI.isDeadObjectIndex(i))
230 continue;
231
232 AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
233 }
234
235 // No scavenger
236
238 // If we have reserved argument space for call sites in the function
239 // immediately on entry to the current function, count it as part of the
240 // overall stack size.
241 if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn))
243
244 // Round up the size to a multiple of the alignment. If the function has
245 // any calls or alloca's, align to the target's StackAlignment value to
246 // ensure that the callee's frame or the alloca data is suitably aligned;
247 // otherwise, for leaf functions, align to the TransientStackAlignment
248 // value.
249 Align StackAlign;
250 if (MFI.adjustsStack() || MFI.hasVarSizedObjects() ||
251 (RegInfo->hasStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0))
252 StackAlign = TFI.getStackAlign();
253 else
254 StackAlign = TFI.getTransientStackAlign();
255
256 // If the frame pointer is eliminated, all frame offsets will be relative to
257 // SP not FP. Align to MaxAlign so this works.
258 Offset = alignTo(Offset, std::max(StackAlign, MaxAlign));
259 }
260
261 // Update frame info to pretend that this is part of the stack...
262 int64_t StackSize = Offset - LocalAreaOffset;
263 MFI.setStackSize(StackSize);
264}
265
266namespace {
267class NVPTXPrologEpilogLegacyPass : public MachineFunctionPass {
268public:
269 static char ID;
270 NVPTXPrologEpilogLegacyPass() : MachineFunctionPass(ID) {}
271
272 bool runOnMachineFunction(MachineFunction &MF) override {
273 return NVPTXPrologEpilog().run(MF);
274 }
275
276 StringRef getPassName() const override { return "NVPTX Prolog Epilog Pass"; }
277
278 void getAnalysisUsage(AnalysisUsage &AU) const override {
279 AU.setPreservesCFG();
281 }
282};
283} // end anonymous namespace
284
285char NVPTXPrologEpilogLegacyPass::ID = 0;
286
287INITIALIZE_PASS(NVPTXPrologEpilogLegacyPass, DEBUG_TYPE,
288 "NVPTX Prologue/Epilogue Insertion", false, false)
289
291 return new NVPTXPrologEpilogLegacyPass();
292}
293
294PreservedAnalyses
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
static bool replaceFrameIndexDebugInstr(MachineFunction &MF, MachineInstr &MI, unsigned OpIdx)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, bool StackGrowsDown, int64_t &Offset, Align &MaxAlign)
AdjustStackOffset - Helper function used to adjust the stack frame offset.
#define LLVM_DEBUG(...)
Definition Debug.h:119
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:275
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
DWARF expression.
static LLVM_ABI 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...
MachineInstrBundleIterator< MachineInstr > iterator
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...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
BasicBlockListType::iterator iterator
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
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...
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ Entry
Definition COFF.h:862
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
MachineFunctionPass * createNVPTXPrologEpilogLegacyPass()
DWARFExpression::Operation Op
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39