diff options
author | Diego Caballero <diego.caballero@intel.com> | 2018-07-09 17:52:49 +0000 |
---|---|---|
committer | Diego Caballero <diego.caballero@intel.com> | 2018-07-09 17:52:49 +0000 |
commit | 29a07b37bf2c6ba4f312c20e5c058826178fcf9e (patch) | |
tree | a1632a84be9e734c37d4ea594b1b65645b6e72ff | |
parent | f639936748a2e5fbe5823705188c324d8cbfcaa5 (diff) | |
download | bcm5719-llvm-29a07b37bf2c6ba4f312c20e5c058826178fcf9e.tar.gz bcm5719-llvm-29a07b37bf2c6ba4f312c20e5c058826178fcf9e.zip |
[LoopInfo] Port loop exit interfaces from Loop to LoopBase
This patch ports hasDedicatedExits, getUniqueExitBlocks and
getUniqueExitBlock in Loop to LoopBase so that they can be used
from other LoopBase sub-classes.
Reviewers: chandlerc, sanjoy, hfinkel, fhahn
Reviewed By: chandlerc
Differential Revision: https://reviews.llvm.org/D48817
llvm-svn: 336572
-rw-r--r-- | llvm/include/llvm/Analysis/LoopInfo.h | 28 | ||||
-rw-r--r-- | llvm/include/llvm/Analysis/LoopInfoImpl.h | 68 | ||||
-rw-r--r-- | llvm/lib/Analysis/LoopInfo.cpp | 63 |
3 files changed, 82 insertions, 77 deletions
diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h index cdc8d0a1895..30b29d66a1d 100644 --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -261,6 +261,20 @@ public: /// Otherwise return null. BlockT *getExitBlock() const; + /// Return true if no exit block for the loop has a predecessor that is + /// outside the loop. + bool hasDedicatedExits() const; + + /// 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 exits are in canonical form, i.e. all exits are + /// dedicated exits. + void getUniqueExitBlocks(SmallVectorImpl<BlockT *> &ExitBlocks) const; + + /// If getUniqueExitBlocks would return exactly one block, return that block. + /// Otherwise return null. + BlockT *getUniqueExitBlock() const; + /// Edge type. typedef std::pair<const BlockT *, const BlockT *> Edge; @@ -553,20 +567,6 @@ public: /// unrolling pass is run more than once (which it generally is). void setLoopAlreadyUnrolled(); - /// Return true if no exit block for the loop has a predecessor that is - /// outside the loop. - bool hasDedicatedExits() const; - - /// 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 exits are in canonical form, i.e. all exits are - /// dedicated exits. - void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const; - - /// If getUniqueExitBlocks would return exactly one block, return that block. - /// Otherwise return null. - BasicBlock *getUniqueExitBlock() const; - void dump() const; void dumpVerbose() const; diff --git a/llvm/include/llvm/Analysis/LoopInfoImpl.h b/llvm/include/llvm/Analysis/LoopInfoImpl.h index e2620459107..94138985886 100644 --- a/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -82,6 +82,74 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const { return nullptr; } +template <class BlockT, class LoopT> +bool LoopBase<BlockT, LoopT>::hasDedicatedExits() const { + // Each predecessor of each exit block of a normal loop is contained + // within the loop. + SmallVector<BlockT *, 4> ExitBlocks; + getExitBlocks(ExitBlocks); + for (BlockT *EB : ExitBlocks) + for (BlockT *Predecessor : children<Inverse<BlockT *>>(EB)) + if (!contains(Predecessor)) + return false; + // All the requirements are met. + return true; +} + +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; + } + + // 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> +BlockT *LoopBase<BlockT, LoopT>::getUniqueExitBlock() const { + SmallVector<BlockT *, 8> UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); + if (UniqueExitBlocks.size() == 1) + return UniqueExitBlocks[0]; + return nullptr; +} + /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). template <class BlockT, class LoopT> void LoopBase<BlockT, LoopT>::getExitEdges( diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index fec808d5d31..3f78456b358 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -378,69 +378,6 @@ Loop::LocRange Loop::getLocRange() const { return LocRange(); } -bool Loop::hasDedicatedExits() const { - // Each predecessor of each exit block of a normal loop is contained - // within the loop. - SmallVector<BasicBlock *, 4> ExitBlocks; - getExitBlocks(ExitBlocks); - for (BasicBlock *BB : ExitBlocks) - for (BasicBlock *Predecessor : predecessors(BB)) - if (!contains(Predecessor)) - return false; - // All the requirements are met. - return true; -} - -void Loop::getUniqueExitBlocks( - SmallVectorImpl<BasicBlock *> &ExitBlocks) const { - assert(hasDedicatedExits() && - "getUniqueExitBlocks assumes the loop has canonical form exits!"); - - SmallVector<BasicBlock *, 32> SwitchExitBlocks; - for (BasicBlock *BB : this->blocks()) { - SwitchExitBlocks.clear(); - for (BasicBlock *Successor : successors(BB)) { - // If block is inside the loop then it is not an exit block. - if (contains(Successor)) - continue; - - pred_iterator PI = pred_begin(Successor); - 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 (BB != 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 (succ_size(BB) <= 2) { - ExitBlocks.push_back(Successor); - 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 (!is_contained(SwitchExitBlocks, Successor)) { - SwitchExitBlocks.push_back(Successor); - ExitBlocks.push_back(Successor); - } - } - } -} - -BasicBlock *Loop::getUniqueExitBlock() const { - SmallVector<BasicBlock *, 8> UniqueExitBlocks; - getUniqueExitBlocks(UniqueExitBlocks); - if (UniqueExitBlocks.size() == 1) - return UniqueExitBlocks[0]; - return nullptr; -} - #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void Loop::dump() const { print(dbgs()); } |