#include "LiveValues.h" #include "llvm/IR/CFG.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" using namespace llvm; static void applyMapping(InstructionSetVector& iset, llvm::DenseMap& imap) { // There will be probably be few entries in the imap, so apply them one at a time to the iset. for (auto& kv : imap) { if (iset.count(kv.first) != 0) { iset.remove(kv.first); iset.insert(kv.second); } } } // Compute liveness of a value at basic blocks. Roughly based on // Algorithm 6 & 7 from the paper "Computing Liveness Sets for SSA- // Form Programs" by Brander et al., 2011. LiveValues::LiveValues(ArrayRef computeLiveAt) { m_liveSets.resize(computeLiveAt.size()); // Build index and set of active blocks for (unsigned int i = 0; i < computeLiveAt.size(); i++) { Instruction* v = computeLiveAt[i]; m_computeLiveAtIndex.insert(std::make_pair(v, i)); m_activeBlocks.insert(v->getParent()); } if (computeLiveAt.size() > 0) { m_function = computeLiveAt[0]->getParent()->getParent(); } } // Go over all the instructions between begin (included) and end (excluded) and mark the given value // live for code locations contained in the given range. void LiveValues::markLiveRange(Instruction* value, BasicBlock::iterator begin, BasicBlock::iterator end) { BasicBlock* B = begin->getParent(); if (m_activeBlocks.count(B) == 0) return; // Nothing to mark in this block for (BasicBlock::iterator I = begin; I != end; ++I) { if (m_computeLiveAtIndex.count(I)) { // Mark this value unsigned int index = m_computeLiveAtIndex[I]; m_liveSets[index].insert(value); m_allLiveSet.insert(value); // Also store for each value where it is live. m_liveAtIndices[value].insert(index); } } } void LiveValues::upAndMark(Instruction* def, Use& use, BlockSet& scanned) { // Determine the starting point for the backwards search. // (Remember that Use represents an edge between the definition of a value and its use) // In the case in which the user of the use is a phi node we start the search from the terminator // of the preceding block. // This allows to avoid going through loop back-edges in cases like these: // | // | (y) // v // ----------------- // (x) | z = phi(x, y) | // ----> | ... | // | | x = z + 1 | // | ----------------- // | | // | | // | | // | v // | ----------------- // | | | // ------| INDIRECT CALL | // | | // ----------------- // | (Start the search for the definition of x (backwards) from here!) // v // // Notice that here x is live across the call. This case is tricky because the def comes 'after' // the use. The def still dominates the use because phi nodes logically use their input values on the // edges, i.e. on the terminator of the preceding blocks. // // This has the advantage of being able to traverse edges strictly backwards. Instruction* startingPoint = dyn_cast(use.getUser()); if (PHINode* usePHI = dyn_cast(startingPoint)) { BasicBlock* predecessor = usePHI->getIncomingBlock(use); startingPoint = predecessor->getTerminator(); } BasicBlock* startingPointBB = startingPoint->getParent(); BasicBlock* defBB = def->getParent(); // Start a bottom-up recursive search from startingPoint to the definition of the current value. // Mark all the code ranges that we encounter on the way a having the current value 'live'. // 'scanned' contains the blocks that we have scanned to the bottom of the block and the we know // already having the current value 'live'. SmallVector worklist; worklist.push_back(startingPointBB); BlockSet visited; while (!worklist.empty()) { BasicBlock* B = worklist.pop_back_val(); if (scanned.count(B) != 0) continue; // We have reached the block that contains the definition of the value. We are done for this // branch of the search. if (B == defBB) { if (defBB == startingPointBB) { // If the first block that we visit is also the last mark only the range of instructions // between the def and the starting point. // ----------------- // | | // | x = // def | <-- // | | ! // | | ! This is the range in which x is live. // | | ! // | = x // use | <-- // | | // ----------------- markLiveRange(def, ++BasicBlock::iterator(def), BasicBlock::iterator(startingPoint)); } else { markLiveRange(def, ++BasicBlock::iterator(def), defBB->end()); scanned.insert(B); } } else { if (B == startingPointBB) { // We are in the starting-point block. // This can mean two things: // 1. We are in the first iteration, mark the range between begin and starting point as // live. if (visited.count(B) == 0) { markLiveRange(def, B->begin(), BasicBlock::iterator(startingPoint)); } // 2. We came back here because the starting point is in a loop. // In this case mark the whole block as live range and don't come back anymore. else { markLiveRange(def, B->begin(), B->end()); scanned.insert(B); } // The if statement above allows to manage situations like this: // BB0 // ----------------- // | x = ... | // ----------------- // | // | // | // BB1 v // -----------------<-- <-- // | | ! ! // ----->| | ! First range marked ! // | | | ! ! // | | ... = x |<-- ! Second and final range marked // | | | ! // | | INDIRECT CALL | ! // | | | ! // | ----------------- <-- // | | // --------------- // x is defined outside a loop and used inside a loop. This means that it is live inside the // whole loop. // So, we first mark the range from the use of x to the top of BB1 and, when we visit BB1 // again (because BB1 is a predecessor of BB1) we mark the whole block as live range. // // This case could have been managed much more easily and efficiently if we had access to // LLVM LoopInfo analysis pass. // We could have done the following: x is uses in a loop and defined outside of it => mark // the whole loop body as live range. // } else { // We are in an intermediate block on the way to the definition mark it, all as live range. markLiveRange(def, B->begin(), B->end()); scanned.insert(B); } visited.insert(B); for (pred_iterator P = pred_begin(B), PE = pred_end(B); P != PE; ++P) { worklist.push_back(*P); } } } } void LiveValues::run() { if (m_computeLiveAtIndex.empty()) return; // for each variable v do for (inst_iterator I = inst_begin(m_function), E = inst_end(m_function); I != E; ++I) { Instruction* v = &*I; assert(v->getParent()->getParent() == m_function); // for each block B where v is used do BlockSet scanned; for (Value::use_iterator U = v->use_begin(), UE = v->use_end(); U != UE; ++U) { Instruction* user = cast(U->getUser()); assert(user->getParent()->getParent() == m_function); (void)user; upAndMark(v, *U, scanned); } } } void LiveValues::remapLiveValues(llvm::DenseMap& imap) { applyMapping(m_allLiveSet, imap); for (auto& liveSet : m_liveSets) applyMapping(liveSet, imap); } const LiveValues::Indices* LiveValues::getIndicesWhereLive(const Value* value) const { const auto& iter = m_liveAtIndices.find(value); if (iter == m_liveAtIndices.end()) return nullptr; return &iter->second; } void LiveValues::setIndicesWhereLive(Value* value, const Indices* indices) { for (unsigned int idx : *indices) setLiveAtIndex(value, idx, true); } bool LiveValues::liveInDisjointRegions(const Value* valueA, const Value* valueB) const { const Indices* indicesA = getIndicesWhereLive(valueA); if (!indicesA) return true; const Indices* indicesB = getIndicesWhereLive(valueB); if (!indicesB) return true; for (const unsigned int index : *indicesA) { if (indicesB->count(index)) return false; } return true; } void LiveValues::setLiveAtIndex(Value* value, unsigned int index, bool live) { assert(index <= m_computeLiveAtIndex.size()); if (live) { m_liveAtIndices[value].insert(index); Instruction* inst = cast(value); m_liveSets[index].insert(inst); m_allLiveSet.insert(inst); } else { m_liveAtIndices[value].remove(index); Instruction* inst = cast(value); m_liveSets[index].remove(inst); if (m_liveAtIndices[value].empty()) m_allLiveSet.remove(inst); } } void LiveValues::setLiveAtAllIndices(llvm::Value* value, bool live) { Instruction* inst = cast(value); if (live) { for (unsigned int index = 0; index < m_computeLiveAtIndex.size(); ++index) { m_liveAtIndices[value].insert(index); m_liveSets[index].insert(inst); } m_allLiveSet.insert(inst); } else { for (unsigned int index = 0; index < m_computeLiveAtIndex.size(); ++index) { m_liveAtIndices[value].remove(index); m_liveSets[index].remove(inst); } if (m_liveAtIndices[value].empty()) m_allLiveSet.remove(inst); } } bool LiveValues::getLiveAtIndex(const Value* value, unsigned int index) const { assert(index <= m_computeLiveAtIndex.size()); const auto& it = m_liveAtIndices.find(value); if (it == m_liveAtIndices.end()) return false; return (it->second.count(index) != 0); }