blob: baa53691dfa5538782e6907bfcb00197336a9d22 [file] [log] [blame] [edit]
#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);
}