summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2013-05-14 23:45:56 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2013-05-14 23:45:56 +0000
commita88d974ce274152d2f8f28660ba277906bde2384 (patch)
tree602a4422e605e7b23aaa1a371ad2a60c6b493c60
parentda2ed458b4e7066fc414c403173b882ccc2c8833 (diff)
downloadllvm-a88d974ce274152d2f8f28660ba277906bde2384.tar.gz
llvm-a88d974ce274152d2f8f28660ba277906bde2384.tar.bz2
llvm-a88d974ce274152d2f8f28660ba277906bde2384.tar.xz
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
-rw-r--r--lib/IR/Value.cpp27
1 files changed, 13 insertions, 14 deletions
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp
index 89a3c0578c..81d7efa774 100644
--- a/lib/IR/Value.cpp
+++ b/lib/IR/Value.cpp
@@ -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;
}