diff options
author | Chris Lattner <sabre@nondot.org> | 2007-08-21 00:55:23 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-08-21 00:55:23 +0000 |
commit | 917f30f7c609f23be419542fa6412891c6b24e65 (patch) | |
tree | 7ce6d2b85b563a0ccf07f3cdcaa922e3a3c96457 /lib/VMCore | |
parent | 9fd3fe9fa57ffb3fcb4386f23164941b0e81953a (diff) | |
download | external_llvm-917f30f7c609f23be419542fa6412891c6b24e65.zip external_llvm-917f30f7c609f23be419542fa6412891c6b24e65.tar.gz external_llvm-917f30f7c609f23be419542fa6412891c6b24e65.tar.bz2 |
Fix potentially N^2 behavior handling arrays with many of the
same value which get RAUW'd. This speeds up reading the .bc
file in PR1616 from 852s to 0.19s on my G5 with a debug build.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41209 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/Constants.cpp | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index eadfe39..87306fe 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1927,14 +1927,21 @@ const char *ConstantExpr::getOpcodeName() const { //===----------------------------------------------------------------------===// // replaceUsesOfWithOnConstant implementations +/// replaceUsesOfWithOnConstant - Update this constant array to change uses of +/// 'From' to be uses of 'To'. This must update the uniquing data structures +/// etc. +/// +/// Note that we intentionally replace all uses of From with To here. Consider +/// a large array that uses 'From' 1000 times. By handling this case all here, +/// ConstantArray::replaceUsesOfWithOnConstant is only invoked once, and that +/// single invocation handles all 1000 uses. Handling them one at a time would +/// work, but would be really slow because it would have to unique each updated +/// array instance. void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast<Constant>(To); - unsigned OperandToUpdate = U-OperandList; - assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); - std::pair<ArrayConstantsTy::MapKey, Constant*> Lookup; Lookup.first.first = getType(); Lookup.second = this; @@ -1945,18 +1952,28 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, // Fill values with the modified operands of the constant array. Also, // compute whether this turns into an all-zeros array. bool isAllZeros = false; + unsigned NumUpdated = 0; if (!ToC->isNullValue()) { - for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) - Values.push_back(cast<Constant>(O->get())); + for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { + Constant *Val = cast<Constant>(O->get()); + if (Val == From) { + Val = ToC; + ++NumUpdated; + } + Values.push_back(Val); + } } else { isAllZeros = true; for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { Constant *Val = cast<Constant>(O->get()); + if (Val == From) { + Val = ToC; + ++NumUpdated; + } Values.push_back(Val); if (isAllZeros) isAllZeros = Val->isNullValue(); } } - Values[OperandToUpdate] = ToC; Constant *Replacement = 0; if (isAllZeros) { @@ -1976,8 +1993,18 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, // in place! ArrayConstants->MoveConstantToNewSlot(this, I); - // Update to the new value. - setOperand(OperandToUpdate, ToC); + // Update to the new value. Optimize for the case when we have a single + // operand that we're changing, but handle bulk updates efficiently. + if (NumUpdated == 1) { + unsigned OperandToUpdate = U-OperandList; + assert(getOperand(OperandToUpdate) == From && + "ReplaceAllUsesWith broken!"); + setOperand(OperandToUpdate, ToC); + } else { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (getOperand(i) == From) + setOperand(i, ToC); + } return; } } |