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