[LVI] Cleanup/unify cache access

This patch combines the "has" and "get" parts of the cache access.
getCachedValueInfo() now both sets the BBLV return argument, and
returns whether the value was found.

Additionally, the management of the work stack is now integrated
into getBlockValue(). If the value is not cached yet, we try to
push to the stack (and return false, indicating that we need to
solve first), or return overdefined in case of a cycle.

These changes a) avoid a duplicate cache lookup for has & get and
b) ensure that the logic is uniform everywhere. For this reason
this change is also not quite NFC, because previously overdefined
values from the cache, and overdefined values from a cycle received
different treatment when it came to assumption intersection.

Differential Revision: https://reviews.llvm.org/D76788
This commit is contained in:
Nikita Popov 2020-03-24 20:31:13 +01:00
parent 24cae17c28
commit f715eda604
1 changed files with 59 additions and 78 deletions

View File

@ -211,28 +211,21 @@ namespace {
return ODI->second.count(V);
}
bool hasCachedValueInfo(Value *V, BasicBlock *BB) const {
if (isOverdefined(V, BB))
bool getCachedValueInfo(ValueLatticeElement &BBLV, Value *V,
BasicBlock *BB) const {
if (isOverdefined(V, BB)) {
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
auto I = ValueCache.find_as(V);
if (I == ValueCache.end())
return false;
return I->second->BlockVals.count(BB);
}
ValueLatticeElement getCachedValueInfo(Value *V, BasicBlock *BB) const {
if (isOverdefined(V, BB))
return ValueLatticeElement::getOverdefined();
auto I = ValueCache.find_as(V);
if (I == ValueCache.end())
return ValueLatticeElement();
auto BBI = I->second->BlockVals.find(BB);
if (BBI == I->second->BlockVals.end())
return ValueLatticeElement();
return BBI->second;
return false;
BBLV = BBI->second;
return true;
}
/// clear - Empty the cache.
@ -409,10 +402,9 @@ namespace {
DominatorTree *DT; ///< An optional DT pointer.
DominatorTree *DisabledDT; ///< Stores DT if it's disabled.
ValueLatticeElement getBlockValue(Value *Val, BasicBlock *BB);
bool getBlockValue(ValueLatticeElement &Result, Value *Val, BasicBlock *BB);
bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T,
ValueLatticeElement &Result, Instruction *CxtI = nullptr);
bool hasBlockValue(Value *Val, BasicBlock *BB);
// These methods process one work item and may add more. A false value
// returned means that the work item was not completely processed and must
@ -547,12 +539,14 @@ void LazyValueInfoImpl::solve() {
if (solveBlockValue(e.second, e.first)) {
// The work item was completely processed.
assert(BlockValueStack.back() == e && "Nothing should have been pushed!");
assert(TheCache.hasCachedValueInfo(e.second, e.first) &&
#ifndef NDEBUG
ValueLatticeElement BBLV;
assert(TheCache.getCachedValueInfo(BBLV, e.second, e.first) &&
"Result should be in cache!");
LLVM_DEBUG(
dbgs() << "POP " << *e.second << " in " << e.first->getName() << " = "
<< TheCache.getCachedValueInfo(e.second, e.first) << "\n");
<< BBLV << "\n");
#endif
BlockValueStack.pop_back();
BlockValueSet.erase(e);
@ -563,21 +557,25 @@ void LazyValueInfoImpl::solve() {
}
}
bool LazyValueInfoImpl::hasBlockValue(Value *Val, BasicBlock *BB) {
bool LazyValueInfoImpl::getBlockValue(ValueLatticeElement &BBLV,
Value *Val, BasicBlock *BB) {
// If already a constant, there is nothing to compute.
if (isa<Constant>(Val))
if (Constant *VC = dyn_cast<Constant>(Val)) {
BBLV = ValueLatticeElement::get(VC);
return true;
}
if (TheCache.getCachedValueInfo(BBLV, Val, BB))
return true;
return TheCache.hasCachedValueInfo(Val, BB);
}
// We have hit a cycle, assume overdefined.
if (!pushBlockValue({ BB, Val })) {
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
ValueLatticeElement LazyValueInfoImpl::getBlockValue(Value *Val,
BasicBlock *BB) {
// If already a constant, there is nothing to compute.
if (Constant *VC = dyn_cast<Constant>(Val))
return ValueLatticeElement::get(VC);
return TheCache.getCachedValueInfo(Val, BB);
// Yet to be resolved.
return false;
}
static ValueLatticeElement getFromRangeMetadata(Instruction *BBI) {
@ -598,9 +596,12 @@ static ValueLatticeElement getFromRangeMetadata(Instruction *BBI) {
}
bool LazyValueInfoImpl::solveBlockValue(Value *Val, BasicBlock *BB) {
#ifndef NDEBUG
ValueLatticeElement BBLV;
assert(!isa<Constant>(Val) && "Value should not be constant");
assert(!TheCache.hasCachedValueInfo(Val, BB) &&
assert(!TheCache.getCachedValueInfo(BBLV, Val, BB) &&
"Value should not be in cache");
#endif
// Hold off inserting this value into the Cache in case we have to return
// false and come back later.
@ -851,13 +852,10 @@ bool LazyValueInfoImpl::solveBlockValueSelect(ValueLatticeElement &BBLV,
SelectInst *SI, BasicBlock *BB) {
// Recurse on our inputs if needed
if (!hasBlockValue(SI->getTrueValue(), BB)) {
if (pushBlockValue(std::make_pair(BB, SI->getTrueValue())))
return false;
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
ValueLatticeElement TrueVal = getBlockValue(SI->getTrueValue(), BB);
ValueLatticeElement TrueVal;
if (!getBlockValue(TrueVal, SI->getTrueValue(), BB))
return false;
// If we hit overdefined, don't ask more queries. We want to avoid poisoning
// extra slots in the table if we can.
if (TrueVal.isOverdefined()) {
@ -865,13 +863,10 @@ bool LazyValueInfoImpl::solveBlockValueSelect(ValueLatticeElement &BBLV,
return true;
}
if (!hasBlockValue(SI->getFalseValue(), BB)) {
if (pushBlockValue(std::make_pair(BB, SI->getFalseValue())))
return false;
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
ValueLatticeElement FalseVal = getBlockValue(SI->getFalseValue(), BB);
ValueLatticeElement FalseVal;
if (!getBlockValue(FalseVal, SI->getFalseValue(), BB))
return false;
// If we hit overdefined, don't ask more queries. We want to avoid poisoning
// extra slots in the table if we can.
if (FalseVal.isOverdefined()) {
@ -998,20 +993,17 @@ bool LazyValueInfoImpl::solveBlockValueSelect(ValueLatticeElement &BBLV,
Optional<ConstantRange> LazyValueInfoImpl::getRangeForOperand(unsigned Op,
Instruction *I,
BasicBlock *BB) {
if (!hasBlockValue(I->getOperand(Op), BB))
if (pushBlockValue(std::make_pair(BB, I->getOperand(Op))))
return None;
ValueLatticeElement Val;
if (!getBlockValue(Val, I->getOperand(Op), BB))
return None;
intersectAssumeOrGuardBlockValueConstantRange(I->getOperand(Op), Val, I);
if (Val.isConstantRange())
return Val.getConstantRange();
const unsigned OperandBitWidth =
DL.getTypeSizeInBits(I->getOperand(Op)->getType());
ConstantRange Range = ConstantRange::getFull(OperandBitWidth);
if (hasBlockValue(I->getOperand(Op), BB)) {
ValueLatticeElement Val = getBlockValue(I->getOperand(Op), BB);
intersectAssumeOrGuardBlockValueConstantRange(I->getOperand(Op), Val, I);
if (Val.isConstantRange())
Range = Val.getConstantRange();
}
return Range;
return ConstantRange::getFull(OperandBitWidth);
}
bool LazyValueInfoImpl::solveBlockValueCast(ValueLatticeElement &BBLV,
@ -1172,16 +1164,8 @@ bool LazyValueInfoImpl::solveBlockValueExtractValue(
// based on replaced with.overflow intrinsics.
if (Value *V = SimplifyExtractValueInst(
EVI->getAggregateOperand(), EVI->getIndices(),
EVI->getModule()->getDataLayout())) {
if (!hasBlockValue(V, BB)) {
if (pushBlockValue({ BB, V }))
return false;
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
BBLV = getBlockValue(V, BB);
return true;
}
EVI->getModule()->getDataLayout()))
return getBlockValue(BBLV, V, BB);
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - overdefined (unknown extractvalue).\n");
@ -1524,16 +1508,11 @@ bool LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
return true;
}
if (!hasBlockValue(Val, BBFrom)) {
if (pushBlockValue(std::make_pair(BBFrom, Val)))
return false;
// No new information.
Result = LocalResult;
return true;
}
ValueLatticeElement InBlock;
if (!getBlockValue(InBlock, Val, BBFrom))
return false;
// Try to intersect ranges of the BB and the constraint on the edge.
ValueLatticeElement InBlock = getBlockValue(Val, BBFrom);
intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock,
BBFrom->getTerminator());
// We can use the context instruction (generically the ultimate instruction
@ -1556,11 +1535,13 @@ ValueLatticeElement LazyValueInfoImpl::getValueInBlock(Value *V, BasicBlock *BB,
<< BB->getName() << "'\n");
assert(BlockValueStack.empty() && BlockValueSet.empty());
if (!hasBlockValue(V, BB)) {
pushBlockValue(std::make_pair(BB, V));
ValueLatticeElement Result;
if (!getBlockValue(Result, V, BB)) {
solve();
bool ValueAvailable = getBlockValue(Result, V, BB);
(void) ValueAvailable;
assert(ValueAvailable && "Value not available after solving");
}
ValueLatticeElement Result = getBlockValue(V, BB);
intersectAssumeOrGuardBlockValueConstantRange(V, Result, CxtI);
LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");