diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h --- a/llvm/include/llvm/IR/BasicBlock.h +++ b/llvm/include/llvm/IR/BasicBlock.h @@ -133,6 +133,15 @@ static_cast(this)->getTerminatingDeoptimizeCall()); } + /// Returns the call instruction calling \@llvm.experimental.deoptimize + /// that is present either in current basic block or in block that is a unique + /// successor to current block, if such call is present. Otherwise, returns null. + const CallInst *getPostdominatingDeoptimizeCall() const; + CallInst *getPostdominatingDeoptimizeCall() { + return const_cast( + static_cast(this)->getPostdominatingDeoptimizeCall()); + } + /// Returns the call instruction marked 'musttail' prior to the terminating /// return instruction of this basic block, if such a call is present. /// Otherwise, returns null. diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -193,6 +193,13 @@ return nullptr; } +const CallInst *BasicBlock::getPostdominatingDeoptimizeCall() const { + const BasicBlock* BB = this; + while (BB->getUniqueSuccessor()) + BB = BB->getUniqueSuccessor(); + return BB->getTerminatingDeoptimizeCall(); +} + const Instruction* BasicBlock::getFirstNonPHI() const { for (const Instruction &I : *this) if (!isa(I)) diff --git a/llvm/lib/Transforms/Scalar/LoopPredication.cpp b/llvm/lib/Transforms/Scalar/LoopPredication.cpp --- a/llvm/lib/Transforms/Scalar/LoopPredication.cpp +++ b/llvm/lib/Transforms/Scalar/LoopPredication.cpp @@ -1020,17 +1020,6 @@ return SE.getUMinFromMismatchedTypes(ExitCounts); } -/// Return true if we can be fairly sure that executing block BB will probably -/// lead to executing an __llvm_deoptimize. This is a profitability heuristic, -/// not a legality constraint. -static bool isVeryLikelyToDeopt(BasicBlock *BB) { - while (BB->getUniqueSuccessor()) - // Will skip side effects, that's okay - BB = BB->getUniqueSuccessor(); - - return BB->getTerminatingDeoptimizeCall(); -} - /// This implements an analogous, but entirely distinct transform from the main /// loop predication transform. This one is phrased in terms of using a /// widenable branch *outside* the loop to allow us to simplify loop exits in a @@ -1150,10 +1139,13 @@ const bool ExitIfTrue = !L->contains(*succ_begin(ExitingBB)); BasicBlock *ExitBB = BI->getSuccessor(ExitIfTrue ? 0 : 1); - if (!isVeryLikelyToDeopt(ExitBB)) - // Profitability: indicator of rarely/never taken exit + if (!ExitBB->getPostdominatingDeoptimizeCall()) continue; + /// Here we can be fairly sure that executing this exit will most likely + /// lead to executing llvm.experimental.deoptimize. + /// This is a profitability heuristic, not a legality constraint. + // If we found a widenable exit condition, do two things: // 1) fold the widened exit test into the widenable condition // 2) fold the branch to untaken - avoids infinite looping