зеркало из https://github.com/mozilla/gecko-dev.git
309 строки
11 KiB
Diff
309 строки
11 KiB
Diff
From 3dd7de023be43bca7d6d45140e4fde42e22bc336 Mon Sep 17 00:00:00 2001
|
|
From: "Brian M. Rzycki" <brzycki@gmail.com>
|
|
Date: Fri, 16 Feb 2018 16:35:17 +0000
|
|
Subject: [PATCH 2/2] [JumpThreading] PR36133 enable/disable DominatorTree for
|
|
LVI analysis
|
|
|
|
Summary:
|
|
The LazyValueInfo pass caches a copy of the DominatorTree when available.
|
|
Whenever there are pending DominatorTree updates within JumpThreading's
|
|
DeferredDominance object we cannot use the cached DT for LVI analysis.
|
|
This commit adds the new methods enableDT() and disableDT() to LVI.
|
|
JumpThreading also sets the appropriate usage model before calling LVI
|
|
analysis methods.
|
|
|
|
Fixes https://bugs.llvm.org/show_bug.cgi?id=36133
|
|
|
|
Reviewers: sebpop, dberlin, kuhar
|
|
|
|
Reviewed by: sebpop, kuhar
|
|
|
|
Subscribers: uabelho, llvm-commits, aprantl, hiraditya, a.elovikov
|
|
|
|
Differential Revision: https://reviews.llvm.org/D42717
|
|
|
|
|
|
|
|
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325356 91177308-0d34-0410-b5e6-96231b3b80d8
|
|
---
|
|
include/llvm/Analysis/LazyValueInfo.h | 7 ++++
|
|
include/llvm/IR/Dominators.h | 3 ++
|
|
lib/Analysis/LazyValueInfo.cpp | 30 +++++++++++++++-
|
|
lib/IR/Dominators.cpp | 3 ++
|
|
lib/Transforms/Scalar/JumpThreading.cpp | 37 ++++++++++++++++++++
|
|
test/Transforms/JumpThreading/pr36133.ll | 44 ++++++++++++++++++++++++
|
|
6 files changed, 123 insertions(+), 1 deletion(-)
|
|
create mode 100644 test/Transforms/JumpThreading/pr36133.ll
|
|
|
|
diff --git a/llvm/include/llvm/Analysis/LazyValueInfo.h b/llvm/include/llvm/Analysis/LazyValueInfo.h
|
|
index 787c88cc6ec..cea5bf0df80 100644
|
|
--- a/llvm/include/llvm/Analysis/LazyValueInfo.h
|
|
+++ b/llvm/include/llvm/Analysis/LazyValueInfo.h
|
|
@@ -113,6 +113,13 @@ public:
|
|
/// in LVI, so we need to pass it here as an argument.
|
|
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();
|
|
|
|
diff --git a/llvm/include/llvm/IR/Dominators.h b/llvm/include/llvm/IR/Dominators.h
|
|
index c5373376ade..ccb18527abc 100644
|
|
--- a/llvm/include/llvm/IR/Dominators.h
|
|
+++ b/llvm/include/llvm/IR/Dominators.h
|
|
@@ -342,6 +342,9 @@ public:
|
|
/// \brief Returns true if DelBB is awaiting deletion at a flush() event.
|
|
bool pendingDeletedBB(BasicBlock *DelBB);
|
|
|
|
+ /// \brief Returns true if pending DT updates are queued for a flush() event.
|
|
+ bool pending();
|
|
+
|
|
/// \brief Flushes all pending updates and block deletions. Returns a
|
|
/// correct DominatorTree reference to be used by the caller for analysis.
|
|
DominatorTree &flush();
|
|
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
|
|
index d7da669f6e7..fcbfb08cf1d 100644
|
|
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
|
|
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
|
|
@@ -401,6 +401,7 @@ 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.
|
|
|
|
ValueLatticeElement getBlockValue(Value *Val, BasicBlock *BB);
|
|
bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T,
|
|
@@ -463,13 +464,30 @@ 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) {}
|
|
+ : AC(AC), DL(DL), DT(DT), DisabledDT(nullptr) {}
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
@@ -1791,6 +1809,16 @@ void LazyValueInfo::printLVI(Function &F, DominatorTree &DTree, raw_ostream &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) {
|
|
diff --git a/llvm/lib/IR/Dominators.cpp b/llvm/lib/IR/Dominators.cpp
|
|
index e44e845b324..5efd0df5db9 100644
|
|
--- a/llvm/lib/IR/Dominators.cpp
|
|
+++ b/llvm/lib/IR/Dominators.cpp
|
|
@@ -453,6 +453,9 @@ bool DeferredDominance::pendingDeletedBB(BasicBlock *DelBB) {
|
|
return DeletedBBs.count(DelBB) != 0;
|
|
}
|
|
|
|
+/// \brief Returns true if pending DT updates are queued for a flush() event.
|
|
+bool DeferredDominance::pending() { return !PendUpdates.empty(); }
|
|
+
|
|
/// \brief Flushes all pending updates and block deletions. Returns a
|
|
/// correct DominatorTree reference to be used by the caller for analysis.
|
|
DominatorTree &DeferredDominance::flush() {
|
|
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
|
|
index 4d366e8e392..9ff91cf4924 100644
|
|
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
|
|
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
|
|
@@ -425,6 +425,7 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
|
|
|
|
LoopHeaders.clear();
|
|
DDT->flush();
|
|
+ LVI->enableDT();
|
|
return EverChanged;
|
|
}
|
|
|
|
@@ -617,6 +618,10 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors(
|
|
// "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 (DDT->pending())
|
|
+ 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.
|
|
@@ -630,6 +635,10 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors(
|
|
|
|
/// If I is a PHI node, then we know the incoming values for any constants.
|
|
if (PHINode *PN = dyn_cast<PHINode>(I)) {
|
|
+ if (DDT->pending())
|
|
+ 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)) {
|
|
@@ -759,6 +768,10 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors(
|
|
const DataLayout &DL = PN->getModule()->getDataLayout();
|
|
// We can do this simplification if any comparisons fold to true or false.
|
|
// See if any do.
|
|
+ if (DDT->pending())
|
|
+ LVI->disableDT();
|
|
+ else
|
|
+ LVI->enableDT();
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
|
BasicBlock *PredBB = PN->getIncomingBlock(i);
|
|
Value *LHS = PN->getIncomingValue(i);
|
|
@@ -792,6 +805,10 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors(
|
|
|
|
if (!isa<Instruction>(CmpLHS) ||
|
|
cast<Instruction>(CmpLHS)->getParent() != BB) {
|
|
+ if (DDT->pending())
|
|
+ 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.
|
|
@@ -820,6 +837,10 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors(
|
|
match(CmpLHS, m_Add(m_Value(AddLHS), m_ConstantInt(AddConst)))) {
|
|
if (!isa<Instruction>(AddLHS) ||
|
|
cast<Instruction>(AddLHS)->getParent() != BB) {
|
|
+ if (DDT->pending())
|
|
+ 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
|
|
@@ -901,6 +922,10 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors(
|
|
}
|
|
|
|
// If all else fails, see if LVI can figure out a constant value for us.
|
|
+ if (DDT->pending())
|
|
+ LVI->disableDT();
|
|
+ else
|
|
+ LVI->enableDT();
|
|
Constant *CI = LVI->getConstant(V, BB, CxtI);
|
|
if (Constant *KC = getKnownConstant(CI, Preference)) {
|
|
for (BasicBlock *Pred : predecessors(BB))
|
|
@@ -1102,6 +1127,10 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
|
|
// threading is concerned.
|
|
assert(CondBr->isConditional() && "Threading on unconditional terminator");
|
|
|
|
+ if (DDT->pending())
|
|
+ LVI->disableDT();
|
|
+ else
|
|
+ LVI->enableDT();
|
|
LazyValueInfo::Tristate Ret =
|
|
LVI->getPredicateAt(CondCmp->getPredicate(), CondCmp->getOperand(0),
|
|
CondConst, CondBr);
|
|
@@ -1899,6 +1928,10 @@ bool JumpThreadingPass::ThreadEdge(BasicBlock *BB,
|
|
<< ", across block:\n "
|
|
<< *BB << "\n");
|
|
|
|
+ if (DDT->pending())
|
|
+ LVI->disableDT();
|
|
+ else
|
|
+ LVI->enableDT();
|
|
LVI->threadEdge(PredBB, BB, SuccBB);
|
|
|
|
// We are going to have to map operands from the original BB block to the new
|
|
@@ -2368,6 +2401,10 @@ 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 (DDT->pending())
|
|
+ LVI->disableDT();
|
|
+ else
|
|
+ LVI->enableDT();
|
|
LazyValueInfo::Tristate LHSFolds =
|
|
LVI->getPredicateOnEdge(CondCmp->getPredicate(), SI->getOperand(1),
|
|
CondRHS, Pred, BB, CondCmp);
|
|
diff --git a/llvm/test/Transforms/JumpThreading/pr36133.ll b/llvm/test/Transforms/JumpThreading/pr36133.ll
|
|
new file mode 100644
|
|
index 00000000000..b8d8c5fac46
|
|
--- /dev/null
|
|
+++ b/llvm/test/Transforms/JumpThreading/pr36133.ll
|
|
@@ -0,0 +1,44 @@
|
|
+; RUN: opt -jump-threading -S < %s | FileCheck %s
|
|
+@global = external global i8*, align 8
|
|
+
|
|
+define i32 @foo(i32 %arg) {
|
|
+; CHECK-LABEL: @foo
|
|
+; CHECK-LABEL: bb:
|
|
+; CHECK: icmp eq
|
|
+; CHECK-NEXT: br i1 %tmp1, label %bb7, label %bb7
|
|
+bb:
|
|
+ %tmp = load i8*, i8** @global, align 8
|
|
+ %tmp1 = icmp eq i8* %tmp, null
|
|
+ br i1 %tmp1, label %bb3, label %bb2
|
|
+
|
|
+; CHECK-NOT: bb2:
|
|
+bb2:
|
|
+ br label %bb3
|
|
+
|
|
+; CHECK-NOT: bb3:
|
|
+bb3:
|
|
+ %tmp4 = phi i8 [ 1, %bb2 ], [ 0, %bb ]
|
|
+ %tmp5 = icmp eq i8 %tmp4, 0
|
|
+ br i1 %tmp5, label %bb7, label %bb6
|
|
+
|
|
+; CHECK-NOT: bb6:
|
|
+bb6:
|
|
+ br label %bb7
|
|
+
|
|
+; CHECK-LABEL: bb7:
|
|
+bb7:
|
|
+ %tmp8 = icmp eq i32 %arg, -1
|
|
+ br i1 %tmp8, label %bb9, label %bb10
|
|
+
|
|
+; CHECK-LABEL: bb9:
|
|
+bb9:
|
|
+ ret i32 0
|
|
+
|
|
+; CHECK-LABEL: bb10:
|
|
+bb10:
|
|
+ %tmp11 = icmp sgt i32 %arg, -1
|
|
+ call void @llvm.assume(i1 %tmp11)
|
|
+ ret i32 1
|
|
+}
|
|
+
|
|
+declare void @llvm.assume(i1)
|
|
--
|
|
2.18.0
|
|
|