LLVM  4.0.0
NVPTXPrologEpilogPass.cpp
Go to the documentation of this file.
1 //===-- NVPTXPrologEpilogPass.cpp - NVPTX prolog/epilog inserter ----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a copy of the generic LLVM PrologEpilogInserter pass, modified
11 // to remove unneeded functionality and to handle virtual registers. Most code
12 // here is a copy of PrologEpilogInserter.cpp.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "NVPTX.h"
20 #include "llvm/Pass.h"
21 #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  TRI.eliminateFrameIndex(MI, 0, i, nullptr);
64  Modified = true;
65  }
66  }
67  }
68 
69  // Add function prolog/epilog
70  TFI.emitPrologue(MF, MF.front());
71 
72  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
73  // If last instruction is a return instruction, add an epilogue
74  if (I->isReturnBlock())
75  TFI.emitEpilogue(MF, *I);
76  }
77 
78  return Modified;
79 }
80 
81 /// AdjustStackOffset - Helper function used to adjust the stack frame offset.
82 static inline void
84  bool StackGrowsDown, int64_t &Offset,
85  unsigned &MaxAlign) {
86  // If the stack grows down, add the object size to find the lowest address.
87  if (StackGrowsDown)
88  Offset += MFI.getObjectSize(FrameIdx);
89 
90  unsigned Align = MFI.getObjectAlignment(FrameIdx);
91 
92  // If the alignment of this object is greater than that of the stack, then
93  // increase the stack alignment to match.
94  MaxAlign = std::max(MaxAlign, Align);
95 
96  // Adjust to alignment boundary.
97  Offset = (Offset + Align - 1) / Align * Align;
98 
99  if (StackGrowsDown) {
100  DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n");
101  MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset
102  } else {
103  DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset << "]\n");
104  MFI.setObjectOffset(FrameIdx, Offset);
105  Offset += MFI.getObjectSize(FrameIdx);
106  }
107 }
108 
109 void
110 NVPTXPrologEpilogPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
112  const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo();
113 
114  bool StackGrowsDown =
116 
117  // Loop over all of the stack objects, assigning sequential addresses...
118  MachineFrameInfo &MFI = Fn.getFrameInfo();
119 
120  // Start at the beginning of the local area.
121  // The Offset is the distance from the stack top in the direction
122  // of stack growth -- so it's always nonnegative.
123  int LocalAreaOffset = TFI.getOffsetOfLocalArea();
124  if (StackGrowsDown)
125  LocalAreaOffset = -LocalAreaOffset;
126  assert(LocalAreaOffset >= 0
127  && "Local area offset should be in direction of stack growth");
128  int64_t Offset = LocalAreaOffset;
129 
130  // If there are fixed sized objects that are preallocated in the local area,
131  // non-fixed objects can't be allocated right at the start of local area.
132  // We currently don't support filling in holes in between fixed sized
133  // objects, so we adjust 'Offset' to point to the end of last fixed sized
134  // preallocated object.
135  for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) {
136  int64_t FixedOff;
137  if (StackGrowsDown) {
138  // The maximum distance from the stack pointer is at lower address of
139  // the object -- which is given by offset. For down growing stack
140  // the offset is negative, so we negate the offset to get the distance.
141  FixedOff = -MFI.getObjectOffset(i);
142  } else {
143  // The maximum distance from the start pointer is at the upper
144  // address of the object.
145  FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i);
146  }
147  if (FixedOff > Offset) Offset = FixedOff;
148  }
149 
150  // NOTE: We do not have a call stack
151 
152  unsigned MaxAlign = MFI.getMaxAlignment();
153 
154  // No scavenger
155 
156  // FIXME: Once this is working, then enable flag will change to a target
157  // check for whether the frame is large enough to want to use virtual
158  // frame index registers. Functions which don't want/need this optimization
159  // will continue to use the existing code path.
161  unsigned Align = MFI.getLocalFrameMaxAlign();
162 
163  // Adjust to alignment boundary.
164  Offset = (Offset + Align - 1) / Align * Align;
165 
166  DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
167 
168  // Resolve offsets for objects in the local block.
169  for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) {
170  std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i);
171  int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;
172  DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" <<
173  FIOffset << "]\n");
174  MFI.setObjectOffset(Entry.first, FIOffset);
175  }
176  // Allocate the local block
177  Offset += MFI.getLocalFrameSize();
178 
179  MaxAlign = std::max(Align, MaxAlign);
180  }
181 
182  // No stack protector
183 
184  // Then assign frame offsets to stack objects that are not used to spill
185  // callee saved registers.
186  for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
187  if (MFI.isObjectPreAllocated(i) &&
189  continue;
190  if (MFI.isDeadObjectIndex(i))
191  continue;
192 
193  AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
194  }
195 
196  // No scavenger
197 
198  if (!TFI.targetHandlesStackFrameRounding()) {
199  // If we have reserved argument space for call sites in the function
200  // immediately on entry to the current function, count it as part of the
201  // overall stack size.
202  if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn))
203  Offset += MFI.getMaxCallFrameSize();
204 
205  // Round up the size to a multiple of the alignment. If the function has
206  // any calls or alloca's, align to the target's StackAlignment value to
207  // ensure that the callee's frame or the alloca data is suitably aligned;
208  // otherwise, for leaf functions, align to the TransientStackAlignment
209  // value.
210  unsigned StackAlign;
211  if (MFI.adjustsStack() || MFI.hasVarSizedObjects() ||
212  (RegInfo->needsStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0))
213  StackAlign = TFI.getStackAlignment();
214  else
215  StackAlign = TFI.getTransientStackAlignment();
216 
217  // If the frame pointer is eliminated, all frame offsets will be relative to
218  // SP not FP. Align to MaxAlign so this works.
219  StackAlign = std::max(StackAlign, MaxAlign);
220  unsigned AlignMask = StackAlign - 1;
221  Offset = (Offset + AlignMask) & ~uint64_t(AlignMask);
222  }
223 
224  // Update frame info to pretend that this is part of the stack...
225  int64_t StackSize = Offset - LocalAreaOffset;
226  MFI.setStackSize(StackSize);
227 }
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
size_t i
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
MachineFunctionPass * createNVPTXPrologEpilogPass()
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
unsigned getMaxAlignment() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
virtual bool targetHandlesStackFrameRounding() const
targetHandlesStackFrameRounding - Returns true if the target is responsible for rounding up the stack...
int64_t getLocalFrameSize() const
Get the size of the local object blob.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
int getObjectIndexBegin() const
Return the minimum frame object index.
static void AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, bool StackGrowsDown, int64_t &Offset, unsigned &MaxAlign)
AdjustStackOffset - Helper function used to adjust the stack frame offset.
MachineBasicBlock * MBB
unsigned getLocalFrameMaxAlign() const
Return the required alignment of the local object blob.
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...
unsigned getTransientStackAlignment() const
getTransientStackAlignment - This method returns the number of bytes to which the stack pointer must ...
int64_t getLocalFrameObjectCount() const
Return the number of objects allocated into the local object block.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
std::pair< int, int64_t > getLocalFrameObjectMap(int i) const
Get the local offset mapping for a for an object.
virtual void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
bool getUseLocalStackAllocationBlock() const
Get whether the local allocation blob should be allocated together or let PEI allocate the locals in ...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void setStackSize(uint64_t Size)
Set the size of the stack.
uint32_t Offset
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
virtual const TargetFrameLowering * getFrameLowering() const
Iterator for intrusive lists based on ilist_node.
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const =0
unsigned getObjectAlignment(int ObjectIdx) const
Return the alignment of the specified stack object.
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call...
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
TargetSubtargetInfo - Generic base class for all target subtargets.
Representation of each machine instruction.
Definition: MachineInstr.h:52
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
#define I(x, y, z)
Definition: MD5.cpp:54
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define DEBUG(X)
Definition: Debug.h:100
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
IRTranslator LLVM IR MI
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
bool needsStackRealignment(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
int getObjectIndexEnd() const
Return one past the maximum frame object index.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.