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