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