aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Analysis/LoopInfo.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-09-03 16:10:48 +0000
committerDan Gohman <gohman@apple.com>2009-09-03 16:10:48 +0000
commit5c42c875f7b8a18b3f3945bf52bbab2fa59450c3 (patch)
treed8fd5fff1d3c220a5f19e8894d86b901f4b48a74 /lib/Analysis/LoopInfo.cpp
parentfb17470d7382d820c535988315c65da4e9de0b48 (diff)
downloadexternal_llvm-5c42c875f7b8a18b3f3945bf52bbab2fa59450c3.tar.gz
external_llvm-5c42c875f7b8a18b3f3945bf52bbab2fa59450c3.tar.bz2
external_llvm-5c42c875f7b8a18b3f3945bf52bbab2fa59450c3.zip
Move getUniqueExitBlocks from LoopBase to Loop, since they depend on
LoopSimplify form, which is currently only available on Loops (and not MachineLoops). Also, move the code out of the header file. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80923 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/LoopInfo.cpp')
-rw-r--r--lib/Analysis/LoopInfo.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp
index 2526480119..4245702ea1 100644
--- a/lib/Analysis/LoopInfo.cpp
+++ b/lib/Analysis/LoopInfo.cpp
@@ -294,6 +294,74 @@ bool Loop::isLoopSimplifyForm() const {
return true;
}
+/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
+/// These are the blocks _outside of the current loop_ which are branched to.
+/// This assumes that loop is in canonical form.
+///
+void
+Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
+ // Sort the blocks vector so that we can use binary search to do quick
+ // lookups.
+ SmallVector<BasicBlock *, 128> LoopBBs(block_begin(), block_end());
+ std::sort(LoopBBs.begin(), LoopBBs.end());
+
+ std::vector<BasicBlock *> switchExitBlocks;
+
+ for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) {
+
+ BasicBlock *current = *BI;
+ switchExitBlocks.clear();
+
+ typedef GraphTraits<BasicBlock *> BlockTraits;
+ typedef GraphTraits<Inverse<BasicBlock *> > InvBlockTraits;
+ for (BlockTraits::ChildIteratorType I =
+ BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
+ I != E; ++I) {
+ // If block is inside the loop then it is not a exit block.
+ if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
+ continue;
+
+ InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(*I);
+ BasicBlock *firstPred = *PI;
+
+ // 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 (current != 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(current),
+ BlockTraits::child_end(current)) <= 2) {
+ ExitBlocks.push_back(*I);
+ continue;
+ }
+
+ // 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 (std::find(switchExitBlocks.begin(), switchExitBlocks.end(), *I)
+ == switchExitBlocks.end()) {
+ switchExitBlocks.push_back(*I);
+ ExitBlocks.push_back(*I);
+ }
+ }
+ }
+}
+
+/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
+/// block, return that block. Otherwise return null.
+BasicBlock *Loop::getUniqueExitBlock() const {
+ SmallVector<BasicBlock *, 8> UniqueExitBlocks;
+ getUniqueExitBlocks(UniqueExitBlocks);
+ if (UniqueExitBlocks.size() == 1)
+ return UniqueExitBlocks[0];
+ return 0;
+}
+
//===----------------------------------------------------------------------===//
// LoopInfo implementation
//