Index: llvm/include/llvm/Analysis/LazyValueInfo.h =================================================================== --- llvm/include/llvm/Analysis/LazyValueInfo.h +++ llvm/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/include/llvm/IR/Dominators.h =================================================================== --- llvm/include/llvm/IR/Dominators.h +++ llvm/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/lib/Analysis/LazyValueInfo.cpp =================================================================== --- llvm/lib/Analysis/LazyValueInfo.cpp +++ llvm/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) { + DisabledDT = DT; + DT = nullptr; + } + } + + /// Enables use of the DominatorTree within LVI. Does nothing if the class + /// instance was initialized without a DT pointer. + void enableDT() { + if (DisabledDT) { + DT = DisabledDT; + DisabledDT = nullptr; + } + } + /// 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/lib/IR/Dominators.cpp =================================================================== --- llvm/lib/IR/Dominators.cpp +++ llvm/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/lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -616,7 +616,8 @@ // 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 (DDT->pending()) + LVI->disableDT(); 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. @@ -624,12 +625,14 @@ if (Constant *KC = getKnownConstant(PredCst, Preference)) Result.push_back(std::make_pair(KC, P)); } - + LVI->enableDT(); return !Result.empty(); } /// 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(); for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { Value *InVal = PN->getIncomingValue(i); if (Constant *KC = getKnownConstant(InVal, Preference)) { @@ -642,7 +645,7 @@ Result.push_back(std::make_pair(KC, PN->getIncomingBlock(i))); } } - + LVI->enableDT(); return !Result.empty(); } @@ -759,6 +762,8 @@ 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(); for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { BasicBlock *PredBB = PN->getIncomingBlock(i); Value *LHS = PN->getIncomingValue(i); @@ -781,7 +786,7 @@ if (Constant *KC = getKnownConstant(Res, WantInteger)) Result.push_back(std::make_pair(KC, PredBB)); } - + LVI->enableDT(); return !Result.empty(); } @@ -792,6 +797,8 @@ if (!isa(CmpLHS) || cast(CmpLHS)->getParent() != BB) { + if (DDT->pending()) + LVI->disableDT(); 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. @@ -804,7 +811,7 @@ Constant *ResC = ConstantInt::get(CmpType, Res); Result.push_back(std::make_pair(ResC, P)); } - + LVI->enableDT(); return !Result.empty(); } @@ -820,6 +827,8 @@ match(CmpLHS, m_Add(m_Value(AddLHS), m_ConstantInt(AddConst)))) { if (!isa(AddLHS) || cast(AddLHS)->getParent() != BB) { + if (DDT->pending()) + LVI->disableDT(); 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 @@ -843,7 +852,7 @@ Result.push_back(std::make_pair(ResC, P)); } - + LVI->enableDT(); return !Result.empty(); } } @@ -901,12 +910,14 @@ } // If all else fails, see if LVI can figure out a constant value for us. + if (DDT->pending()) + LVI->disableDT(); Constant *CI = LVI->getConstant(V, BB, CxtI); if (Constant *KC = getKnownConstant(CI, Preference)) { for (BasicBlock *Pred : predecessors(BB)) Result.push_back(std::make_pair(KC, Pred)); } - + LVI->enableDT(); return !Result.empty(); } @@ -1102,9 +1113,12 @@ // threading is concerned. assert(CondBr->isConditional() && "Threading on unconditional terminator"); + if (DDT->pending()) + LVI->disableDT(); LazyValueInfo::Tristate Ret = LVI->getPredicateAt(CondCmp->getPredicate(), CondCmp->getOperand(0), CondConst, CondBr); + LVI->enableDT(); if (Ret != LazyValueInfo::Unknown) { unsigned ToRemove = Ret == LazyValueInfo::True ? 1 : 0; unsigned ToKeep = Ret == LazyValueInfo::True ? 0 : 1; @@ -1902,7 +1916,10 @@ << ", across block:\n " << *BB << "\n"); + if (DDT->pending()) + LVI->disableDT(); LVI->threadEdge(PredBB, BB, SuccBB); + LVI->enableDT(); // We are going to have to map operands from the original BB block to the new // copy of the block 'NewBB'. If there are PHI nodes in BB, evaluate them to @@ -2371,12 +2388,15 @@ // 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(); LazyValueInfo::Tristate LHSFolds = LVI->getPredicateOnEdge(CondCmp->getPredicate(), SI->getOperand(1), CondRHS, Pred, BB, CondCmp); LazyValueInfo::Tristate RHSFolds = LVI->getPredicateOnEdge(CondCmp->getPredicate(), SI->getOperand(2), CondRHS, Pred, BB, CondCmp); + LVI->enableDT(); if ((LHSFolds != LazyValueInfo::Unknown || RHSFolds != LazyValueInfo::Unknown) && LHSFolds != RHSFolds) { Index: llvm/test/Transforms/JumpThreading/pr36133.ll =================================================================== --- /dev/null +++ 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)