From a88d974ce274152d2f8f28660ba277906bde2384 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 14 May 2013 23:45:56 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181851 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/Value.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 89a3c0578cf..81d7efa7740 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(*I); + // Scan use list: Check if the use at UI is in BB. + const Instruction *User = dyn_cast(*UI); if (User && User->getParent() == BB) return true; } -- 2.34.1