llvm.org GIT mirror llvm / a88d974
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 Jakob Stoklund Olesen 7 years ago
1 changed file(s) with 13 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
111111 /// isUsedInBasicBlock - Return true if this value is used in the specified
112112 /// basic block.
113113 bool Value::isUsedInBasicBlock(const BasicBlock *BB) const {
114 // Start by scanning over the instructions looking for a use before we start
115 // the expensive use iteration.
116 unsigned MaxBlockSize = 3;
117 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
118 if (std::find(I->op_begin(), I->op_end(), this) != I->op_end())
114 // This can be computed either by scanning the instructions in BB, or by
115 // scanning the use list of this Value. Both lists can be very long, but
116 // usually one is quite short.
117 //
118 // Scan both lists simultaneously until one is exhausted. This limits the
119 // search to the shorter list.
120 BasicBlock::const_iterator BI = BB->begin(), BE = BB->end();
121 const_use_iterator UI = use_begin(), UE = use_end();
122 for (; BI != BE && UI != UE; ++BI, ++UI) {
123 // Scan basic block: Check if this Value is used by the instruction at BI.
124 if (std::find(BI->op_begin(), BI->op_end(), this) != BI->op_end())
119125 return true;
120 if (--MaxBlockSize == 0) // If the block is larger fall back to use_iterator
121 break;
122 }
123
124 if (MaxBlockSize != 0) // We scanned the entire block and found no use.
125 return false;
126
127 for (const_use_iterator I = use_begin(), E = use_end(); I != E; ++I) {
128 const Instruction *User = dyn_cast(*I);
126 // Scan use list: Check if the use at UI is in BB.
127 const Instruction *User = dyn_cast(*UI);
129128 if (User && User->getParent() == BB)
130129 return true;
131130 }