summaryrefslogtreecommitdiff
path: root/include/llvm/Analysis/LoopInfoImpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Analysis/LoopInfoImpl.h')
-rw-r--r--include/llvm/Analysis/LoopInfoImpl.h85
1 files changed, 32 insertions, 53 deletions
diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h
index 2b807919fedf..4c33dac9e21e 100644
--- a/include/llvm/Analysis/LoopInfoImpl.h
+++ b/include/llvm/Analysis/LoopInfoImpl.h
@@ -1,9 +1,8 @@
//===- llvm/Analysis/LoopInfoImpl.h - Natural Loop Calculator ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -96,49 +95,36 @@ bool LoopBase<BlockT, LoopT>::hasDedicatedExits() const {
return true;
}
+// 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 <class BlockT, class LoopT, typename PredicateT>
+void getUniqueExitBlocksHelper(const LoopT *L,
+ SmallVectorImpl<BlockT *> &ExitBlocks,
+ PredicateT Pred) {
+ assert(!L->isInvalid() && "Loop not in a valid state!");
+ SmallPtrSet<BlockT *, 32> Visited;
+ auto Filtered = make_filter_range(L->blocks(), Pred);
+ for (BlockT *BB : Filtered)
+ for (BlockT *Successor : children<BlockT *>(BB))
+ if (!L->contains(Successor))
+ if (Visited.insert(Successor).second)
+ ExitBlocks.push_back(Successor);
+}
+
template <class BlockT, class LoopT>
void LoopBase<BlockT, LoopT>::getUniqueExitBlocks(
SmallVectorImpl<BlockT *> &ExitBlocks) const {
- typedef GraphTraits<BlockT *> BlockTraits;
- typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits;
-
- assert(hasDedicatedExits() &&
- "getUniqueExitBlocks assumes the loop has canonical form exits!");
-
- SmallVector<BlockT *, 32> SwitchExitBlocks;
- for (BlockT *Block : this->blocks()) {
- SwitchExitBlocks.clear();
- for (BlockT *Successor : children<BlockT *>(Block)) {
- // If block is inside the loop then it is not an exit block.
- if (contains(Successor))
- continue;
-
- BlockT *FirstPred = *InvBlockTraits::child_begin(Successor);
-
- // If current basic block is this exit block's first predecessor then only
- // insert exit block in to the output ExitBlocks vector. This ensures that
- // same exit block is not inserted twice into ExitBlocks vector.
- if (Block != FirstPred)
- continue;
-
- // If a terminator has more then two successors, for example SwitchInst,
- // then it is possible that there are multiple edges from current block to
- // one exit block.
- if (std::distance(BlockTraits::child_begin(Block),
- BlockTraits::child_end(Block)) <= 2) {
- ExitBlocks.push_back(Successor);
- continue;
- }
+ getUniqueExitBlocksHelper(this, ExitBlocks,
+ [](const BlockT *BB) { return true; });
+}
- // In case of multiple edges from current block to exit block, collect
- // only one edge in ExitBlocks. Use switchExitBlocks to keep track of
- // duplicate edges.
- if (!is_contained(SwitchExitBlocks, Successor)) {
- SwitchExitBlocks.push_back(Successor);
- ExitBlocks.push_back(Successor);
- }
- }
- }
+template <class BlockT, class LoopT>
+void LoopBase<BlockT, LoopT>::getUniqueNonLatchExitBlocks(
+ SmallVectorImpl<BlockT *> &ExitBlocks) const {
+ const BlockT *Latch = getLoopLatch();
+ assert(Latch && "Latch block must exists");
+ getUniqueExitBlocksHelper(this, ExitBlocks,
+ [Latch](const BlockT *BB) { return BB != Latch; });
}
template <class BlockT, class LoopT>
@@ -588,16 +574,9 @@ SmallVector<LoopT *, 4> LoopInfoBase<BlockT, LoopT>::getLoopsInPreorder() {
// FIXME: If we change the order of LoopInfo we will want to remove the
// reverse here.
for (LoopT *RootL : reverse(*this)) {
- assert(PreOrderWorklist.empty() &&
- "Must start with an empty preorder walk worklist.");
- PreOrderWorklist.push_back(RootL);
- do {
- LoopT *L = PreOrderWorklist.pop_back_val();
- // Sub-loops are stored in forward program order, but will process the
- // worklist backwards so append them in reverse order.
- PreOrderWorklist.append(L->rbegin(), L->rend());
- PreOrderLoops.push_back(L);
- } while (!PreOrderWorklist.empty());
+ auto PreOrderLoopsInRootL = RootL->getLoopsInPreorder();
+ PreOrderLoops.append(PreOrderLoopsInRootL.begin(),
+ PreOrderLoopsInRootL.end());
}
return PreOrderLoops;