123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- #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);
- }
|