LLVM: lib/CodeGen/LocalStackSlotAllocation.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
36#include
37#include
38#include
39#include
40
41using namespace llvm;
42
43#define DEBUG_TYPE "localstackalloc"
44
45STATISTIC(NumAllocations, "Number of frame indices allocated into local block");
46STATISTIC(NumBaseRegisters, "Number of virtual frame base registers allocated");
47STATISTIC(NumReplacements, "Number of frame indices references replaced");
48
49namespace {
50
51 class FrameRef {
53 int64_t LocalOffset;
54 int FrameIdx;
55
56
57
58
59 unsigned Order;
60
61 public:
63 MI(I), LocalOffset(Offset), FrameIdx(Idx), Order(Ord) {}
64
65 bool operator<(const FrameRef &RHS) const {
66 return std::tie(LocalOffset, FrameIdx, Order) <
67 std::tie(RHS.LocalOffset, RHS.FrameIdx, RHS.Order);
68 }
69
71 int64_t getLocalOffset() const { return LocalOffset; }
72 int getFrameIndex() const { return FrameIdx; }
73 };
74
75 class LocalStackSlotImpl {
77
78
80
82 bool StackGrowsDown, Align &MaxAlign);
89
90 public:
92 };
93
95 public:
96 static char ID;
97
100 }
101
103 return LocalStackSlotImpl().runOnMachineFunction(MF);
104 }
105
109 }
110 };
111
112}
113
117 bool Changed = LocalStackSlotImpl().runOnMachineFunction(MF);
118 if (!Changed)
122 return PA;
123}
124
125char LocalStackSlotPass::ID = 0;
126
129 "Local Stack Slot Allocation", false, false)
130
135
136
137
138 if (LocalObjectCount == 0 || ->requiresVirtualBaseRegisters(MF))
139 return false;
140
141
143
144
145 calculateFrameObjectOffsets(MF);
146
147
148 bool UsedBaseRegs = insertFrameReferenceRegisters(MF);
149
150
151
152
153
154
156
157 return true;
158}
159
160
161void LocalStackSlotImpl::AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx,
162 int64_t &Offset, bool StackGrowsDown,
163 Align &MaxAlign) {
164
165 if (StackGrowsDown)
167
169
170
171
172 MaxAlign = std::max(MaxAlign, Alignment);
173
174
176
177 int64_t LocalOffset = StackGrowsDown ? -Offset : Offset;
178 LLVM_DEBUG(dbgs() << "Allocate FI(" << FrameIdx << ") to local offset "
179 << LocalOffset << "\n");
180
181 LocalOffsets[FrameIdx] = LocalOffset;
182
184
185 if (!StackGrowsDown)
187
188 ++NumAllocations;
189}
190
191
192
193void LocalStackSlotImpl::AssignProtectedObjSet(
196 Align &MaxAlign) {
197 for (int i : UnassignedObjs) {
199 ProtectedObjs.insert(i);
200 }
201}
202
203
204
205void LocalStackSlotImpl::calculateFrameObjectOffsets(MachineFunction &Fn) {
206
209 bool StackGrowsDown =
213
214
215
219
220
221
222
223
225 "Stack protector pre-allocated in LocalStackSlotAllocation");
226
230
231
232
235 MaxAlign);
236
237
240 continue;
241 if (StackProtectorFI == (int)i)
242 continue;
244 continue;
245
248 continue;
250 SmallArrayObjs.insert(i);
251 continue;
253 AddrOfObjs.insert(i);
254 continue;
256 LargeArrayObjs.insert(i);
257 continue;
258 }
260 }
261
268 }
269
270
271
274 continue;
276 continue;
277 if (ProtectedObjs.count(i))
278 continue;
280 continue;
281
283 }
284
285
288}
289
290static inline bool
292 int64_t BaseOffset,
293 int64_t FrameSizeAdjust,
294 int64_t LocalFrameOffset,
297
298
299 int64_t Offset = FrameSizeAdjust + LocalFrameOffset - BaseOffset;
300 return TRI->isFrameOffsetLegal(&MI, BaseReg, Offset);
301}
302
303bool LocalStackSlotImpl::insertFrameReferenceRegisters(MachineFunction &Fn) {
304
305
306
307
308
309
310
314 bool StackGrowsDown =
316
317
318
319
320
322
323 unsigned Order = 0;
324
327
328
329 if (MI.isDebugInstr() || MI.getOpcode() == TargetOpcode::STATEPOINT ||
330 MI.getOpcode() == TargetOpcode::STACKMAP ||
331 MI.getOpcode() == TargetOpcode::PATCHPOINT)
332 continue;
333
334
335
336
337
338
339
341
342
343 if (MO.isFI()) {
344
346 break;
347 int Idx = MO.getIndex();
348 int64_t LocalOffset = LocalOffsets[Idx];
349 if (->needsFrameBaseReg(&MI, LocalOffset))
350 break;
351 FrameReferenceInsns.push_back(FrameRef(&MI, LocalOffset, Idx, Order++));
352 break;
353 }
354 }
355 }
356 }
357
358
359
361
363
365 int64_t BaseOffset = 0;
366
367
368 for (int ref = 0, e = FrameReferenceInsns.size(); ref < e ; ++ref) {
369 FrameRef &FR = FrameReferenceInsns[ref];
371 int64_t LocalOffset = FR.getLocalOffset();
372 int FrameIdx = FR.getFrameIndex();
374 "Only pre-allocated locals expected!");
375
376
377
378
379
382 continue;
383
385
386 unsigned idx = 0;
387 for (unsigned f = MI.getNumOperands(); idx != f; ++idx) {
388 if (.getOperand(idx).isFI())
389 continue;
390
391 if (FrameIdx == MI.getOperand(idx).getIndex())
392 break;
393 }
394
395 assert(idx < MI.getNumOperands() && "Cannot find FI operand");
396
398 int64_t FrameSizeAdjust = StackGrowsDown ? MFI.getLocalFrameSize() : 0;
399
401
402
403
404
405
406
411 << "\n");
412
413 Offset = FrameSizeAdjust + LocalOffset - BaseOffset;
414 } else {
415
416 int64_t InstrOffset = TRI->getFrameIndexInstrOffset(&MI, idx);
417
418 int64_t CandBaseOffset = FrameSizeAdjust + LocalOffset + InstrOffset;
419
420
421
422
423
424
425 if (ref + 1 >= e ||
427 BaseReg, CandBaseOffset, FrameSizeAdjust,
428 FrameReferenceInsns[ref + 1].getLocalOffset(),
430 continue;
431
432
433 BaseOffset = CandBaseOffset;
434
435
436
437
438 BaseReg = TRI->materializeFrameBaseRegister(Entry, FrameIdx, InstrOffset);
439
440 LLVM_DEBUG(dbgs() << " Materialized base register at frame local offset "
441 << LocalOffset + InstrOffset
442 << " into " << printReg(BaseReg, TRI) << '\n');
443
444
445
446
447 Offset = -InstrOffset;
448
449 ++NumBaseRegisters;
450 }
451 assert(BaseReg && "Unable to allocate virtual base register!");
452
453
454
455 TRI->resolveFrameIndex(MI, BaseReg, Offset);
457
458 ++NumReplacements;
459 }
460
461 return BaseReg.isValid();
462}
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static MachineInstr * getMachineInstr(MachineInstr *MI)
static bool lookupCandidateBaseReg(unsigned BaseReg, int64_t BaseOffset, int64_t FrameSizeAdjust, int64_t LocalFrameOffset, const MachineInstr &MI, const TargetRegisterInfo *TRI)
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static void AssignProtectedObjSet(const StackObjSet &UnassignedObjs, SmallSet< int, 16 > &ProtectedObjs, MachineFrameInfo &MFI, bool StackGrowsDown, int64_t &Offset, Align &MaxAlign)
AssignProtectedObjSet - Helper function to assign large stack objects (i.e., those required to be clo...
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())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
SSPLayoutKind getObjectSSPLayout(int ObjectIdx) const
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
void setUseLocalStackAllocationBlock(bool v)
setUseLocalStackAllocationBlock - Set whether the local allocation blob should be allocated together ...
void setLocalFrameSize(int64_t sz)
Set the size of the local object blob.
@ SSPLK_SmallArray
Array or nested array < SSP-buffer-size.
@ SSPLK_LargeArray
Array or nested array >= SSP-buffer-size.
@ SSPLK_AddrOf
The address of this allocation is exposed and triggered protection.
@ SSPLK_None
Did not trigger a stack protector.
void setLocalFrameMaxAlign(Align Alignment)
Required alignment of the local object blob, which is the strictest alignment of any object in it.
int getStackProtectorIndex() const
Return the index for the stack protector object.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
void mapLocalFrameObject(int ObjectIndex, int64_t Offset)
Map a frame index into the local object block.
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.
bool hasStackProtectorIndex() const
uint8_t getStackID(int ObjectIdx) const
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.
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.
MachineOperand class - Representation of each machine instruction operand.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Information about stack frame layout on the target.
virtual bool isStackIdSafeForLocalArea(unsigned StackId) const
This method returns whether or not it is safe for an object with the given stack id to be bundled int...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
char & LocalStackSlotAllocationID
LocalStackSlotAllocation - This pass assigns local frame indices to stack slots relative to one anoth...
void initializeLocalStackSlotPassPass(PassRegistry &)
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
This struct is a compact representation of a valid (non-zero power of two) alignment.