LLVM  10.0.0svn
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  assert(i == 0 && "Frame indices can only appear as the first "
69  "operand of a DBG_VALUE machine instruction");
70  unsigned Reg;
71  int64_t Offset =
72  TFI.getFrameIndexReference(MF, MI.getOperand(0).getIndex(), Reg);
73  MI.getOperand(0).ChangeToRegister(Reg, /*isDef=*/false);
74  MI.getOperand(0).setIsDebug();
75  auto *DIExpr = DIExpression::prepend(
76  MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
77  MI.getOperand(3).setMetadata(DIExpr);
78  continue;
79  }
80 
81  TRI.eliminateFrameIndex(MI, 0, i, nullptr);
82  Modified = true;
83  }
84  }
85  }
86 
87  // Add function prolog/epilog
88  TFI.emitPrologue(MF, MF.front());
89 
90  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
91  // If last instruction is a return instruction, add an epilogue
92  if (I->isReturnBlock())
93  TFI.emitEpilogue(MF, *I);
94  }
95 
96  return Modified;
97 }
98 
99 /// AdjustStackOffset - Helper function used to adjust the stack frame offset.
100 static inline void
102  bool StackGrowsDown, int64_t &Offset,
103  unsigned &MaxAlign) {
104  // If the stack grows down, add the object size to find the lowest address.
105  if (StackGrowsDown)
106  Offset += MFI.getObjectSize(FrameIdx);
107 
108  unsigned Align = MFI.getObjectAlignment(FrameIdx);
109 
110  // If the alignment of this object is greater than that of the stack, then
111  // increase the stack alignment to match.
112  MaxAlign = std::max(MaxAlign, Align);
113 
114  // Adjust to alignment boundary.
115  Offset = (Offset + Align - 1) / Align * Align;
116 
117  if (StackGrowsDown) {
118  LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset
119  << "]\n");
120  MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset
121  } else {
122  LLVM_DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset
123  << "]\n");
124  MFI.setObjectOffset(FrameIdx, Offset);
125  Offset += MFI.getObjectSize(FrameIdx);
126  }
127 }
128 
129 void
130 NVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
132  const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo();
133 
134  bool StackGrowsDown =
136 
137  // Loop over all of the stack objects, assigning sequential addresses...
138  MachineFrameInfo &MFI = Fn.getFrameInfo();
139 
140  // Start at the beginning of the local area.
141  // The Offset is the distance from the stack top in the direction
142  // of stack growth -- so it's always nonnegative.
143  int LocalAreaOffset = TFI.getOffsetOfLocalArea();
144  if (StackGrowsDown)
145  LocalAreaOffset = -LocalAreaOffset;
146  assert(LocalAreaOffset >= 0
147  && "Local area offset should be in direction of stack growth");
148  int64_t Offset = LocalAreaOffset;
149 
150  // If there are fixed sized objects that are preallocated in the local area,
151  // non-fixed objects can't be allocated right at the start of local area.
152  // We currently don't support filling in holes in between fixed sized
153  // objects, so we adjust 'Offset' to point to the end of last fixed sized
154  // preallocated object.
155  for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) {
156  int64_t FixedOff;
157  if (StackGrowsDown) {
158  // The maximum distance from the stack pointer is at lower address of
159  // the object -- which is given by offset. For down growing stack
160  // the offset is negative, so we negate the offset to get the distance.
161  FixedOff = -MFI.getObjectOffset(i);
162  } else {
163  // The maximum distance from the start pointer is at the upper
164  // address of the object.
165  FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i);
166  }
167  if (FixedOff > Offset) Offset = FixedOff;
168  }
169 
170  // NOTE: We do not have a call stack
171 
172  unsigned MaxAlign = MFI.getMaxAlignment();
173 
174  // No scavenger
175 
176  // FIXME: Once this is working, then enable flag will change to a target
177  // check for whether the frame is large enough to want to use virtual
178  // frame index registers. Functions which don't want/need this optimization
179  // will continue to use the existing code path.
181  unsigned Align = MFI.getLocalFrameMaxAlign().value();
182 
183  // Adjust to alignment boundary.
184  Offset = (Offset + Align - 1) / Align * Align;
185 
186  LLVM_DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
187 
188  // Resolve offsets for objects in the local block.
189  for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) {
190  std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i);
191  int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;
192  LLVM_DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << FIOffset
193  << "]\n");
194  MFI.setObjectOffset(Entry.first, FIOffset);
195  }
196  // Allocate the local block
197  Offset += MFI.getLocalFrameSize();
198 
199  MaxAlign = std::max(Align, MaxAlign);
200  }
201 
202  // No stack protector
203 
204  // Then assign frame offsets to stack objects that are not used to spill
205  // callee saved registers.
206  for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
207  if (MFI.isObjectPreAllocated(i) &&
209  continue;
210  if (MFI.isDeadObjectIndex(i))
211  continue;
212 
213  AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
214  }
215 
216  // No scavenger
217 
218  if (!TFI.targetHandlesStackFrameRounding()) {
219  // If we have reserved argument space for call sites in the function
220  // immediately on entry to the current function, count it as part of the
221  // overall stack size.
222  if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn))
223  Offset += MFI.getMaxCallFrameSize();
224 
225  // Round up the size to a multiple of the alignment. If the function has
226  // any calls or alloca's, align to the target's StackAlignment value to
227  // ensure that the callee's frame or the alloca data is suitably aligned;
228  // otherwise, for leaf functions, align to the TransientStackAlignment
229  // value.
230  unsigned StackAlign;
231  if (MFI.adjustsStack() || MFI.hasVarSizedObjects() ||
232  (RegInfo->needsStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0))
233  StackAlign = TFI.getStackAlignment();
234  else
235  StackAlign = TFI.getTransientStackAlignment();
236 
237  // If the frame pointer is eliminated, all frame offsets will be relative to
238  // SP not FP. Align to MaxAlign so this works.
239  StackAlign = std::max(StackAlign, MaxAlign);
240  unsigned AlignMask = StackAlign - 1;
241  Offset = (Offset + AlignMask) & ~uint64_t(AlignMask);
242  }
243 
244  // Update frame info to pretend that this is part of the stack...
245  int64_t StackSize = Offset - LocalAreaOffset;
246  MFI.setStackSize(StackSize);
247 }
This class represents lattice values for constants.
Definition: AllocatorList.h:23
virtual int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
int64_t getLocalFrameSize() const
Get the size of the local object blob.
unsigned Reg
MachineFunctionPass * createNVPTXPrologEpilogPass()
unsigned const TargetRegisterInfo * TRI
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
static DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
std::pair< int, int64_t > getLocalFrameObjectMap(int i) const
Get the local offset mapping for a for an object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
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 getUseLocalStackAllocationBlock() const
Get whether the local allocation blob should be allocated together or let PEI allocate the locals in ...
static void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, bool StackGrowsDown, int64_t &Offset, unsigned &MaxAlign)
AdjustStackOffset - Helper function used to adjust the stack frame offset.
virtual bool targetHandlesStackFrameRounding() const
targetHandlesStackFrameRounding - Returns true if the target is responsible for rounding up the stack...
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
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...
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:86
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
virtual void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
unsigned getObjectAlignment(int ObjectIdx) const
Return the alignment of the specified stack object.
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void setStackSize(uint64_t Size)
Set the size of the stack.
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
unsigned getMaxAlignment() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
constexpr double e
Definition: MathExtras.h:57
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
virtual bool hasReservedCallFrame(const MachineFunction &MF) const
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required, we reserve argument space for call sites in the function immediately on entry to the current function.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:40
Iterator for intrusive lists based on ilist_node.
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:390
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call...
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
Information about stack frame layout on the target.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
unsigned getTransientStackAlignment() const
getTransientStackAlignment - This method returns the number of bytes to which the stack pointer must ...
TargetSubtargetInfo - Generic base class for all target subtargets.
Representation of each machine instruction.
Definition: MachineInstr.h:63
#define I(x, y, z)
Definition: MD5.cpp:58
virtual const TargetFrameLowering * getFrameLowering() const
Align getLocalFrameMaxAlign() const
Return the required alignment of the local object blob.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool needsStackRealignment(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
IRTranslator LLVM IR MI
#define LLVM_DEBUG(X)
Definition: Debug.h:122
int64_t getLocalFrameObjectCount() const
Return the number of objects allocated into the local object block.