[LVI] Don't require DominatorTree in LVI (NFC)

After D76797 the dominator tree is no longer used in LVI, so we
can remove it as a pass dependency, and also get rid of the
dominator tree enabling/disabling logic in JumpThreading.

Apart from cleaning up the code, this also clarifies LVI
cache consistency, in that the LVI cache can no longer
depend on whether the DT was or wasn't enabled due to
pending DT updates at any given time.

Differential Revision: https://reviews.llvm.org/D76985
This commit is contained in:
Nikita Popov 2020-03-25 20:02:07 +01:00
parent 520a570268
commit 5fae613a4f
5 changed files with 23 additions and 139 deletions

View File

@ -33,18 +33,17 @@ class LazyValueInfo {
AssumptionCache *AC = nullptr;
const DataLayout *DL = nullptr;
class TargetLibraryInfo *TLI = nullptr;
DominatorTree *DT = nullptr;
void *PImpl = nullptr;
LazyValueInfo(const LazyValueInfo&) = delete;
void operator=(const LazyValueInfo&) = delete;
public:
~LazyValueInfo();
LazyValueInfo() {}
LazyValueInfo(AssumptionCache *AC_, const DataLayout *DL_, TargetLibraryInfo *TLI_,
DominatorTree *DT_)
: AC(AC_), DL(DL_), TLI(TLI_), DT(DT_) {}
LazyValueInfo(AssumptionCache *AC_, const DataLayout *DL_,
TargetLibraryInfo *TLI_)
: AC(AC_), DL(DL_), TLI(TLI_) {}
LazyValueInfo(LazyValueInfo &&Arg)
: AC(Arg.AC), DL(Arg.DL), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) {
: AC(Arg.AC), DL(Arg.DL), TLI(Arg.TLI), PImpl(Arg.PImpl) {
Arg.PImpl = nullptr;
}
LazyValueInfo &operator=(LazyValueInfo &&Arg) {
@ -52,7 +51,6 @@ public:
AC = Arg.AC;
DL = Arg.DL;
TLI = Arg.TLI;
DT = Arg.DT;
PImpl = Arg.PImpl;
Arg.PImpl = nullptr;
return *this;
@ -110,17 +108,9 @@ public:
/// Print the \LazyValueInfo Analysis.
/// We pass in the DTree that is required for identifying which basic blocks
/// we can solve/print for, in the LVIPrinter. The DT is optional
/// in LVI, so we need to pass it here as an argument.
/// we can solve/print for, in the LVIPrinter.
void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS);
/// Disables use of the DominatorTree within LVI.
void disableDT();
/// Enables use of the DominatorTree within LVI. Does nothing if the class
/// instance was initialized without a DT pointer.
void enableDT();
// For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
void releaseMemory();

View File

@ -348,9 +348,7 @@ class LazyValueInfoImpl;
class LazyValueInfoAnnotatedWriter : public AssemblyAnnotationWriter {
LazyValueInfoImpl *LVIImpl;
// While analyzing which blocks we can solve values for, we need the dominator
// information. Since this is an optional parameter in LVI, we require this
// DomTreeAnalysis pass in the printer pass, and pass the dominator
// tree to the LazyValueInfoAnnotatedWriter.
// information.
DominatorTree &DT;
public:
@ -395,8 +393,6 @@ namespace {
AssumptionCache *AC; ///< A pointer to the cache of @llvm.assume calls.
const DataLayout &DL; ///< A mandatory DataLayout
DominatorTree *DT; ///< An optional DT pointer.
DominatorTree *DisabledDT; ///< Stores DT if it's disabled.
Optional<ValueLatticeElement> getBlockValue(Value *Val, BasicBlock *BB);
Optional<ValueLatticeElement> getEdgeValue(Value *V, BasicBlock *F,
@ -471,30 +467,12 @@ namespace {
TheCache.eraseBlock(BB);
}
/// Disables use of the DominatorTree within LVI.
void disableDT() {
if (DT) {
assert(!DisabledDT && "Both DT and DisabledDT are not nullptr!");
std::swap(DT, DisabledDT);
}
}
/// Enables use of the DominatorTree within LVI. Does nothing if the class
/// instance was initialized without a DT pointer.
void enableDT() {
if (DisabledDT) {
assert(!DT && "Both DT and DisabledDT are not nullptr!");
std::swap(DT, DisabledDT);
}
}
/// This is the update interface to inform the cache that an edge from
/// PredBB to OldSucc has been threaded to be from PredBB to NewSucc.
void threadEdge(BasicBlock *PredBB,BasicBlock *OldSucc,BasicBlock *NewSucc);
LazyValueInfoImpl(AssumptionCache *AC, const DataLayout &DL,
DominatorTree *DT = nullptr)
: AC(AC), DL(DL), DT(DT), DisabledDT(nullptr) {}
LazyValueInfoImpl(AssumptionCache *AC, const DataLayout &DL)
: AC(AC), DL(DL) {}
};
} // end anonymous namespace
@ -1546,11 +1524,10 @@ void LazyValueInfoImpl::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
/// This lazily constructs the LazyValueInfoImpl.
static LazyValueInfoImpl &getImpl(void *&PImpl, AssumptionCache *AC,
const DataLayout *DL,
DominatorTree *DT = nullptr) {
const DataLayout *DL) {
if (!PImpl) {
assert(DL && "getCache() called with a null DataLayout");
PImpl = new LazyValueInfoImpl(AC, *DL, DT);
PImpl = new LazyValueInfoImpl(AC, *DL);
}
return *static_cast<LazyValueInfoImpl*>(PImpl);
}
@ -1558,14 +1535,10 @@ static LazyValueInfoImpl &getImpl(void *&PImpl, AssumptionCache *AC,
bool LazyValueInfoWrapperPass::runOnFunction(Function &F) {
Info.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
const DataLayout &DL = F.getParent()->getDataLayout();
DominatorTreeWrapperPass *DTWP =
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
Info.DT = DTWP ? &DTWP->getDomTree() : nullptr;
Info.TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
if (Info.PImpl)
getImpl(Info.PImpl, Info.AC, &DL, Info.DT).clear();
getImpl(Info.PImpl, Info.AC, &DL).clear();
// Fully lazy.
return false;
@ -1594,8 +1567,7 @@ bool LazyValueInfo::invalidate(Function &F, const PreservedAnalyses &PA,
// We need to invalidate if we have either failed to preserve this analyses
// result directly or if any of its dependencies have been invalidated.
auto PAC = PA.getChecker<LazyValueAnalysis>();
if (!(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) ||
(DT && Inv.invalidate<DominatorTreeAnalysis>(F, PA)))
if (!(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()))
return true;
return false;
@ -1607,9 +1579,8 @@ LazyValueInfo LazyValueAnalysis::run(Function &F,
FunctionAnalysisManager &FAM) {
auto &AC = FAM.getResult<AssumptionAnalysis>(F);
auto &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
return LazyValueInfo(&AC, &F.getParent()->getDataLayout(), &TLI, DT);
return LazyValueInfo(&AC, &F.getParent()->getDataLayout(), &TLI);
}
/// Returns true if we can statically tell that this value will never be a
@ -1634,7 +1605,7 @@ Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB,
const DataLayout &DL = BB->getModule()->getDataLayout();
ValueLatticeElement Result =
getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
getImpl(PImpl, AC, &DL).getValueInBlock(V, BB, CxtI);
if (Result.isConstant())
return Result.getConstant();
@ -1653,7 +1624,7 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, BasicBlock *BB,
unsigned Width = V->getType()->getIntegerBitWidth();
const DataLayout &DL = BB->getModule()->getDataLayout();
ValueLatticeElement Result =
getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
getImpl(PImpl, AC, &DL).getValueInBlock(V, BB, CxtI);
if (Result.isUnknown())
return ConstantRange::getEmpty(Width);
if (Result.isConstantRange(UndefAllowed))
@ -1672,7 +1643,7 @@ Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB,
Instruction *CxtI) {
const DataLayout &DL = FromBB->getModule()->getDataLayout();
ValueLatticeElement Result =
getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI);
getImpl(PImpl, AC, &DL).getValueOnEdge(V, FromBB, ToBB, CxtI);
if (Result.isConstant())
return Result.getConstant();
@ -1691,7 +1662,7 @@ ConstantRange LazyValueInfo::getConstantRangeOnEdge(Value *V,
unsigned Width = V->getType()->getIntegerBitWidth();
const DataLayout &DL = FromBB->getModule()->getDataLayout();
ValueLatticeElement Result =
getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI);
getImpl(PImpl, AC, &DL).getValueOnEdge(V, FromBB, ToBB, CxtI);
if (Result.isUnknown())
return ConstantRange::getEmpty(Width);
@ -1777,7 +1748,7 @@ LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
Instruction *CxtI) {
const DataLayout &DL = FromBB->getModule()->getDataLayout();
ValueLatticeElement Result =
getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI);
getImpl(PImpl, AC, &DL).getValueOnEdge(V, FromBB, ToBB, CxtI);
return getPredicateResult(Pred, C, Result, DL, TLI);
}
@ -1797,7 +1768,7 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
else if (Pred == ICmpInst::ICMP_NE)
return LazyValueInfo::True;
}
ValueLatticeElement Result = getImpl(PImpl, AC, &DL, DT).getValueAt(V, CxtI);
ValueLatticeElement Result = getImpl(PImpl, AC, &DL).getValueAt(V, CxtI);
Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI);
if (Ret != Unknown)
return Ret;
@ -1887,34 +1858,24 @@ void LazyValueInfo::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
BasicBlock *NewSucc) {
if (PImpl) {
const DataLayout &DL = PredBB->getModule()->getDataLayout();
getImpl(PImpl, AC, &DL, DT).threadEdge(PredBB, OldSucc, NewSucc);
getImpl(PImpl, AC, &DL).threadEdge(PredBB, OldSucc, NewSucc);
}
}
void LazyValueInfo::eraseBlock(BasicBlock *BB) {
if (PImpl) {
const DataLayout &DL = BB->getModule()->getDataLayout();
getImpl(PImpl, AC, &DL, DT).eraseBlock(BB);
getImpl(PImpl, AC, &DL).eraseBlock(BB);
}
}
void LazyValueInfo::printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS) {
if (PImpl) {
getImpl(PImpl, AC, DL, DT).printLVI(F, DTree, OS);
getImpl(PImpl, AC, DL).printLVI(F, DTree, OS);
}
}
void LazyValueInfo::disableDT() {
if (PImpl)
getImpl(PImpl, AC, DL, DT).disableDT();
}
void LazyValueInfo::enableDT() {
if (PImpl)
getImpl(PImpl, AC, DL, DT).enableDT();
}
// Print the LVI for the function arguments at the start of each basic block.
void LazyValueInfoAnnotatedWriter::emitBasicBlockStartAnnot(
const BasicBlock *BB, formatted_raw_ostream &OS) {

View File

@ -298,8 +298,6 @@ bool JumpThreading::runOnFunction(Function &F) {
if (skipFunction(F))
return false;
auto TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
// Get DT analysis before LVI. When LVI is initialized it conditionally adds
// DT if it's available.
auto DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
auto LVI = &getAnalysis<LazyValueInfoWrapperPass>().getLVI();
auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
@ -316,7 +314,7 @@ bool JumpThreading::runOnFunction(Function &F) {
std::move(BFI), std::move(BPI));
if (PrintLVIAfterJumpThreading) {
dbgs() << "LVI for function '" << F.getName() << "':\n";
LVI->printLVI(F, *DT, dbgs());
LVI->printLVI(F, DTU.getDomTree(), dbgs());
}
return Changed;
}
@ -324,8 +322,6 @@ bool JumpThreading::runOnFunction(Function &F) {
PreservedAnalyses JumpThreadingPass::run(Function &F,
FunctionAnalysisManager &AM) {
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
// Get DT analysis before LVI. When LVI is initialized it conditionally adds
// DT if it's available.
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
auto &LVI = AM.getResult<LazyValueAnalysis>(F);
auto &AA = AM.getResult<AAManager>(F);
@ -454,9 +450,6 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
} while (Changed);
LoopHeaders.clear();
// Flush only the Dominator Tree.
DTU->getDomTree();
LVI->enableDT();
return EverChanged;
}
@ -645,11 +638,6 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessorsImpl(
// able to handle value inequalities better, for example if the compare is
// "X < 4" and "X < 3" is known true but "X < 4" itself is not available.
// Perhaps getConstantOnEdge should be smart enough to do this?
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
for (BasicBlock *P : predecessors(BB)) {
// If the value is known by LazyValueInfo to be a constant in a
// predecessor, use that information to try to thread this block.
@ -663,10 +651,6 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessorsImpl(
/// If I is a PHI node, then we know the incoming values for any constants.
if (PHINode *PN = dyn_cast<PHINode>(I)) {
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
Value *InVal = PN->getIncomingValue(i);
if (Constant *KC = getKnownConstant(InVal, Preference)) {
@ -797,10 +781,6 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessorsImpl(
const DataLayout &DL = PN->getModule()->getDataLayout();
// We can do this simplification if any comparisons fold to true or false.
// See if any do.
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
BasicBlock *PredBB = PN->getIncomingBlock(i);
Value *LHS, *RHS;
@ -844,10 +824,6 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessorsImpl(
if (!isa<Instruction>(CmpLHS) ||
cast<Instruction>(CmpLHS)->getParent() != BB) {
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
for (BasicBlock *P : predecessors(BB)) {
// If the value is known by LazyValueInfo to be a constant in a
// predecessor, use that information to try to thread this block.
@ -876,10 +852,6 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessorsImpl(
match(CmpLHS, m_Add(m_Value(AddLHS), m_ConstantInt(AddConst)))) {
if (!isa<Instruction>(AddLHS) ||
cast<Instruction>(AddLHS)->getParent() != BB) {
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
for (BasicBlock *P : predecessors(BB)) {
// If the value is known by LazyValueInfo to be a ConstantRange in
// a predecessor, use that information to try to thread this
@ -961,10 +933,6 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessorsImpl(
}
// If all else fails, see if LVI can figure out a constant value for us.
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
Constant *CI = LVI->getConstant(V, BB, CxtI);
if (Constant *KC = getKnownConstant(CI, Preference)) {
for (BasicBlock *Pred : predecessors(BB))
@ -1124,10 +1092,6 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
// threading is concerned.
assert(CondBr->isConditional() && "Threading on unconditional terminator");
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
LazyValueInfo::Tristate Ret =
LVI->getPredicateAt(CondCmp->getPredicate(), CondCmp->getOperand(0),
CondConst, CondBr);
@ -1581,10 +1545,6 @@ Constant *JumpThreadingPass::EvaluateOnPredecessorEdge(BasicBlock *BB,
// Consult LVI if V is not an instruction in BB or PredBB.
Instruction *I = dyn_cast<Instruction>(V);
if (!I || (I->getParent() != BB && I->getParent() != PredBB)) {
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
return LVI->getConstantOnEdge(V, PredPredBB, PredBB, nullptr);
}
@ -2345,10 +2305,6 @@ void JumpThreadingPass::ThreadEdge(BasicBlock *BB,
<< "' to '" << SuccBB->getName()
<< ", across block:\n " << *BB << "\n");
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
LVI->threadEdge(PredBB, BB, SuccBB);
BasicBlock *NewBB = BasicBlock::Create(BB->getContext(),
@ -2791,10 +2747,6 @@ bool JumpThreadingPass::TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB) {
// Now check if one of the select values would allow us to constant fold the
// terminator in BB. We don't do the transform if both sides fold, those
// cases will be threaded in any case.
if (DTU->hasPendingDomTreeUpdates())
LVI->disableDT();
else
LVI->enableDT();
LazyValueInfo::Tristate LHSFolds =
LVI->getPredicateOnEdge(CondCmp->getPredicate(), SI->getOperand(1),
CondRHS, Pred, BB, CondCmp);

View File

@ -148,13 +148,6 @@ bool LowerSwitch::runOnFunction(Function &F) {
LazyValueInfo *LVI = &getAnalysis<LazyValueInfoWrapperPass>().getLVI();
auto *ACT = getAnalysisIfAvailable<AssumptionCacheTracker>();
AssumptionCache *AC = ACT ? &ACT->getAssumptionCache(F) : nullptr;
// Prevent LazyValueInfo from using the DominatorTree as LowerSwitch does not
// preserve it and it becomes stale (when available) pretty much immediately.
// Currently the DominatorTree is only used by LowerSwitch indirectly via LVI
// and computeKnownBits to refine isValidAssumeForContext's results. Given
// that the latter can handle some of the simple cases w/o a DominatorTree,
// it's easier to refrain from using the tree than to keep it up to date.
LVI->disableDT();
bool Changed = false;
SmallPtrSet<BasicBlock*, 8> DeleteList;

View File

@ -12,18 +12,6 @@
; CHECK-INVALIDATE: Invalidating analysis: LazyValueAnalysis
; CHECK-INVALIDATE: Running pass: RequireAnalysisPass
; CHECK-INVALIDATE: Running analysis: LazyValueAnalysis
;
; Check DomTree specifically.
; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
; RUN: -passes='require<domtree>,require<lazy-value-info>,invalidate<domtree>,require<lazy-value-info>' \
; RUN: | FileCheck %s --check-prefix=CHECK-DT-INVALIDATE
; CHECK-DT-INVALIDATE: Running pass: RequireAnalysisPass
; CHECK-DT-INVALIDATE: Running analysis: LazyValueAnalysis
; CHECK-DT-INVALIDATE: Running pass: InvalidateAnalysisPass
; CHECK-DT-INVALIDATE: Invalidating analysis: DominatorTreeAnalysis
; CHECK-DT-INVALIDATE: Invalidating analysis: LazyValueAnalysis
; CHECK-AC-INVALIDATE: Running pass: RequireAnalysisPass
; CHECK-DT-INVALIDATE: Running analysis: LazyValueAnalysis
target triple = "x86_64-unknown-linux-gnu"