15ffd83dbSDimitry Andric //===- StackLifetime.cpp - Alloca Lifetime Analysis -----------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "llvm/Analysis/StackLifetime.h" 105ffd83dbSDimitry Andric #include "llvm/ADT/DepthFirstIterator.h" 115ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h" 125ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h" 135ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h" 14e8d8bef9SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 155ffd83dbSDimitry Andric #include "llvm/Config/llvm-config.h" 165ffd83dbSDimitry Andric #include "llvm/IR/AssemblyAnnotationWriter.h" 175ffd83dbSDimitry Andric #include "llvm/IR/BasicBlock.h" 185ffd83dbSDimitry Andric #include "llvm/IR/CFG.h" 195ffd83dbSDimitry Andric #include "llvm/IR/InstIterator.h" 205ffd83dbSDimitry Andric #include "llvm/IR/Instructions.h" 215ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicInst.h" 225ffd83dbSDimitry Andric #include "llvm/IR/Value.h" 235ffd83dbSDimitry Andric #include "llvm/Support/Casting.h" 245ffd83dbSDimitry Andric #include "llvm/Support/Compiler.h" 255ffd83dbSDimitry Andric #include "llvm/Support/Debug.h" 265ffd83dbSDimitry Andric #include "llvm/Support/FormattedStream.h" 275ffd83dbSDimitry Andric #include <algorithm> 285ffd83dbSDimitry Andric #include <tuple> 295ffd83dbSDimitry Andric 305ffd83dbSDimitry Andric using namespace llvm; 315ffd83dbSDimitry Andric 325ffd83dbSDimitry Andric #define DEBUG_TYPE "stack-lifetime" 335ffd83dbSDimitry Andric 345ffd83dbSDimitry Andric const StackLifetime::LiveRange & 355ffd83dbSDimitry Andric StackLifetime::getLiveRange(const AllocaInst *AI) const { 365ffd83dbSDimitry Andric const auto IT = AllocaNumbering.find(AI); 375ffd83dbSDimitry Andric assert(IT != AllocaNumbering.end()); 385ffd83dbSDimitry Andric return LiveRanges[IT->second]; 395ffd83dbSDimitry Andric } 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric bool StackLifetime::isReachable(const Instruction *I) const { 4206c3fb27SDimitry Andric return BlockInstRange.contains(I->getParent()); 435ffd83dbSDimitry Andric } 445ffd83dbSDimitry Andric 455ffd83dbSDimitry Andric bool StackLifetime::isAliveAfter(const AllocaInst *AI, 465ffd83dbSDimitry Andric const Instruction *I) const { 475ffd83dbSDimitry Andric const BasicBlock *BB = I->getParent(); 485ffd83dbSDimitry Andric auto ItBB = BlockInstRange.find(BB); 495ffd83dbSDimitry Andric assert(ItBB != BlockInstRange.end() && "Unreachable is not expected"); 505ffd83dbSDimitry Andric 515ffd83dbSDimitry Andric // Search the block for the first instruction following 'I'. 525ffd83dbSDimitry Andric auto It = std::upper_bound(Instructions.begin() + ItBB->getSecond().first + 1, 535ffd83dbSDimitry Andric Instructions.begin() + ItBB->getSecond().second, I, 545ffd83dbSDimitry Andric [](const Instruction *L, const Instruction *R) { 555ffd83dbSDimitry Andric return L->comesBefore(R); 565ffd83dbSDimitry Andric }); 575ffd83dbSDimitry Andric --It; 585ffd83dbSDimitry Andric unsigned InstNum = It - Instructions.begin(); 595ffd83dbSDimitry Andric return getLiveRange(AI).test(InstNum); 605ffd83dbSDimitry Andric } 615ffd83dbSDimitry Andric 62e8d8bef9SDimitry Andric // Returns unique alloca annotated by lifetime marker only if 63e8d8bef9SDimitry Andric // markers has the same size and points to the alloca start. 64e8d8bef9SDimitry Andric static const AllocaInst *findMatchingAlloca(const IntrinsicInst &II, 65e8d8bef9SDimitry Andric const DataLayout &DL) { 66e8d8bef9SDimitry Andric const AllocaInst *AI = findAllocaForValue(II.getArgOperand(1), true); 67e8d8bef9SDimitry Andric if (!AI) 68e8d8bef9SDimitry Andric return nullptr; 695ffd83dbSDimitry Andric 70bdd1243dSDimitry Andric auto AllocaSize = AI->getAllocationSize(DL); 71bdd1243dSDimitry Andric if (!AllocaSize) 72e8d8bef9SDimitry Andric return nullptr; 73e8d8bef9SDimitry Andric 74e8d8bef9SDimitry Andric auto *Size = dyn_cast<ConstantInt>(II.getArgOperand(0)); 75e8d8bef9SDimitry Andric if (!Size) 76e8d8bef9SDimitry Andric return nullptr; 77e8d8bef9SDimitry Andric int64_t LifetimeSize = Size->getSExtValue(); 78e8d8bef9SDimitry Andric 79bdd1243dSDimitry Andric if (LifetimeSize != -1 && uint64_t(LifetimeSize) != *AllocaSize) 80e8d8bef9SDimitry Andric return nullptr; 81e8d8bef9SDimitry Andric 82e8d8bef9SDimitry Andric return AI; 835ffd83dbSDimitry Andric } 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric void StackLifetime::collectMarkers() { 865ffd83dbSDimitry Andric InterestingAllocas.resize(NumAllocas); 875ffd83dbSDimitry Andric DenseMap<const BasicBlock *, SmallDenseMap<const IntrinsicInst *, Marker>> 885ffd83dbSDimitry Andric BBMarkerSet; 895ffd83dbSDimitry Andric 90*0fca6ea1SDimitry Andric const DataLayout &DL = F.getDataLayout(); 91e8d8bef9SDimitry Andric 925ffd83dbSDimitry Andric // Compute the set of start/end markers per basic block. 93e8d8bef9SDimitry Andric for (const BasicBlock *BB : depth_first(&F)) { 94e8d8bef9SDimitry Andric for (const Instruction &I : *BB) { 95e8d8bef9SDimitry Andric const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I); 96e8d8bef9SDimitry Andric if (!II || !II->isLifetimeStartOrEnd()) 97e8d8bef9SDimitry Andric continue; 98e8d8bef9SDimitry Andric const AllocaInst *AI = findMatchingAlloca(*II, DL); 99e8d8bef9SDimitry Andric if (!AI) { 100e8d8bef9SDimitry Andric HasUnknownLifetimeStartOrEnd = true; 1015ffd83dbSDimitry Andric continue; 1025ffd83dbSDimitry Andric } 103e8d8bef9SDimitry Andric auto It = AllocaNumbering.find(AI); 104e8d8bef9SDimitry Andric if (It == AllocaNumbering.end()) 1055ffd83dbSDimitry Andric continue; 106e8d8bef9SDimitry Andric auto AllocaNo = It->second; 107e8d8bef9SDimitry Andric bool IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start; 1085ffd83dbSDimitry Andric if (IsStart) 1095ffd83dbSDimitry Andric InterestingAllocas.set(AllocaNo); 110e8d8bef9SDimitry Andric BBMarkerSet[BB][II] = {AllocaNo, IsStart}; 1115ffd83dbSDimitry Andric } 1125ffd83dbSDimitry Andric } 1135ffd83dbSDimitry Andric 1145ffd83dbSDimitry Andric // Compute instruction numbering. Only the following instructions are 1155ffd83dbSDimitry Andric // considered: 1165ffd83dbSDimitry Andric // * Basic block entries 1175ffd83dbSDimitry Andric // * Lifetime markers 1185ffd83dbSDimitry Andric // For each basic block, compute 1195ffd83dbSDimitry Andric // * the list of markers in the instruction order 1205ffd83dbSDimitry Andric // * the sets of allocas whose lifetime starts or ends in this BB 1215ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Instructions:\n"); 1225ffd83dbSDimitry Andric for (const BasicBlock *BB : depth_first(&F)) { 1235ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << " " << Instructions.size() << ": BB " << BB->getName() 1245ffd83dbSDimitry Andric << "\n"); 1255ffd83dbSDimitry Andric auto BBStart = Instructions.size(); 1265ffd83dbSDimitry Andric Instructions.push_back(nullptr); 1275ffd83dbSDimitry Andric 1285ffd83dbSDimitry Andric BlockLifetimeInfo &BlockInfo = 1295ffd83dbSDimitry Andric BlockLiveness.try_emplace(BB, NumAllocas).first->getSecond(); 1305ffd83dbSDimitry Andric 1315ffd83dbSDimitry Andric auto &BlockMarkerSet = BBMarkerSet[BB]; 1325ffd83dbSDimitry Andric if (BlockMarkerSet.empty()) { 1335ffd83dbSDimitry Andric BlockInstRange[BB] = std::make_pair(BBStart, Instructions.size()); 1345ffd83dbSDimitry Andric continue; 1355ffd83dbSDimitry Andric } 1365ffd83dbSDimitry Andric 1375ffd83dbSDimitry Andric auto ProcessMarker = [&](const IntrinsicInst *I, const Marker &M) { 1385ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << " " << Instructions.size() << ": " 1395ffd83dbSDimitry Andric << (M.IsStart ? "start " : "end ") << M.AllocaNo 1405ffd83dbSDimitry Andric << ", " << *I << "\n"); 1415ffd83dbSDimitry Andric 1425ffd83dbSDimitry Andric BBMarkers[BB].push_back({Instructions.size(), M}); 1435ffd83dbSDimitry Andric Instructions.push_back(I); 1445ffd83dbSDimitry Andric 1455ffd83dbSDimitry Andric if (M.IsStart) { 1465ffd83dbSDimitry Andric BlockInfo.End.reset(M.AllocaNo); 1475ffd83dbSDimitry Andric BlockInfo.Begin.set(M.AllocaNo); 1485ffd83dbSDimitry Andric } else { 1495ffd83dbSDimitry Andric BlockInfo.Begin.reset(M.AllocaNo); 1505ffd83dbSDimitry Andric BlockInfo.End.set(M.AllocaNo); 1515ffd83dbSDimitry Andric } 1525ffd83dbSDimitry Andric }; 1535ffd83dbSDimitry Andric 1545ffd83dbSDimitry Andric if (BlockMarkerSet.size() == 1) { 1555ffd83dbSDimitry Andric ProcessMarker(BlockMarkerSet.begin()->getFirst(), 1565ffd83dbSDimitry Andric BlockMarkerSet.begin()->getSecond()); 1575ffd83dbSDimitry Andric } else { 1585ffd83dbSDimitry Andric // Scan the BB to determine the marker order. 1595ffd83dbSDimitry Andric for (const Instruction &I : *BB) { 1605ffd83dbSDimitry Andric const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I); 1615ffd83dbSDimitry Andric if (!II) 1625ffd83dbSDimitry Andric continue; 1635ffd83dbSDimitry Andric auto It = BlockMarkerSet.find(II); 1645ffd83dbSDimitry Andric if (It == BlockMarkerSet.end()) 1655ffd83dbSDimitry Andric continue; 1665ffd83dbSDimitry Andric ProcessMarker(II, It->getSecond()); 1675ffd83dbSDimitry Andric } 1685ffd83dbSDimitry Andric } 1695ffd83dbSDimitry Andric 1705ffd83dbSDimitry Andric BlockInstRange[BB] = std::make_pair(BBStart, Instructions.size()); 1715ffd83dbSDimitry Andric } 1725ffd83dbSDimitry Andric } 1735ffd83dbSDimitry Andric 1745ffd83dbSDimitry Andric void StackLifetime::calculateLocalLiveness() { 1755ffd83dbSDimitry Andric bool Changed = true; 176bdd1243dSDimitry Andric 177bdd1243dSDimitry Andric // LiveIn, LiveOut and BitsIn have a different meaning deppends on type. 178bdd1243dSDimitry Andric // ::Maybe true bits represent "may be alive" allocas, ::Must true bits 179bdd1243dSDimitry Andric // represent "may be dead". After the loop we will convert ::Must bits from 180bdd1243dSDimitry Andric // "may be dead" to "must be alive". 1815ffd83dbSDimitry Andric while (Changed) { 182bdd1243dSDimitry Andric // TODO: Consider switching to worklist instead of traversing entire graph. 1835ffd83dbSDimitry Andric Changed = false; 1845ffd83dbSDimitry Andric 1855ffd83dbSDimitry Andric for (const BasicBlock *BB : depth_first(&F)) { 1865ffd83dbSDimitry Andric BlockLifetimeInfo &BlockInfo = BlockLiveness.find(BB)->getSecond(); 1875ffd83dbSDimitry Andric 188bdd1243dSDimitry Andric // Compute BitsIn by unioning together the LiveOut sets of all preds. 189bdd1243dSDimitry Andric BitVector BitsIn; 190fcaf7f86SDimitry Andric for (const auto *PredBB : predecessors(BB)) { 1915ffd83dbSDimitry Andric LivenessMap::const_iterator I = BlockLiveness.find(PredBB); 1925ffd83dbSDimitry Andric // If a predecessor is unreachable, ignore it. 1935ffd83dbSDimitry Andric if (I == BlockLiveness.end()) 1945ffd83dbSDimitry Andric continue; 195bdd1243dSDimitry Andric BitsIn |= I->second.LiveOut; 1965ffd83dbSDimitry Andric } 197bdd1243dSDimitry Andric 198bdd1243dSDimitry Andric // Everything is "may be dead" for entry without predecessors. 199bdd1243dSDimitry Andric if (Type == LivenessType::Must && BitsIn.empty()) 200bdd1243dSDimitry Andric BitsIn.resize(NumAllocas, true); 201bdd1243dSDimitry Andric 202bdd1243dSDimitry Andric // Update block LiveIn set, noting whether it has changed. 203bdd1243dSDimitry Andric if (BitsIn.test(BlockInfo.LiveIn)) { 204bdd1243dSDimitry Andric BlockInfo.LiveIn |= BitsIn; 2055ffd83dbSDimitry Andric } 2065ffd83dbSDimitry Andric 2075ffd83dbSDimitry Andric // Compute LiveOut by subtracting out lifetimes that end in this 2085ffd83dbSDimitry Andric // block, then adding in lifetimes that begin in this block. If 2095ffd83dbSDimitry Andric // we have both BEGIN and END markers in the same basic block 2105ffd83dbSDimitry Andric // then we know that the BEGIN marker comes after the END, 2115ffd83dbSDimitry Andric // because we already handle the case where the BEGIN comes 2125ffd83dbSDimitry Andric // before the END when collecting the markers (and building the 2135ffd83dbSDimitry Andric // BEGIN/END vectors). 214bdd1243dSDimitry Andric switch (Type) { 215bdd1243dSDimitry Andric case LivenessType::May: 216bdd1243dSDimitry Andric BitsIn.reset(BlockInfo.End); 217bdd1243dSDimitry Andric // "may be alive" is set by lifetime start. 218bdd1243dSDimitry Andric BitsIn |= BlockInfo.Begin; 219bdd1243dSDimitry Andric break; 220bdd1243dSDimitry Andric case LivenessType::Must: 221bdd1243dSDimitry Andric BitsIn.reset(BlockInfo.Begin); 222bdd1243dSDimitry Andric // "may be dead" is set by lifetime end. 223bdd1243dSDimitry Andric BitsIn |= BlockInfo.End; 224bdd1243dSDimitry Andric break; 2255ffd83dbSDimitry Andric } 2265ffd83dbSDimitry Andric 2275ffd83dbSDimitry Andric // Update block LiveOut set, noting whether it has changed. 228bdd1243dSDimitry Andric if (BitsIn.test(BlockInfo.LiveOut)) { 2295ffd83dbSDimitry Andric Changed = true; 230bdd1243dSDimitry Andric BlockInfo.LiveOut |= BitsIn; 2315ffd83dbSDimitry Andric } 2325ffd83dbSDimitry Andric } 2335ffd83dbSDimitry Andric } // while changed. 234bdd1243dSDimitry Andric 235bdd1243dSDimitry Andric if (Type == LivenessType::Must) { 236bdd1243dSDimitry Andric // Convert from "may be dead" to "must be alive". 237bdd1243dSDimitry Andric for (auto &[BB, BlockInfo] : BlockLiveness) { 238bdd1243dSDimitry Andric BlockInfo.LiveIn.flip(); 239bdd1243dSDimitry Andric BlockInfo.LiveOut.flip(); 240bdd1243dSDimitry Andric } 241bdd1243dSDimitry Andric } 2425ffd83dbSDimitry Andric } 2435ffd83dbSDimitry Andric 2445ffd83dbSDimitry Andric void StackLifetime::calculateLiveIntervals() { 2455ffd83dbSDimitry Andric for (auto IT : BlockLiveness) { 2465ffd83dbSDimitry Andric const BasicBlock *BB = IT.getFirst(); 2475ffd83dbSDimitry Andric BlockLifetimeInfo &BlockInfo = IT.getSecond(); 2485ffd83dbSDimitry Andric unsigned BBStart, BBEnd; 2495ffd83dbSDimitry Andric std::tie(BBStart, BBEnd) = BlockInstRange[BB]; 2505ffd83dbSDimitry Andric 2515ffd83dbSDimitry Andric BitVector Started, Ended; 2525ffd83dbSDimitry Andric Started.resize(NumAllocas); 2535ffd83dbSDimitry Andric Ended.resize(NumAllocas); 2545ffd83dbSDimitry Andric SmallVector<unsigned, 8> Start; 2555ffd83dbSDimitry Andric Start.resize(NumAllocas); 2565ffd83dbSDimitry Andric 2575ffd83dbSDimitry Andric // LiveIn ranges start at the first instruction. 2585ffd83dbSDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) { 2595ffd83dbSDimitry Andric if (BlockInfo.LiveIn.test(AllocaNo)) { 2605ffd83dbSDimitry Andric Started.set(AllocaNo); 2615ffd83dbSDimitry Andric Start[AllocaNo] = BBStart; 2625ffd83dbSDimitry Andric } 2635ffd83dbSDimitry Andric } 2645ffd83dbSDimitry Andric 2655ffd83dbSDimitry Andric for (auto &It : BBMarkers[BB]) { 2665ffd83dbSDimitry Andric unsigned InstNo = It.first; 2675ffd83dbSDimitry Andric bool IsStart = It.second.IsStart; 2685ffd83dbSDimitry Andric unsigned AllocaNo = It.second.AllocaNo; 2695ffd83dbSDimitry Andric 2705ffd83dbSDimitry Andric if (IsStart) { 2715ffd83dbSDimitry Andric if (!Started.test(AllocaNo)) { 2725ffd83dbSDimitry Andric Started.set(AllocaNo); 2735ffd83dbSDimitry Andric Ended.reset(AllocaNo); 2745ffd83dbSDimitry Andric Start[AllocaNo] = InstNo; 2755ffd83dbSDimitry Andric } 2765ffd83dbSDimitry Andric } else { 2775ffd83dbSDimitry Andric if (Started.test(AllocaNo)) { 2785ffd83dbSDimitry Andric LiveRanges[AllocaNo].addRange(Start[AllocaNo], InstNo); 2795ffd83dbSDimitry Andric Started.reset(AllocaNo); 2805ffd83dbSDimitry Andric } 2815ffd83dbSDimitry Andric Ended.set(AllocaNo); 2825ffd83dbSDimitry Andric } 2835ffd83dbSDimitry Andric } 2845ffd83dbSDimitry Andric 2855ffd83dbSDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) 2865ffd83dbSDimitry Andric if (Started.test(AllocaNo)) 2875ffd83dbSDimitry Andric LiveRanges[AllocaNo].addRange(Start[AllocaNo], BBEnd); 2885ffd83dbSDimitry Andric } 2895ffd83dbSDimitry Andric } 2905ffd83dbSDimitry Andric 2915ffd83dbSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 2925ffd83dbSDimitry Andric LLVM_DUMP_METHOD void StackLifetime::dumpAllocas() const { 2935ffd83dbSDimitry Andric dbgs() << "Allocas:\n"; 2945ffd83dbSDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) 2955ffd83dbSDimitry Andric dbgs() << " " << AllocaNo << ": " << *Allocas[AllocaNo] << "\n"; 2965ffd83dbSDimitry Andric } 2975ffd83dbSDimitry Andric 2985ffd83dbSDimitry Andric LLVM_DUMP_METHOD void StackLifetime::dumpBlockLiveness() const { 2995ffd83dbSDimitry Andric dbgs() << "Block liveness:\n"; 3005ffd83dbSDimitry Andric for (auto IT : BlockLiveness) { 3015ffd83dbSDimitry Andric const BasicBlock *BB = IT.getFirst(); 3025ffd83dbSDimitry Andric const BlockLifetimeInfo &BlockInfo = BlockLiveness.find(BB)->getSecond(); 3035ffd83dbSDimitry Andric auto BlockRange = BlockInstRange.find(BB)->getSecond(); 304e8d8bef9SDimitry Andric dbgs() << " BB (" << BB->getName() << ") [" << BlockRange.first << ", " << BlockRange.second 3055ffd83dbSDimitry Andric << "): begin " << BlockInfo.Begin << ", end " << BlockInfo.End 3065ffd83dbSDimitry Andric << ", livein " << BlockInfo.LiveIn << ", liveout " 3075ffd83dbSDimitry Andric << BlockInfo.LiveOut << "\n"; 3085ffd83dbSDimitry Andric } 3095ffd83dbSDimitry Andric } 3105ffd83dbSDimitry Andric 3115ffd83dbSDimitry Andric LLVM_DUMP_METHOD void StackLifetime::dumpLiveRanges() const { 3125ffd83dbSDimitry Andric dbgs() << "Alloca liveness:\n"; 3135ffd83dbSDimitry Andric for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) 3145ffd83dbSDimitry Andric dbgs() << " " << AllocaNo << ": " << LiveRanges[AllocaNo] << "\n"; 3155ffd83dbSDimitry Andric } 3165ffd83dbSDimitry Andric #endif 3175ffd83dbSDimitry Andric 3185ffd83dbSDimitry Andric StackLifetime::StackLifetime(const Function &F, 3195ffd83dbSDimitry Andric ArrayRef<const AllocaInst *> Allocas, 3205ffd83dbSDimitry Andric LivenessType Type) 3215ffd83dbSDimitry Andric : F(F), Type(Type), Allocas(Allocas), NumAllocas(Allocas.size()) { 3225ffd83dbSDimitry Andric LLVM_DEBUG(dumpAllocas()); 3235ffd83dbSDimitry Andric 3245ffd83dbSDimitry Andric for (unsigned I = 0; I < NumAllocas; ++I) 3255ffd83dbSDimitry Andric AllocaNumbering[Allocas[I]] = I; 3265ffd83dbSDimitry Andric 3275ffd83dbSDimitry Andric collectMarkers(); 3285ffd83dbSDimitry Andric } 3295ffd83dbSDimitry Andric 3305ffd83dbSDimitry Andric void StackLifetime::run() { 331e8d8bef9SDimitry Andric if (HasUnknownLifetimeStartOrEnd) { 332e8d8bef9SDimitry Andric // There is marker which we can't assign to a specific alloca, so we 333e8d8bef9SDimitry Andric // fallback to the most conservative results for the type. 334e8d8bef9SDimitry Andric switch (Type) { 335e8d8bef9SDimitry Andric case LivenessType::May: 336e8d8bef9SDimitry Andric LiveRanges.resize(NumAllocas, getFullLiveRange()); 337e8d8bef9SDimitry Andric break; 338e8d8bef9SDimitry Andric case LivenessType::Must: 339e8d8bef9SDimitry Andric LiveRanges.resize(NumAllocas, LiveRange(Instructions.size())); 340e8d8bef9SDimitry Andric break; 341e8d8bef9SDimitry Andric } 342e8d8bef9SDimitry Andric return; 343e8d8bef9SDimitry Andric } 344e8d8bef9SDimitry Andric 3455ffd83dbSDimitry Andric LiveRanges.resize(NumAllocas, LiveRange(Instructions.size())); 3465ffd83dbSDimitry Andric for (unsigned I = 0; I < NumAllocas; ++I) 3475ffd83dbSDimitry Andric if (!InterestingAllocas.test(I)) 3485ffd83dbSDimitry Andric LiveRanges[I] = getFullLiveRange(); 3495ffd83dbSDimitry Andric 3505ffd83dbSDimitry Andric calculateLocalLiveness(); 3515ffd83dbSDimitry Andric LLVM_DEBUG(dumpBlockLiveness()); 3525ffd83dbSDimitry Andric calculateLiveIntervals(); 3535ffd83dbSDimitry Andric LLVM_DEBUG(dumpLiveRanges()); 3545ffd83dbSDimitry Andric } 3555ffd83dbSDimitry Andric 3565ffd83dbSDimitry Andric class StackLifetime::LifetimeAnnotationWriter 3575ffd83dbSDimitry Andric : public AssemblyAnnotationWriter { 3585ffd83dbSDimitry Andric const StackLifetime &SL; 3595ffd83dbSDimitry Andric 3605ffd83dbSDimitry Andric void printInstrAlive(unsigned InstrNo, formatted_raw_ostream &OS) { 3615ffd83dbSDimitry Andric SmallVector<StringRef, 16> Names; 3625ffd83dbSDimitry Andric for (const auto &KV : SL.AllocaNumbering) { 3635ffd83dbSDimitry Andric if (SL.LiveRanges[KV.getSecond()].test(InstrNo)) 3645ffd83dbSDimitry Andric Names.push_back(KV.getFirst()->getName()); 3655ffd83dbSDimitry Andric } 3665ffd83dbSDimitry Andric llvm::sort(Names); 3675ffd83dbSDimitry Andric OS << " ; Alive: <" << llvm::join(Names, " ") << ">\n"; 3685ffd83dbSDimitry Andric } 3695ffd83dbSDimitry Andric 3705ffd83dbSDimitry Andric void emitBasicBlockStartAnnot(const BasicBlock *BB, 3715ffd83dbSDimitry Andric formatted_raw_ostream &OS) override { 3725ffd83dbSDimitry Andric auto ItBB = SL.BlockInstRange.find(BB); 3735ffd83dbSDimitry Andric if (ItBB == SL.BlockInstRange.end()) 3745ffd83dbSDimitry Andric return; // Unreachable. 3755ffd83dbSDimitry Andric printInstrAlive(ItBB->getSecond().first, OS); 3765ffd83dbSDimitry Andric } 3775ffd83dbSDimitry Andric 3785ffd83dbSDimitry Andric void printInfoComment(const Value &V, formatted_raw_ostream &OS) override { 3795ffd83dbSDimitry Andric const Instruction *Instr = dyn_cast<Instruction>(&V); 3805ffd83dbSDimitry Andric if (!Instr || !SL.isReachable(Instr)) 3815ffd83dbSDimitry Andric return; 3825ffd83dbSDimitry Andric 3835ffd83dbSDimitry Andric SmallVector<StringRef, 16> Names; 3845ffd83dbSDimitry Andric for (const auto &KV : SL.AllocaNumbering) { 3855ffd83dbSDimitry Andric if (SL.isAliveAfter(KV.getFirst(), Instr)) 3865ffd83dbSDimitry Andric Names.push_back(KV.getFirst()->getName()); 3875ffd83dbSDimitry Andric } 3885ffd83dbSDimitry Andric llvm::sort(Names); 3895ffd83dbSDimitry Andric OS << "\n ; Alive: <" << llvm::join(Names, " ") << ">\n"; 3905ffd83dbSDimitry Andric } 3915ffd83dbSDimitry Andric 3925ffd83dbSDimitry Andric public: 3935ffd83dbSDimitry Andric LifetimeAnnotationWriter(const StackLifetime &SL) : SL(SL) {} 3945ffd83dbSDimitry Andric }; 3955ffd83dbSDimitry Andric 3965ffd83dbSDimitry Andric void StackLifetime::print(raw_ostream &OS) { 3975ffd83dbSDimitry Andric LifetimeAnnotationWriter AAW(*this); 3985ffd83dbSDimitry Andric F.print(OS, &AAW); 3995ffd83dbSDimitry Andric } 4005ffd83dbSDimitry Andric 4015ffd83dbSDimitry Andric PreservedAnalyses StackLifetimePrinterPass::run(Function &F, 4025ffd83dbSDimitry Andric FunctionAnalysisManager &AM) { 4035ffd83dbSDimitry Andric SmallVector<const AllocaInst *, 8> Allocas; 4045ffd83dbSDimitry Andric for (auto &I : instructions(F)) 4055ffd83dbSDimitry Andric if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) 4065ffd83dbSDimitry Andric Allocas.push_back(AI); 4075ffd83dbSDimitry Andric StackLifetime SL(F, Allocas, Type); 4085ffd83dbSDimitry Andric SL.run(); 4095ffd83dbSDimitry Andric SL.print(OS); 4105ffd83dbSDimitry Andric return PreservedAnalyses::all(); 4115ffd83dbSDimitry Andric } 412349cc55cSDimitry Andric 413349cc55cSDimitry Andric void StackLifetimePrinterPass::printPipeline( 414349cc55cSDimitry Andric raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { 415349cc55cSDimitry Andric static_cast<PassInfoMixin<StackLifetimePrinterPass> *>(this)->printPipeline( 416349cc55cSDimitry Andric OS, MapClassName2PassName); 41706c3fb27SDimitry Andric OS << '<'; 418349cc55cSDimitry Andric switch (Type) { 419349cc55cSDimitry Andric case StackLifetime::LivenessType::May: 420349cc55cSDimitry Andric OS << "may"; 421349cc55cSDimitry Andric break; 422349cc55cSDimitry Andric case StackLifetime::LivenessType::Must: 423349cc55cSDimitry Andric OS << "must"; 424349cc55cSDimitry Andric break; 425349cc55cSDimitry Andric } 42606c3fb27SDimitry Andric OS << '>'; 427349cc55cSDimitry Andric } 428