Index: llvm/trunk/include/llvm/Analysis/LazyValueInfo.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LazyValueInfo.h +++ llvm/trunk/include/llvm/Analysis/LazyValueInfo.h @@ -113,6 +113,13 @@ /// 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(); Index: llvm/trunk/include/llvm/IR/Dominators.h =================================================================== --- llvm/trunk/include/llvm/IR/Dominators.h +++ llvm/trunk/include/llvm/IR/Dominators.h @@ -335,6 +335,9 @@ /// \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(); Index: llvm/trunk/lib/Analysis/LazyValueInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LazyValueInfo.cpp +++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp @@ -401,6 +401,7 @@ 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 @@ 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::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) { Index: llvm/trunk/lib/IR/Dominators.cpp =================================================================== --- llvm/trunk/lib/IR/Dominators.cpp +++ llvm/trunk/lib/IR/Dominators.cpp @@ -448,6 +448,9 @@ 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() { Index: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp +++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp @@ -425,6 +425,7 @@ LoopHeaders.clear(); DDT->flush(); + LVI->enableDT(); return EverChanged; } @@ -617,6 +618,10 @@ // "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 @@ /// If I is a PHI node, then we know the incoming values for any constants. if (PHINode *PN = dyn_cast(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 @@ 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 @@ if (!isa(CmpLHS) || cast(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 @@ match(CmpLHS, m_Add(m_Value(AddLHS), m_ConstantInt(AddConst)))) { if (!isa(AddLHS) || cast(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 @@ } // 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 @@ // 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); @@ -1902,6 +1931,10 @@ << ", 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 @@ -2371,6 +2404,10 @@ // 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); Index: llvm/trunk/test/Transforms/JumpThreading/pr36133.ll =================================================================== --- llvm/trunk/test/Transforms/JumpThreading/pr36133.ll +++ llvm/trunk/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)