LLVM  13.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 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "nvptx-prolog-epilog"
30 
31 namespace {
32 class NVPTXPrologEpilogPass : public MachineFunctionPass {
33 public:
34  static char ID;
35  NVPTXPrologEpilogPass() : MachineFunctionPass(ID) {}
36 
37  bool runOnMachineFunction(MachineFunction &MF) override;
38 
39 private:
40  void calculateFrameObjectOffsets(MachineFunction &Fn);
41 };
42 }
43 
45  return new NVPTXPrologEpilogPass();
46 }
47 
49 
50 bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) {
51  const TargetSubtargetInfo &STI = MF.getSubtarget();
52  const TargetFrameLowering &TFI = *STI.getFrameLowering();
53  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
54  bool Modified = false;
55 
56  calculateFrameObjectOffsets(MF);
57 
58  for (MachineBasicBlock &MBB : MF) {
59  for (MachineInstr &MI : MBB) {
60  for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
61  if (!MI.getOperand(i).isFI())
62  continue;
63 
64  // Frame indices in debug values are encoded in a target independent
65  // way with simply the frame index and offset rather than any
66  // target-specific addressing mode.
67  if (MI.isDebugValue()) {
68  MachineOperand &Op = MI.getOperand(i);
69  assert(
70  MI.isDebugOperand(&Op) &&
71  "Frame indices can only appear as a debug operand in a DBG_VALUE*"
72  " machine instruction");
73  Register Reg;
74  auto Offset =
75  TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);
76  Op.ChangeToRegister(Reg, /*isDef=*/false);
77  Op.setIsDebug();
78  const DIExpression *DIExpr = MI.getDebugExpression();
79  if (MI.isNonListDebugValue()) {
80  DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
81  } else {
84  unsigned OpIdx = MI.getDebugOperandIndex(&Op);
85  DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, OpIdx);
86  }
87  MI.getDebugExpressionOp().setMetadata(DIExpr);
88  continue;
89  }
90 
91  TRI.eliminateFrameIndex(MI, 0, i, nullptr);
92  Modified = true;
93  }
94  }
95  }
96 
97  // Add function prolog/epilog
98  TFI.emitPrologue(MF, MF.front());
99 
100  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
101  // If last instruction is a return instruction, add an epilogue
102  if (I->isReturnBlock())
103  TFI.emitEpilogue(MF, *I);
104  }
105 
106  return Modified;
107 }
108 
109 /// AdjustStackOffset - Helper function used to adjust the stack frame offset.
110 static inline void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx,
111  bool StackGrowsDown, int64_t &Offset,
112  Align &MaxAlign) {
113  // If the stack grows down, add the object size to find the lowest address.
114  if (StackGrowsDown)
115  Offset += MFI.getObjectSize(FrameIdx);
116 
117  Align Alignment = MFI.getObjectAlign(FrameIdx);
118 
119  // If the alignment of this object is greater than that of the stack, then
120  // increase the stack alignment to match.
121  MaxAlign = std::max(MaxAlign, Alignment);
122 
123  // Adjust to alignment boundary.
124  Offset = alignTo(Offset, Alignment);
125 
126  if (StackGrowsDown) {
127  LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset
128  << "]\n");
129  MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset
130  } else {
131  LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset
132  << "]\n");
133  MFI.setObjectOffset(FrameIdx, Offset);
134  Offset += MFI.getObjectSize(FrameIdx);
135  }
136 }
137 
138 void
139 NVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
141  const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo();
142 
143  bool StackGrowsDown =
145 
146  // Loop over all of the stack objects, assigning sequential addresses...
147  MachineFrameInfo &MFI = Fn.getFrameInfo();
148 
149  // Start at the beginning of the local area.
150  // The Offset is the distance from the stack top in the direction
151  // of stack growth -- so it's always nonnegative.
152  int LocalAreaOffset = TFI.getOffsetOfLocalArea();
153  if (StackGrowsDown)
154  LocalAreaOffset = -LocalAreaOffset;
155  assert(LocalAreaOffset >= 0
156  && "Local area offset should be in direction of stack growth");
157  int64_t Offset = LocalAreaOffset;
158 
159  // If there are fixed sized objects that are preallocated in the local area,
160  // non-fixed objects can't be allocated right at the start of local area.
161  // We currently don't support filling in holes in between fixed sized
162  // objects, so we adjust 'Offset' to point to the end of last fixed sized
163  // preallocated object.
164  for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) {
165  int64_t FixedOff;
166  if (StackGrowsDown) {
167  // The maximum distance from the stack pointer is at lower address of
168  // the object -- which is given by offset. For down growing stack
169  // the offset is negative, so we negate the offset to get the distance.
170  FixedOff = -MFI.getObjectOffset(i);
171  } else {
172  // The maximum distance from the start pointer is at the upper
173  // address of the object.
174  FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i);
175  }
176  if (FixedOff > Offset) Offset = FixedOff;
177  }
178 
179  // NOTE: We do not have a call stack
180 
181  Align MaxAlign = MFI.getMaxAlign();
182 
183  // No scavenger
184 
185  // FIXME: Once this is working, then enable flag will change to a target
186  // check for whether the frame is large enough to want to use virtual
187  // frame index registers. Functions which don't want/need this optimization
188  // will continue to use the existing code path.
190  Align Alignment = MFI.getLocalFrameMaxAlign();
191 
192  // Adjust to alignment boundary.
193  Offset = alignTo(Offset, Alignment);
194 
195  LLVM_DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
196 
197  // Resolve offsets for objects in the local block.
198  for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) {
199  std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i);
200  int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;
201  LLVM_DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << FIOffset
202  << "]\n");
203  MFI.setObjectOffset(Entry.first, FIOffset);
204  }
205  // Allocate the local block
206  Offset += MFI.getLocalFrameSize();
207 
208  MaxAlign = std::max(Alignment, MaxAlign);
209  }
210 
211  // No stack protector
212 
213  // Then assign frame offsets to stack objects that are not used to spill
214  // callee saved registers.
215  for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
216  if (MFI.isObjectPreAllocated(i) &&
218  continue;
219  if (MFI.isDeadObjectIndex(i))
220  continue;
221 
222  AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
223  }
224 
225  // No scavenger
226 
227  if (!TFI.targetHandlesStackFrameRounding()) {
228  // If we have reserved argument space for call sites in the function
229  // immediately on entry to the current function, count it as part of the
230  // overall stack size.
231  if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn))
232  Offset += MFI.getMaxCallFrameSize();
233 
234  // Round up the size to a multiple of the alignment. If the function has
235  // any calls or alloca's, align to the target's StackAlignment value to
236  // ensure that the callee's frame or the alloca data is suitably aligned;
237  // otherwise, for leaf functions, align to the TransientStackAlignment
238  // value.
240  if (MFI.adjustsStack() || MFI.hasVarSizedObjects() ||
241  (RegInfo->hasStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0))
242  StackAlign = TFI.getStackAlign();
243  else
245 
246  // If the frame pointer is eliminated, all frame offsets will be relative to
247  // SP not FP. Align to MaxAlign so this works.
248  Offset = alignTo(Offset, std::max(StackAlign, MaxAlign));
249  }
250 
251  // Update frame info to pretend that this is part of the stack...
252  int64_t StackSize = Offset - LocalAreaOffset;
253  MFI.setStackSize(StackSize);
254 }
i
i
Definition: README.txt:29
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:148
llvm::MachineFrameInfo::hasVarSizedObjects
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
Definition: MachineFrameInfo.h:351
llvm::RISCVAttrs::StackAlign
StackAlign
Definition: RISCVAttributes.h:37
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:102
llvm
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
TargetFrameLowering.h
llvm::TargetFrameLowering
Information about stack frame layout on the target.
Definition: TargetFrameLowering.h:43
DebugInfoMetadata.h
Pass.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1167
llvm::MachineFrameInfo::getUseLocalStackAllocationBlock
bool getUseLocalStackAllocationBlock() const
Get whether the local allocation blob should be allocated together or let PEI allocate the locals in ...
Definition: MachineFrameInfo.h:432
llvm::TargetRegisterInfo::getOffsetOpcodes
virtual void getOffsetOpcodes(const StackOffset &Offset, SmallVectorImpl< uint64_t > &Ops) const
Gets the DWARF expression opcodes for Offset.
Definition: TargetRegisterInfo.cpp:642
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::TargetSubtargetInfo::getRegisterInfo
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
Definition: TargetSubtargetInfo.h:124
llvm::TargetRegisterInfo
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Definition: TargetRegisterInfo.h:231
llvm::MachineFrameInfo::setStackSize
void setStackSize(uint64_t Size)
Set the size of the stack.
Definition: MachineFrameInfo.h:554
llvm::MachineFrameInfo::isObjectPreAllocated
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
Definition: MachineFrameInfo.h:444
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::DIExpression
DWARF expression.
Definition: DebugInfoMetadata.h:2554
llvm::MachineFrameInfo::getObjectIndexEnd
int getObjectIndexEnd() const
Return one past the maximum frame object index.
Definition: MachineFrameInfo.h:391
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1567
llvm::MachineFrameInfo::getMaxCallFrameSize
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
Definition: MachineFrameInfo.h:620
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
NVPTX.h
llvm::TargetFrameLowering::getTransientStackAlign
Align getTransientStackAlign() const
getTransientStackAlignment - This method returns the number of bytes to which the stack pointer must ...
Definition: TargetFrameLowering.h:118
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
llvm::DIExpression::appendOpsToArg
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...
Definition: DebugInfoMetadata.cpp:1301
llvm::TargetFrameLowering::getOffsetOfLocalArea
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
Definition: TargetFrameLowering.h:140
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::DIExpression::ApplyOffset
@ ApplyOffset
Definition: DebugInfoMetadata.h:2761
llvm::TargetFrameLowering::getStackAlign
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
Definition: TargetFrameLowering.h:100
llvm::TargetFrameLowering::hasReservedCallFrame
virtual bool hasReservedCallFrame(const MachineFunction &MF) const
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
Definition: TargetFrameLowering.h:274
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::createNVPTXPrologEpilogPass
MachineFunctionPass * createNVPTXPrologEpilogPass()
Definition: NVPTXPrologEpilogPass.cpp:44
LoopDeletionResult::Modified
@ Modified
llvm::MachineFrameInfo::getLocalFrameMaxAlign
Align getLocalFrameMaxAlign() const
Return the required alignment of the local object blob.
Definition: MachineFrameInfo.h:428
llvm::MachineFrameInfo::getObjectOffset
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
Definition: MachineFrameInfo.h:492
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::MachineFrameInfo::getObjectIndexBegin
int getObjectIndexBegin() const
Return the minimum frame object index.
Definition: MachineFrameInfo.h:388
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
llvm::MachineFrameInfo::isDeadObjectIndex
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
Definition: MachineFrameInfo.h:711
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:576
llvm::MachineFrameInfo::getLocalFrameObjectMap
std::pair< int, int64_t > getLocalFrameObjectMap(int i) const
Get the local offset mapping for a for an object.
Definition: MachineFrameInfo.h:406
llvm::MachineFrameInfo::getLocalFrameSize
int64_t getLocalFrameSize() const
Get the size of the local object blob.
Definition: MachineFrameInfo.h:419
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::MachineFrameInfo::getObjectSize
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
Definition: MachineFrameInfo.h:451
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::MachineFrameInfo::getObjectAlign
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
Definition: MachineFrameInfo.h:465
llvm::TargetRegisterInfo::eliminateFrameIndex
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const =0
This method must be overriden to eliminate abstract frame indices from instructions which may use the...
llvm::MachineFrameInfo::setObjectOffset
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
Definition: MachineFrameInfo.h:526
MachineFunctionPass.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineFunction::getFrameInfo
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Definition: MachineFunction.h:592
llvm::TargetFrameLowering::getStackGrowthDirection
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
Definition: TargetFrameLowering.h:89
llvm::MachineFunction
Definition: MachineFunction.h:230
TargetSubtargetInfo.h
llvm::TargetSubtargetInfo
TargetSubtargetInfo - Generic base class for all target subtargets.
Definition: TargetSubtargetInfo.h:59
AdjustStackOffset
static void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, bool StackGrowsDown, int64_t &Offset, Align &MaxAlign)
AdjustStackOffset - Helper function used to adjust the stack frame offset.
Definition: NVPTXPrologEpilogPass.cpp:110
llvm::MachineFrameInfo::getLocalFrameObjectCount
int64_t getLocalFrameObjectCount() const
Return the number of objects allocated into the local object block.
Definition: MachineFrameInfo.h:413
llvm::MachineFrameInfo::getMaxAlign
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
Definition: MachineFrameInfo.h:567
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::TargetSubtargetInfo::getFrameLowering
virtual const TargetFrameLowering * getFrameLowering() const
Definition: TargetSubtargetInfo.h:93
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:314
llvm::ilist_iterator
Iterator for intrusive lists based on ilist_node.
Definition: ilist_iterator.h:57
MachineFrameInfo.h
llvm::TargetFrameLowering::getFrameIndexReference
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...
Definition: TargetFrameLoweringImpl.cpp:45
llvm::TargetFrameLowering::targetHandlesStackFrameRounding
virtual bool targetHandlesStackFrameRounding() const
targetHandlesStackFrameRounding - Returns true if the target is responsible for rounding up the stack...
Definition: TargetFrameLowering.h:186
llvm::TargetRegisterInfo::hasStackRealignment
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
Definition: TargetRegisterInfo.h:934
llvm::MachineFrameInfo
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Definition: MachineFrameInfo.h:107
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::TargetFrameLowering::StackGrowsDown
@ StackGrowsDown
Definition: TargetFrameLowering.h:47
llvm::TargetFrameLowering::emitPrologue
virtual void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
llvm::MachineFrameInfo::adjustsStack
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
Definition: MachineFrameInfo.h:575
raw_ostream.h
MachineFunction.h
llvm::TargetFrameLowering::emitEpilogue
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
TargetRegisterInfo.h
Debug.h
llvm::TargetRegisterInfo::prependOffsetExpression
DIExpression * prependOffsetExpression(const DIExpression *Expr, unsigned PrependFlags, const StackOffset &Offset) const
Prepends a DWARF expression for Offset to DIExpression Expr.
Definition: TargetRegisterInfo.cpp:649
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38