Index: llvm/include/llvm/Analysis/LoopInfo.h =================================================================== --- llvm/include/llvm/Analysis/LoopInfo.h +++ llvm/include/llvm/Analysis/LoopInfo.h @@ -286,6 +286,11 @@ /// Return all blocks inside the loop that have successors outside of the /// loop. These are the blocks _inside of the current loop_ which branch out. /// The returned list is always unique. + /// + /// Only finds 2 when StopAfterFindingTwo is true to speed up code looking + /// for unique instances. + /// + template void getExitingBlocks(SmallVectorImpl &ExitingBlocks) const; /// If getExitingBlocks would return exactly one block, return that block. @@ -294,6 +299,11 @@ /// Return all of the successor blocks of this loop. These are the blocks /// _outside of the current loop_ which are branched to. + /// + /// Only finds 2 when StopAfterFindingTwo is true to speed up code looking + /// for unique instances. + /// + template void getExitBlocks(SmallVectorImpl &ExitBlocks) const; /// If getExitBlocks would return exactly one block, return that block. @@ -306,6 +316,11 @@ /// Return all unique successor blocks of this loop. /// These are the blocks _outside of the current loop_ which are branched to. + /// + /// Only finds 2 when StopAfterFindingTwo is true to speed up code looking + /// for unique instances. + /// + template void getUniqueExitBlocks(SmallVectorImpl &ExitBlocks) const; /// Return all unique successor blocks of this loop except successors from @@ -1390,6 +1405,14 @@ llvm::ArrayRef RemovePrefixes, llvm::ArrayRef AddAttrs); +extern template void llvm::LoopBase::getExitingBlocks( + SmallVectorImpl &ExitingBlocks) const; +extern template void llvm::LoopBase::getExitBlocks( + SmallVectorImpl &ExitBlocks) const; +extern template void +llvm::LoopBase::getUniqueExitBlocks( + SmallVectorImpl &ExitBlocks) const; + } // End llvm namespace #endif Index: llvm/include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- llvm/include/llvm/Analysis/LoopInfoImpl.h +++ llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -29,17 +29,25 @@ /// outside of the loop. These are the blocks _inside of the current loop_ /// which branch out. The returned list is always unique. /// +/// Only finds 2 when StopAfterFindingTwo is true to speed up code looking +/// for unique instances. +/// template +template void LoopBase::getExitingBlocks( SmallVectorImpl &ExitingBlocks) const { assert(!isInvalid() && "Loop not in a valid state!"); for (const auto BB : blocks()) - for (auto *Succ : children(BB)) + for (auto *Succ : children(BB)) { + if (StopAfterFindingTwo && ExitingBlocks.size() >= 2) + // short cut when looking for unique items + return; if (!contains(Succ)) { // Not in current loop? It must be an exit block. ExitingBlocks.push_back(BB); break; } + } } /// getExitingBlock - If getExitingBlocks would return exactly one block, @@ -47,8 +55,8 @@ template BlockT *LoopBase::getExitingBlock() const { assert(!isInvalid() && "Loop not in a valid state!"); - SmallVector ExitingBlocks; - getExitingBlocks(ExitingBlocks); + SmallVector ExitingBlocks; + getExitingBlocks(ExitingBlocks); if (ExitingBlocks.size() == 1) return ExitingBlocks[0]; return nullptr; @@ -57,15 +65,23 @@ /// getExitBlocks - Return all of the successor blocks of this loop. These /// are the blocks _outside of the current loop_ which are branched to. /// +/// Only finds 2 when StopAfterFindingTwo is true to speed up code looking +/// for unique instances. +/// template +template void LoopBase::getExitBlocks( SmallVectorImpl &ExitBlocks) const { assert(!isInvalid() && "Loop not in a valid state!"); for (const auto BB : blocks()) - for (auto *Succ : children(BB)) + for (auto *Succ : children(BB)) { + if (StopAfterFindingTwo && ExitBlocks.size() >= 2) + // short cut when looking for unique items + return; if (!contains(Succ)) // Not in current loop? It must be an exit block. ExitBlocks.push_back(Succ); + } } template @@ -80,8 +96,8 @@ template BlockT *LoopBase::getExitBlock() const { assert(!isInvalid() && "Loop not in a valid state!"); - SmallVector ExitBlocks; - getExitBlocks(ExitBlocks); + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); if (ExitBlocks.size() == 1) return ExitBlocks[0]; return nullptr; @@ -103,7 +119,11 @@ // Helper function to get unique loop exits. Pred is a predicate pointing to // BasicBlocks in a loop which should be considered to find loop exits. -template +// Only finds 2 when StopAfterFindingTwo is true to speed up code looking +// for unique instances. +// +template void getUniqueExitBlocksHelper(const LoopT *L, SmallVectorImpl &ExitBlocks, PredicateT Pred) { @@ -111,17 +131,25 @@ SmallPtrSet Visited; auto Filtered = make_filter_range(L->blocks(), Pred); for (BlockT *BB : Filtered) - for (BlockT *Successor : children(BB)) + for (BlockT *Successor : children(BB)) { + if (StopAfterFindingTwo && ExitBlocks.size() >= 2) + // short cut when looking for unique items + return; if (!L->contains(Successor)) if (Visited.insert(Successor).second) ExitBlocks.push_back(Successor); + } } +/// Only finds 2 when StopAfterFindingTwo is true to speed up code looking +/// for unique instances. +/// template +template void LoopBase::getUniqueExitBlocks( SmallVectorImpl &ExitBlocks) const { - getUniqueExitBlocksHelper(this, ExitBlocks, - [](const BlockT *BB) { return true; }); + getUniqueExitBlocksHelper( + this, ExitBlocks, [](const BlockT *BB) { return true; }); } template @@ -129,14 +157,14 @@ SmallVectorImpl &ExitBlocks) const { const BlockT *Latch = getLoopLatch(); assert(Latch && "Latch block must exists"); - getUniqueExitBlocksHelper(this, ExitBlocks, - [Latch](const BlockT *BB) { return BB != Latch; }); + getUniqueExitBlocksHelper( + this, ExitBlocks, [Latch](const BlockT *BB) { return BB != Latch; }); } template BlockT *LoopBase::getUniqueExitBlock() const { - SmallVector UniqueExitBlocks; - getUniqueExitBlocks(UniqueExitBlocks); + SmallVector UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); if (UniqueExitBlocks.size() == 1) return UniqueExitBlocks[0]; return nullptr; Index: llvm/include/llvm/CodeGen/MachineLoopInfo.h =================================================================== --- llvm/include/llvm/CodeGen/MachineLoopInfo.h +++ llvm/include/llvm/CodeGen/MachineLoopInfo.h @@ -199,6 +199,10 @@ static ChildIteratorType child_end(NodeRef N) { return N->end(); } }; +extern template void +llvm::LoopBase::getExitingBlocks( + SmallVectorImpl &ExitingBlocks) const; + } // end namespace llvm #endif // LLVM_CODEGEN_MACHINELOOPINFO_H Index: llvm/lib/Analysis/LoopInfo.cpp =================================================================== --- llvm/lib/Analysis/LoopInfo.cpp +++ llvm/lib/Analysis/LoopInfo.cpp @@ -42,6 +42,12 @@ // Explicitly instantiate methods in LoopInfoImpl.h for IR-level Loops. template class llvm::LoopBase; template class llvm::LoopInfoBase; +template void llvm::LoopBase::getExitingBlocks( + SmallVectorImpl &ExitingBlocks) const; +template void llvm::LoopBase::getExitBlocks( + SmallVectorImpl &ExitBlocks) const; +template void llvm::LoopBase::getUniqueExitBlocks( + SmallVectorImpl &ExitBlocks) const; // Always verify loopinfo if expensive checking is enabled. #ifdef EXPENSIVE_CHECKS Index: llvm/lib/CodeGen/MachineLoopInfo.cpp =================================================================== --- llvm/lib/CodeGen/MachineLoopInfo.cpp +++ llvm/lib/CodeGen/MachineLoopInfo.cpp @@ -29,6 +29,9 @@ // Explicitly instantiate methods in LoopInfoImpl.h for MI-level Loops. template class llvm::LoopBase; template class llvm::LoopInfoBase; +template void +llvm::LoopBase::getExitingBlocks( + SmallVectorImpl &ExitingBlocks) const; char MachineLoopInfo::ID = 0; MachineLoopInfo::MachineLoopInfo() : MachineFunctionPass(ID) {