1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[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
This commit is contained in:
Diego Caballero 2018-07-09 17:52:49 +00:00
parent 435cf460c9
commit 23d29638bf
3 changed files with 82 additions and 77 deletions

View File

@ -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;

View File

@ -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(

View File

@ -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()); }