Index: llvm/trunk/include/llvm/Analysis/LoopInfo.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LoopInfo.h +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h @@ -261,6 +261,20 @@ /// 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 &ExitBlocks) const; + + /// If getUniqueExitBlocks would return exactly one block, return that block. + /// Otherwise return null. + BlockT *getUniqueExitBlock() const; + /// Edge type. typedef std::pair Edge; @@ -553,20 +567,6 @@ /// 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 &ExitBlocks) const; - - /// If getUniqueExitBlocks would return exactly one block, return that block. - /// Otherwise return null. - BasicBlock *getUniqueExitBlock() const; - void dump() const; void dumpVerbose() const; Index: llvm/trunk/include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LoopInfoImpl.h +++ llvm/trunk/include/llvm/Analysis/LoopInfoImpl.h @@ -82,6 +82,74 @@ return nullptr; } +template +bool LoopBase::hasDedicatedExits() const { + // Each predecessor of each exit block of a normal loop is contained + // within the loop. + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); + for (BlockT *EB : ExitBlocks) + for (BlockT *Predecessor : children>(EB)) + if (!contains(Predecessor)) + return false; + // All the requirements are met. + return true; +} + +template +void LoopBase::getUniqueExitBlocks( + SmallVectorImpl &ExitBlocks) const { + typedef GraphTraits BlockTraits; + typedef GraphTraits> InvBlockTraits; + + assert(hasDedicatedExits() && + "getUniqueExitBlocks assumes the loop has canonical form exits!"); + + SmallVector SwitchExitBlocks; + for (BlockT *Block : this->blocks()) { + SwitchExitBlocks.clear(); + for (BlockT *Successor : children(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 +BlockT *LoopBase::getUniqueExitBlock() const { + SmallVector UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); + if (UniqueExitBlocks.size() == 1) + return UniqueExitBlocks[0]; + return nullptr; +} + /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). template void LoopBase::getExitEdges( Index: llvm/trunk/lib/Analysis/LoopInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LoopInfo.cpp +++ llvm/trunk/lib/Analysis/LoopInfo.cpp @@ -378,69 +378,6 @@ return LocRange(); } -bool Loop::hasDedicatedExits() const { - // Each predecessor of each exit block of a normal loop is contained - // within the loop. - SmallVector 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 &ExitBlocks) const { - assert(hasDedicatedExits() && - "getUniqueExitBlocks assumes the loop has canonical form exits!"); - - SmallVector 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 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()); }