make LVI::getEdgeValue() always intersect the constraints of the edge with the range of the block. Previously it was only performing the intersection for a few cases, thus losing precision

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159320 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nuno Lopes
2012-06-28 01:16:18 +00:00
parent 532516a87b
commit e441394784
2 changed files with 96 additions and 35 deletions

View File

@ -172,7 +172,7 @@ public:
if (NewR.isEmptySet())
return markOverdefined();
bool changed = Range == NewR;
bool changed = Range != NewR;
Range = NewR;
return changed;
}
@ -457,8 +457,10 @@ void LazyValueInfoCache::eraseBlock(BasicBlock *BB) {
void LazyValueInfoCache::solve() {
while (!BlockValueStack.empty()) {
std::pair<BasicBlock*, Value*> &e = BlockValueStack.top();
if (solveBlockValue(e.second, e.first))
if (solveBlockValue(e.second, e.first)) {
assert(BlockValueStack.top() == e);
BlockValueStack.pop();
}
}
}
@ -766,15 +768,10 @@ bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV,
return true;
}
/// getEdgeValue - This method attempts to infer more complex
bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom,
BasicBlock *BBTo, LVILatticeVal &Result) {
// If already a constant, there is nothing to compute.
if (Constant *VC = dyn_cast<Constant>(Val)) {
Result = LVILatticeVal::get(VC);
return true;
}
/// \brief Compute the value of Val on the edge BBFrom -> BBTo. Returns false if
/// Val is not constrained on the edge.
static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
BasicBlock *BBTo, LVILatticeVal &Result) {
// TODO: Handle more complex conditionals. If (v == 0 || v2 < 1) is false, we
// know that v != 0.
if (BranchInst *BI = dyn_cast<BranchInst>(BBFrom->getTerminator())) {
@ -827,25 +824,8 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom,
// If we're interested in the false dest, invert the condition.
if (!isTrueDest) TrueValues = TrueValues.inverse();
// Figure out the possible values of the query BEFORE this branch.
if (!hasBlockValue(Val, BBFrom)) {
BlockValueStack.push(std::make_pair(BBFrom, Val));
return false;
}
LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
if (!InBlock.isConstantRange()) {
Result = LVILatticeVal::getRange(TrueValues);
return true;
}
// Find all potential values that satisfy both the input and output
// conditions.
ConstantRange PossibleValues =
TrueValues.intersectWith(InBlock.getConstantRange());
Result = LVILatticeVal::getRange(PossibleValues);
Result = LVILatticeVal::getRange(TrueValues);
return true;
}
}
@ -874,14 +854,51 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom,
return true;
}
}
// Otherwise see if the value is known in the block.
if (hasBlockValue(Val, BBFrom)) {
Result = getBlockValue(Val, BBFrom);
return false;
}
/// \brief Compute the value of Val on the edge BBFrom -> BBTo, or the value at
/// the basic block if the edge does not constraint Val.
bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom,
BasicBlock *BBTo, LVILatticeVal &Result) {
// If already a constant, there is nothing to compute.
if (Constant *VC = dyn_cast<Constant>(Val)) {
Result = LVILatticeVal::get(VC);
return true;
}
BlockValueStack.push(std::make_pair(BBFrom, Val));
return false;
if (getEdgeValueLocal(Val, BBFrom, BBTo, Result)) {
if (!Result.isConstantRange() ||
Result.getConstantRange().getSingleElement())
return true;
// FIXME: this check should be moved to the beginning of the function when
// LVI better supports recursive values. Even for the single value case, we
// can intersect to detect dead code (an empty range).
if (!hasBlockValue(Val, BBFrom)) {
BlockValueStack.push(std::make_pair(BBFrom, Val));
return false;
}
// Try to intersect ranges of the BB and the constraint on the edge.
LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
if (!InBlock.isConstantRange())
return true;
ConstantRange Range =
Result.getConstantRange().intersectWith(InBlock.getConstantRange());
Result = LVILatticeVal::getRange(Range);
return true;
}
if (!hasBlockValue(Val, BBFrom)) {
BlockValueStack.push(std::make_pair(BBFrom, Val));
return false;
}
// if we couldn't compute the value on the edge, use the value from the BB
Result = getBlockValue(Val, BBFrom);
return true;
}
LVILatticeVal LazyValueInfoCache::getValueInBlock(Value *V, BasicBlock *BB) {