mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-30 07:00:45 +00:00
Speed up Value::isUsedInBasicBlock() for long use lists.
This is expanding Ben's original heuristic for short basic blocks to also work for longer basic blocks and huge use lists. Scan the basic block and the use list in parallel, terminating the search when the shorter list ends. In almost all cases, either the basic block or the use list is short, and the function returns quickly. In one crazy test case with very long use chains, CodeGenPrepare runs 400x faster. When compiling ARMDisassembler.cpp it is 5x faster. <rdar://problem/13840497> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181851 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
da2ed458b4
commit
a88d974ce2
@ -112,21 +112,20 @@ bool Value::hasNUsesOrMore(unsigned N) const {
|
||||
/// isUsedInBasicBlock - Return true if this value is used in the specified
|
||||
/// basic block.
|
||||
bool Value::isUsedInBasicBlock(const BasicBlock *BB) const {
|
||||
// Start by scanning over the instructions looking for a use before we start
|
||||
// the expensive use iteration.
|
||||
unsigned MaxBlockSize = 3;
|
||||
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
|
||||
if (std::find(I->op_begin(), I->op_end(), this) != I->op_end())
|
||||
// This can be computed either by scanning the instructions in BB, or by
|
||||
// scanning the use list of this Value. Both lists can be very long, but
|
||||
// usually one is quite short.
|
||||
//
|
||||
// Scan both lists simultaneously until one is exhausted. This limits the
|
||||
// search to the shorter list.
|
||||
BasicBlock::const_iterator BI = BB->begin(), BE = BB->end();
|
||||
const_use_iterator UI = use_begin(), UE = use_end();
|
||||
for (; BI != BE && UI != UE; ++BI, ++UI) {
|
||||
// Scan basic block: Check if this Value is used by the instruction at BI.
|
||||
if (std::find(BI->op_begin(), BI->op_end(), this) != BI->op_end())
|
||||
return true;
|
||||
if (--MaxBlockSize == 0) // If the block is larger fall back to use_iterator
|
||||
break;
|
||||
}
|
||||
|
||||
if (MaxBlockSize != 0) // We scanned the entire block and found no use.
|
||||
return false;
|
||||
|
||||
for (const_use_iterator I = use_begin(), E = use_end(); I != E; ++I) {
|
||||
const Instruction *User = dyn_cast<Instruction>(*I);
|
||||
// Scan use list: Check if the use at UI is in BB.
|
||||
const Instruction *User = dyn_cast<Instruction>(*UI);
|
||||
if (User && User->getParent() == BB)
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user