mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Quick look-up for block in loop.
This patch implements quick look-up for block in loop by maintaining a hash set for blocks. It improves the efficiency of loop analysis a lot, the biggest improvement could be 5-6%(458.sjeng). Below are the compilation time for our benchmark in llc before & after the patch. Benchmark llc - trunk llc - patched 401.bzip2 0.339081 100.00% 0.329657 102.86% 403.gcc 19.853966 100.00% 19.605466 101.27% 429.mcf 0.049823 100.00% 0.048451 102.83% 433.milc 0.514898 100.00% 0.510217 100.92% 444.namd 1.109328 100.00% 1.103481 100.53% 445.gobmk 4.988028 100.00% 4.929114 101.20% 456.hmmer 0.843871 100.00% 0.825865 102.18% 458.sjeng 0.754238 100.00% 0.714095 105.62% 464.h264ref 2.9668 100.00% 2.90612 102.09% 471.omnetpp 4.556533 100.00% 4.511886 100.99% bitmnp01 0.038168 100.00% 0.0357 106.91% idctrn01 0.037745 100.00% 0.037332 101.11% libquake2 3.78689 100.00% 3.76209 100.66% libquake_ 2.251525 100.00% 2.234104 100.78% linpack 0.033159 100.00% 0.032788 101.13% matrix01 0.045319 100.00% 0.043497 104.19% nbench 0.333161 100.00% 0.329799 101.02% tblook01 0.017863 100.00% 0.017666 101.12% ttsprk01 0.054337 100.00% 0.053057 102.41% Reviewer : Andrew Trick <atrick@apple.com>, Hal Finkel <hfinkel@anl.gov> Approver : Andrew Trick <atrick@apple.com> Test : Pass make check-all & llvm test-suite git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193460 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f7ca7c2a09
commit
887f9c5ec1
@ -69,6 +69,8 @@ class LoopBase {
|
||||
// Blocks - The list of blocks in this loop. First entry is the header node.
|
||||
std::vector<BlockT*> Blocks;
|
||||
|
||||
SmallPtrSet<const BlockT*, 8> DenseBlockSet;
|
||||
|
||||
LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
|
||||
const LoopBase<BlockT, LoopT>&
|
||||
operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
|
||||
@ -108,7 +110,7 @@ public:
|
||||
/// contains - Return true if the specified basic block is in this loop.
|
||||
///
|
||||
bool contains(const BlockT *BB) const {
|
||||
return std::find(block_begin(), block_end(), BB) != block_end();
|
||||
return DenseBlockSet.count(BB);
|
||||
}
|
||||
|
||||
/// contains - Return true if the specified instruction is in this loop.
|
||||
@ -134,7 +136,6 @@ public:
|
||||
/// getBlocks - Get a list of the basic blocks which make up this loop.
|
||||
///
|
||||
const std::vector<BlockT*> &getBlocks() const { return Blocks; }
|
||||
std::vector<BlockT*> &getBlocksVector() { return Blocks; }
|
||||
typedef typename std::vector<BlockT*>::const_iterator block_iterator;
|
||||
block_iterator block_begin() const { return Blocks.begin(); }
|
||||
block_iterator block_end() const { return Blocks.end(); }
|
||||
@ -271,6 +272,17 @@ public:
|
||||
/// transformations should use addBasicBlockToLoop.
|
||||
void addBlockEntry(BlockT *BB) {
|
||||
Blocks.push_back(BB);
|
||||
DenseBlockSet.insert(BB);
|
||||
}
|
||||
|
||||
/// reverseBlocks - interface to reverse Blocks[from, end of loop] in this loop
|
||||
void reverseBlock(unsigned from) {
|
||||
std::reverse(Blocks.begin() + from, Blocks.end());
|
||||
}
|
||||
|
||||
/// reserveBlocks- interface to do reserve() for Blocks
|
||||
void reserveBlocks(unsigned size) {
|
||||
Blocks.reserve(size);
|
||||
}
|
||||
|
||||
/// moveToHeader - This method is used to move BB (which must be part of this
|
||||
@ -293,6 +305,7 @@ public:
|
||||
/// the mapping in the LoopInfo class.
|
||||
void removeBlockFromLoop(BlockT *BB) {
|
||||
RemoveFromVector(Blocks, BB);
|
||||
DenseBlockSet.erase(BB);
|
||||
}
|
||||
|
||||
/// verifyLoop - Verify loop structure
|
||||
@ -307,6 +320,7 @@ protected:
|
||||
friend class LoopInfoBase<BlockT, LoopT>;
|
||||
explicit LoopBase(BlockT *BB) : ParentLoop(0) {
|
||||
Blocks.push_back(BB);
|
||||
DenseBlockSet.insert(BB);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -31,17 +31,12 @@ namespace llvm {
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) {
|
||||
if (!contains(*I)) {
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitingBlocks.push_back(*BI);
|
||||
break;
|
||||
@ -65,17 +60,12 @@ BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const {
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
|
||||
if (!contains(*I))
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitBlocks.push_back(*I);
|
||||
}
|
||||
@ -95,17 +85,12 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const {
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
array_pod_sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
|
||||
if (!contains(*I))
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitEdges.push_back(Edge(*BI, *I));
|
||||
}
|
||||
@ -210,7 +195,7 @@ addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) {
|
||||
|
||||
// Add the basic block to this loop and all parent loops...
|
||||
while (L) {
|
||||
L->Blocks.push_back(NewBB);
|
||||
L->addBlockEntry(NewBB);
|
||||
L = L->getParentLoop();
|
||||
}
|
||||
}
|
||||
@ -250,11 +235,6 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
// Keep track of the number of BBs visited.
|
||||
unsigned NumVisited = 0;
|
||||
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
// Check the individual blocks.
|
||||
for ( ; BI != BE; ++BI) {
|
||||
BlockT *BB = *BI;
|
||||
@ -266,7 +246,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
for (typename BlockTraits::ChildIteratorType SI =
|
||||
BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB);
|
||||
SI != SE; ++SI)
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) {
|
||||
if (contains(*SI)) {
|
||||
HasInsideLoopSuccs = true;
|
||||
break;
|
||||
}
|
||||
@ -275,7 +255,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
BlockT *N = *PI;
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N))
|
||||
if (contains(N))
|
||||
HasInsideLoopPreds = true;
|
||||
else
|
||||
OutsideLoopPreds.push_back(N);
|
||||
@ -309,7 +289,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
// Each block in each subloop should be contained within this loop.
|
||||
for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end();
|
||||
BI != BE; ++BI) {
|
||||
assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) &&
|
||||
assert(contains(*BI) &&
|
||||
"Loop does not contain all the blocks of a subloop!");
|
||||
}
|
||||
|
||||
@ -418,7 +398,7 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
|
||||
}
|
||||
}
|
||||
L->getSubLoopsVector().reserve(NumSubloops);
|
||||
L->getBlocksVector().reserve(NumBlocks);
|
||||
L->reserveBlocks(NumBlocks);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -489,15 +469,14 @@ void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
|
||||
|
||||
// For convenience, Blocks and Subloops are inserted in postorder. Reverse
|
||||
// the lists, except for the loop header, which is always at the beginning.
|
||||
std::reverse(Subloop->getBlocksVector().begin()+1,
|
||||
Subloop->getBlocksVector().end());
|
||||
Subloop->reverseBlock(1);
|
||||
std::reverse(Subloop->getSubLoopsVector().begin(),
|
||||
Subloop->getSubLoopsVector().end());
|
||||
|
||||
Subloop = Subloop->getParentLoop();
|
||||
}
|
||||
for (; Subloop; Subloop = Subloop->getParentLoop())
|
||||
Subloop->getBlocksVector().push_back(Block);
|
||||
Subloop->addBlockEntry(Block);
|
||||
}
|
||||
|
||||
/// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal
|
||||
|
@ -177,10 +177,6 @@ PHINode *Loop::getCanonicalInductionVariable() const {
|
||||
|
||||
/// isLCSSAForm - Return true if the Loop is in LCSSA form
|
||||
bool Loop::isLCSSAForm(DominatorTree &DT) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallPtrSet<BasicBlock*, 16> LoopBBs(block_begin(), block_end());
|
||||
|
||||
for (block_iterator BI = block_begin(), E = block_end(); BI != E; ++BI) {
|
||||
BasicBlock *BB = *BI;
|
||||
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;++I)
|
||||
@ -196,7 +192,7 @@ bool Loop::isLCSSAForm(DominatorTree &DT) const {
|
||||
// block they are defined in. Also, blocks not reachable from the
|
||||
// entry are special; uses in them don't need to go through PHIs.
|
||||
if (UserBB != BB &&
|
||||
!LoopBBs.count(UserBB) &&
|
||||
!contains(UserBB) &&
|
||||
DT.isReachableFromEntry(UserBB))
|
||||
return false;
|
||||
}
|
||||
@ -337,9 +333,6 @@ bool Loop::isAnnotatedParallel() const {
|
||||
/// hasDedicatedExits - Return true if no exit block for the loop
|
||||
/// has a predecessor that is outside the loop.
|
||||
bool Loop::hasDedicatedExits() const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());
|
||||
// Each predecessor of each exit block of a normal loop is contained
|
||||
// within the loop.
|
||||
SmallVector<BasicBlock *, 4> ExitBlocks;
|
||||
@ -347,7 +340,7 @@ bool Loop::hasDedicatedExits() const {
|
||||
for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
|
||||
for (pred_iterator PI = pred_begin(ExitBlocks[i]),
|
||||
PE = pred_end(ExitBlocks[i]); PI != PE; ++PI)
|
||||
if (!LoopBBs.count(*PI))
|
||||
if (!contains(*PI))
|
||||
return false;
|
||||
// All the requirements are met.
|
||||
return true;
|
||||
@ -362,11 +355,6 @@ Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
|
||||
assert(hasDedicatedExits() &&
|
||||
"getUniqueExitBlocks assumes the loop has canonical form exits!");
|
||||
|
||||
// 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());
|
||||
|
||||
SmallVector<BasicBlock *, 32> switchExitBlocks;
|
||||
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) {
|
||||
@ -376,7 +364,7 @@ Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
|
||||
|
||||
for (succ_iterator I = succ_begin(*BI), E = succ_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))
|
||||
if (contains(*I))
|
||||
continue;
|
||||
|
||||
pred_iterator PI = pred_begin(*I);
|
||||
|
@ -55,7 +55,6 @@ namespace {
|
||||
DominatorTree *DT;
|
||||
LoopInfo *LI;
|
||||
ScalarEvolution *SE;
|
||||
std::vector<BasicBlock*> LoopBlocks;
|
||||
PredIteratorCache PredCache;
|
||||
Loop *L;
|
||||
|
||||
@ -82,11 +81,6 @@ namespace {
|
||||
// Check the special guarantees that LCSSA makes.
|
||||
assert(L->isLCSSAForm(*DT) && "LCSSA form not preserved!");
|
||||
}
|
||||
|
||||
/// inLoop - returns true if the given block is within the current loop
|
||||
bool inLoop(BasicBlock *B) const {
|
||||
return std::binary_search(LoopBlocks.begin(), LoopBlocks.end(), B);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -129,11 +123,6 @@ bool LCSSA::runOnLoop(Loop *TheLoop, LPPassManager &LPM) {
|
||||
if (ExitBlocks.empty())
|
||||
return false;
|
||||
|
||||
// Speed up queries by creating a sorted vector of blocks.
|
||||
LoopBlocks.clear();
|
||||
LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end());
|
||||
array_pod_sort(LoopBlocks.begin(), LoopBlocks.end());
|
||||
|
||||
// Look at all the instructions in the loop, checking to see if they have uses
|
||||
// outside the loop. If so, rewrite those uses.
|
||||
bool MadeChange = false;
|
||||
@ -198,7 +187,7 @@ bool LCSSA::ProcessInstruction(Instruction *Inst,
|
||||
if (PHINode *PN = dyn_cast<PHINode>(U))
|
||||
UserBB = PN->getIncomingBlock(UI);
|
||||
|
||||
if (InstBB != UserBB && !inLoop(UserBB))
|
||||
if (InstBB != UserBB && !L->contains(UserBB))
|
||||
UsesToRewrite.push_back(&UI.getUse());
|
||||
}
|
||||
|
||||
@ -244,7 +233,7 @@ bool LCSSA::ProcessInstruction(Instruction *Inst,
|
||||
// If the exit block has a predecessor not within the loop, arrange for
|
||||
// the incoming value use corresponding to that predecessor to be
|
||||
// rewritten in terms of a different LCSSA PHI.
|
||||
if (!inLoop(*PI))
|
||||
if (!L->contains(*PI))
|
||||
UsesToRewrite.push_back(
|
||||
&PN->getOperandUse(
|
||||
PN->getOperandNumForIncomingValue(PN->getNumIncomingValues()-1)));
|
||||
|
@ -2694,14 +2694,14 @@ bool LoopVectorizationLegality::canVectorizeWithIfConvert() {
|
||||
return false;
|
||||
|
||||
assert(TheLoop->getNumBlocks() > 1 && "Single block loops are vectorizable");
|
||||
std::vector<BasicBlock*> &LoopBlocks = TheLoop->getBlocksVector();
|
||||
|
||||
// A list of pointers that we can safely read and write to.
|
||||
SmallPtrSet<Value *, 8> SafePointes;
|
||||
|
||||
// Collect safe addresses.
|
||||
for (unsigned i = 0, e = LoopBlocks.size(); i < e; ++i) {
|
||||
BasicBlock *BB = LoopBlocks[i];
|
||||
for (Loop::block_iterator BI = TheLoop->block_begin(),
|
||||
BE = TheLoop->block_end(); BI != BE; ++BI) {
|
||||
BasicBlock *BB = *BI;
|
||||
|
||||
if (blockNeedsPredication(BB))
|
||||
continue;
|
||||
@ -2715,8 +2715,9 @@ bool LoopVectorizationLegality::canVectorizeWithIfConvert() {
|
||||
}
|
||||
|
||||
// Collect the blocks that need predication.
|
||||
for (unsigned i = 0, e = LoopBlocks.size(); i < e; ++i) {
|
||||
BasicBlock *BB = LoopBlocks[i];
|
||||
for (Loop::block_iterator BI = TheLoop->block_begin(),
|
||||
BE = TheLoop->block_end(); BI != BE; ++BI) {
|
||||
BasicBlock *BB = *BI;
|
||||
|
||||
// We don't support switch statements inside loops.
|
||||
if (!isa<BranchInst>(BB->getTerminator()))
|
||||
|
Loading…
Reference in New Issue
Block a user