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