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:
parent
435cf460c9
commit
23d29638bf
@ -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;
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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()); }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user