| #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<llvm::Instruction *, llvm::Instruction *> &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<Instruction *> 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<Instruction>(use.getUser()); |
| if (PHINode *usePHI = dyn_cast<PHINode>(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<BasicBlock *, 16> 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. |
| // <rant> |
| // 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. |
| // </rant> |
| } 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<Instruction>(U->getUser()); |
| assert(user->getParent()->getParent() == m_function); |
| (void)user; |
| |
| upAndMark(v, *U, scanned); |
| } |
| } |
| } |
| |
| void LiveValues::remapLiveValues( |
| llvm::DenseMap<llvm::Instruction *, llvm::Instruction *> &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<Instruction>(value); |
| m_liveSets[index].insert(inst); |
| m_allLiveSet.insert(inst); |
| } else { |
| m_liveAtIndices[value].remove(index); |
| Instruction *inst = cast<Instruction>(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<Instruction>(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); |
| } |