1 //===- StackLifetime.cpp - Alloca Lifetime Analysis -----------------------===//
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 #include "llvm/Analysis/StackLifetime.h"
10 #include "llvm/ADT/DepthFirstIterator.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallVector.h"
13 #include "llvm/ADT/StringExtras.h"
14 #include "llvm/Analysis/ValueTracking.h"
15 #include "llvm/Config/llvm-config.h"
16 #include "llvm/IR/AssemblyAnnotationWriter.h"
17 #include "llvm/IR/BasicBlock.h"
18 #include "llvm/IR/CFG.h"
19 #include "llvm/IR/InstIterator.h"
20 #include "llvm/IR/Instructions.h"
21 #include "llvm/IR/IntrinsicInst.h"
22 #include "llvm/IR/Intrinsics.h"
23 #include "llvm/IR/User.h"
24 #include "llvm/IR/Value.h"
25 #include "llvm/Pass.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/FormattedStream.h"
31 #include <algorithm>
32 #include <memory>
33 #include <tuple>
34
35 using namespace llvm;
36
37 #define DEBUG_TYPE "stack-lifetime"
38
39 const StackLifetime::LiveRange &
getLiveRange(const AllocaInst * AI) const40 StackLifetime::getLiveRange(const AllocaInst *AI) const {
41 const auto IT = AllocaNumbering.find(AI);
42 assert(IT != AllocaNumbering.end());
43 return LiveRanges[IT->second];
44 }
45
isReachable(const Instruction * I) const46 bool StackLifetime::isReachable(const Instruction *I) const {
47 return BlockInstRange.find(I->getParent()) != BlockInstRange.end();
48 }
49
isAliveAfter(const AllocaInst * AI,const Instruction * I) const50 bool StackLifetime::isAliveAfter(const AllocaInst *AI,
51 const Instruction *I) const {
52 const BasicBlock *BB = I->getParent();
53 auto ItBB = BlockInstRange.find(BB);
54 assert(ItBB != BlockInstRange.end() && "Unreachable is not expected");
55
56 // Search the block for the first instruction following 'I'.
57 auto It = std::upper_bound(Instructions.begin() + ItBB->getSecond().first + 1,
58 Instructions.begin() + ItBB->getSecond().second, I,
59 [](const Instruction *L, const Instruction *R) {
60 return L->comesBefore(R);
61 });
62 --It;
63 unsigned InstNum = It - Instructions.begin();
64 return getLiveRange(AI).test(InstNum);
65 }
66
67 // Returns unique alloca annotated by lifetime marker only if
68 // markers has the same size and points to the alloca start.
findMatchingAlloca(const IntrinsicInst & II,const DataLayout & DL)69 static const AllocaInst *findMatchingAlloca(const IntrinsicInst &II,
70 const DataLayout &DL) {
71 const AllocaInst *AI = findAllocaForValue(II.getArgOperand(1), true);
72 if (!AI)
73 return nullptr;
74
75 auto AllocaSizeInBits = AI->getAllocationSizeInBits(DL);
76 if (!AllocaSizeInBits)
77 return nullptr;
78 int64_t AllocaSize = AllocaSizeInBits.getValue() / 8;
79
80 auto *Size = dyn_cast<ConstantInt>(II.getArgOperand(0));
81 if (!Size)
82 return nullptr;
83 int64_t LifetimeSize = Size->getSExtValue();
84
85 if (LifetimeSize != -1 && LifetimeSize != AllocaSize)
86 return nullptr;
87
88 return AI;
89 }
90
collectMarkers()91 void StackLifetime::collectMarkers() {
92 InterestingAllocas.resize(NumAllocas);
93 DenseMap<const BasicBlock *, SmallDenseMap<const IntrinsicInst *, Marker>>
94 BBMarkerSet;
95
96 const DataLayout &DL = F.getParent()->getDataLayout();
97
98 // Compute the set of start/end markers per basic block.
99 for (const BasicBlock *BB : depth_first(&F)) {
100 for (const Instruction &I : *BB) {
101 const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
102 if (!II || !II->isLifetimeStartOrEnd())
103 continue;
104 const AllocaInst *AI = findMatchingAlloca(*II, DL);
105 if (!AI) {
106 HasUnknownLifetimeStartOrEnd = true;
107 continue;
108 }
109 auto It = AllocaNumbering.find(AI);
110 if (It == AllocaNumbering.end())
111 continue;
112 auto AllocaNo = It->second;
113 bool IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start;
114 if (IsStart)
115 InterestingAllocas.set(AllocaNo);
116 BBMarkerSet[BB][II] = {AllocaNo, IsStart};
117 }
118 }
119
120 // Compute instruction numbering. Only the following instructions are
121 // considered:
122 // * Basic block entries
123 // * Lifetime markers
124 // For each basic block, compute
125 // * the list of markers in the instruction order
126 // * the sets of allocas whose lifetime starts or ends in this BB
127 LLVM_DEBUG(dbgs() << "Instructions:\n");
128 for (const BasicBlock *BB : depth_first(&F)) {
129 LLVM_DEBUG(dbgs() << " " << Instructions.size() << ": BB " << BB->getName()
130 << "\n");
131 auto BBStart = Instructions.size();
132 Instructions.push_back(nullptr);
133
134 BlockLifetimeInfo &BlockInfo =
135 BlockLiveness.try_emplace(BB, NumAllocas).first->getSecond();
136
137 auto &BlockMarkerSet = BBMarkerSet[BB];
138 if (BlockMarkerSet.empty()) {
139 BlockInstRange[BB] = std::make_pair(BBStart, Instructions.size());
140 continue;
141 }
142
143 auto ProcessMarker = [&](const IntrinsicInst *I, const Marker &M) {
144 LLVM_DEBUG(dbgs() << " " << Instructions.size() << ": "
145 << (M.IsStart ? "start " : "end ") << M.AllocaNo
146 << ", " << *I << "\n");
147
148 BBMarkers[BB].push_back({Instructions.size(), M});
149 Instructions.push_back(I);
150
151 if (M.IsStart) {
152 BlockInfo.End.reset(M.AllocaNo);
153 BlockInfo.Begin.set(M.AllocaNo);
154 } else {
155 BlockInfo.Begin.reset(M.AllocaNo);
156 BlockInfo.End.set(M.AllocaNo);
157 }
158 };
159
160 if (BlockMarkerSet.size() == 1) {
161 ProcessMarker(BlockMarkerSet.begin()->getFirst(),
162 BlockMarkerSet.begin()->getSecond());
163 } else {
164 // Scan the BB to determine the marker order.
165 for (const Instruction &I : *BB) {
166 const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
167 if (!II)
168 continue;
169 auto It = BlockMarkerSet.find(II);
170 if (It == BlockMarkerSet.end())
171 continue;
172 ProcessMarker(II, It->getSecond());
173 }
174 }
175
176 BlockInstRange[BB] = std::make_pair(BBStart, Instructions.size());
177 }
178 }
179
calculateLocalLiveness()180 void StackLifetime::calculateLocalLiveness() {
181 bool Changed = true;
182 while (Changed) {
183 Changed = false;
184
185 for (const BasicBlock *BB : depth_first(&F)) {
186 BlockLifetimeInfo &BlockInfo = BlockLiveness.find(BB)->getSecond();
187
188 // Compute LiveIn by unioning together the LiveOut sets of all preds.
189 BitVector LocalLiveIn;
190 for (auto *PredBB : predecessors(BB)) {
191 LivenessMap::const_iterator I = BlockLiveness.find(PredBB);
192 // If a predecessor is unreachable, ignore it.
193 if (I == BlockLiveness.end())
194 continue;
195 switch (Type) {
196 case LivenessType::May:
197 LocalLiveIn |= I->second.LiveOut;
198 break;
199 case LivenessType::Must:
200 if (LocalLiveIn.empty())
201 LocalLiveIn = I->second.LiveOut;
202 else
203 LocalLiveIn &= I->second.LiveOut;
204 break;
205 }
206 }
207
208 // Compute LiveOut by subtracting out lifetimes that end in this
209 // block, then adding in lifetimes that begin in this block. If
210 // we have both BEGIN and END markers in the same basic block
211 // then we know that the BEGIN marker comes after the END,
212 // because we already handle the case where the BEGIN comes
213 // before the END when collecting the markers (and building the
214 // BEGIN/END vectors).
215 BitVector LocalLiveOut = LocalLiveIn;
216 LocalLiveOut.reset(BlockInfo.End);
217 LocalLiveOut |= BlockInfo.Begin;
218
219 // Update block LiveIn set, noting whether it has changed.
220 if (LocalLiveIn.test(BlockInfo.LiveIn)) {
221 BlockInfo.LiveIn |= LocalLiveIn;
222 }
223
224 // Update block LiveOut set, noting whether it has changed.
225 if (LocalLiveOut.test(BlockInfo.LiveOut)) {
226 Changed = true;
227 BlockInfo.LiveOut |= LocalLiveOut;
228 }
229 }
230 } // while changed.
231 }
232
calculateLiveIntervals()233 void StackLifetime::calculateLiveIntervals() {
234 for (auto IT : BlockLiveness) {
235 const BasicBlock *BB = IT.getFirst();
236 BlockLifetimeInfo &BlockInfo = IT.getSecond();
237 unsigned BBStart, BBEnd;
238 std::tie(BBStart, BBEnd) = BlockInstRange[BB];
239
240 BitVector Started, Ended;
241 Started.resize(NumAllocas);
242 Ended.resize(NumAllocas);
243 SmallVector<unsigned, 8> Start;
244 Start.resize(NumAllocas);
245
246 // LiveIn ranges start at the first instruction.
247 for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) {
248 if (BlockInfo.LiveIn.test(AllocaNo)) {
249 Started.set(AllocaNo);
250 Start[AllocaNo] = BBStart;
251 }
252 }
253
254 for (auto &It : BBMarkers[BB]) {
255 unsigned InstNo = It.first;
256 bool IsStart = It.second.IsStart;
257 unsigned AllocaNo = It.second.AllocaNo;
258
259 if (IsStart) {
260 assert(!Started.test(AllocaNo) || Start[AllocaNo] == BBStart);
261 if (!Started.test(AllocaNo)) {
262 Started.set(AllocaNo);
263 Ended.reset(AllocaNo);
264 Start[AllocaNo] = InstNo;
265 }
266 } else {
267 assert(!Ended.test(AllocaNo));
268 if (Started.test(AllocaNo)) {
269 LiveRanges[AllocaNo].addRange(Start[AllocaNo], InstNo);
270 Started.reset(AllocaNo);
271 }
272 Ended.set(AllocaNo);
273 }
274 }
275
276 for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
277 if (Started.test(AllocaNo))
278 LiveRanges[AllocaNo].addRange(Start[AllocaNo], BBEnd);
279 }
280 }
281
282 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dumpAllocas() const283 LLVM_DUMP_METHOD void StackLifetime::dumpAllocas() const {
284 dbgs() << "Allocas:\n";
285 for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
286 dbgs() << " " << AllocaNo << ": " << *Allocas[AllocaNo] << "\n";
287 }
288
dumpBlockLiveness() const289 LLVM_DUMP_METHOD void StackLifetime::dumpBlockLiveness() const {
290 dbgs() << "Block liveness:\n";
291 for (auto IT : BlockLiveness) {
292 const BasicBlock *BB = IT.getFirst();
293 const BlockLifetimeInfo &BlockInfo = BlockLiveness.find(BB)->getSecond();
294 auto BlockRange = BlockInstRange.find(BB)->getSecond();
295 dbgs() << " BB (" << BB->getName() << ") [" << BlockRange.first << ", " << BlockRange.second
296 << "): begin " << BlockInfo.Begin << ", end " << BlockInfo.End
297 << ", livein " << BlockInfo.LiveIn << ", liveout "
298 << BlockInfo.LiveOut << "\n";
299 }
300 }
301
dumpLiveRanges() const302 LLVM_DUMP_METHOD void StackLifetime::dumpLiveRanges() const {
303 dbgs() << "Alloca liveness:\n";
304 for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo)
305 dbgs() << " " << AllocaNo << ": " << LiveRanges[AllocaNo] << "\n";
306 }
307 #endif
308
StackLifetime(const Function & F,ArrayRef<const AllocaInst * > Allocas,LivenessType Type)309 StackLifetime::StackLifetime(const Function &F,
310 ArrayRef<const AllocaInst *> Allocas,
311 LivenessType Type)
312 : F(F), Type(Type), Allocas(Allocas), NumAllocas(Allocas.size()) {
313 LLVM_DEBUG(dumpAllocas());
314
315 for (unsigned I = 0; I < NumAllocas; ++I)
316 AllocaNumbering[Allocas[I]] = I;
317
318 collectMarkers();
319 }
320
run()321 void StackLifetime::run() {
322 if (HasUnknownLifetimeStartOrEnd) {
323 // There is marker which we can't assign to a specific alloca, so we
324 // fallback to the most conservative results for the type.
325 switch (Type) {
326 case LivenessType::May:
327 LiveRanges.resize(NumAllocas, getFullLiveRange());
328 break;
329 case LivenessType::Must:
330 LiveRanges.resize(NumAllocas, LiveRange(Instructions.size()));
331 break;
332 }
333 return;
334 }
335
336 LiveRanges.resize(NumAllocas, LiveRange(Instructions.size()));
337 for (unsigned I = 0; I < NumAllocas; ++I)
338 if (!InterestingAllocas.test(I))
339 LiveRanges[I] = getFullLiveRange();
340
341 calculateLocalLiveness();
342 LLVM_DEBUG(dumpBlockLiveness());
343 calculateLiveIntervals();
344 LLVM_DEBUG(dumpLiveRanges());
345 }
346
347 class StackLifetime::LifetimeAnnotationWriter
348 : public AssemblyAnnotationWriter {
349 const StackLifetime &SL;
350
printInstrAlive(unsigned InstrNo,formatted_raw_ostream & OS)351 void printInstrAlive(unsigned InstrNo, formatted_raw_ostream &OS) {
352 SmallVector<StringRef, 16> Names;
353 for (const auto &KV : SL.AllocaNumbering) {
354 if (SL.LiveRanges[KV.getSecond()].test(InstrNo))
355 Names.push_back(KV.getFirst()->getName());
356 }
357 llvm::sort(Names);
358 OS << " ; Alive: <" << llvm::join(Names, " ") << ">\n";
359 }
360
emitBasicBlockStartAnnot(const BasicBlock * BB,formatted_raw_ostream & OS)361 void emitBasicBlockStartAnnot(const BasicBlock *BB,
362 formatted_raw_ostream &OS) override {
363 auto ItBB = SL.BlockInstRange.find(BB);
364 if (ItBB == SL.BlockInstRange.end())
365 return; // Unreachable.
366 printInstrAlive(ItBB->getSecond().first, OS);
367 }
368
printInfoComment(const Value & V,formatted_raw_ostream & OS)369 void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
370 const Instruction *Instr = dyn_cast<Instruction>(&V);
371 if (!Instr || !SL.isReachable(Instr))
372 return;
373
374 SmallVector<StringRef, 16> Names;
375 for (const auto &KV : SL.AllocaNumbering) {
376 if (SL.isAliveAfter(KV.getFirst(), Instr))
377 Names.push_back(KV.getFirst()->getName());
378 }
379 llvm::sort(Names);
380 OS << "\n ; Alive: <" << llvm::join(Names, " ") << ">\n";
381 }
382
383 public:
LifetimeAnnotationWriter(const StackLifetime & SL)384 LifetimeAnnotationWriter(const StackLifetime &SL) : SL(SL) {}
385 };
386
print(raw_ostream & OS)387 void StackLifetime::print(raw_ostream &OS) {
388 LifetimeAnnotationWriter AAW(*this);
389 F.print(OS, &AAW);
390 }
391
run(Function & F,FunctionAnalysisManager & AM)392 PreservedAnalyses StackLifetimePrinterPass::run(Function &F,
393 FunctionAnalysisManager &AM) {
394 SmallVector<const AllocaInst *, 8> Allocas;
395 for (auto &I : instructions(F))
396 if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I))
397 Allocas.push_back(AI);
398 StackLifetime SL(F, Allocas, Type);
399 SL.run();
400 SL.print(OS);
401 return PreservedAnalyses::all();
402 }
403