diff options
| author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-08-19 20:03:35 +0000 |
|---|---|---|
| committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-08-19 20:03:35 +0000 |
| commit | 33de00cf5970f11437aef58f452fdc6d84f02074 (patch) | |
| tree | b5fdd2da5d52112e3d906aacebd1c11bafbaafa5 /llvm/lib/IR/Constants.cpp | |
| parent | 170eb985dad2bc4d0bea63262d043d4135170885 (diff) | |
| download | bcm5719-llvm-33de00cf5970f11437aef58f452fdc6d84f02074.tar.gz bcm5719-llvm-33de00cf5970f11437aef58f452fdc6d84f02074.zip | |
IR: Fix ConstantExpr::replaceUsesOfWithOnConstant()
Change `ConstantExpr` to follow the model the other constants are using:
only malloc a replacement if it's going to be used. This fixes a subtle
bug where if an API user had used `ConstantExpr::get()` already to
create the replacement but hadn't given it any users, we'd delete the
replacement.
This relies on r216015 to thread `OnlyIfReduced` through
`ConstantExpr::getWithOperands()`.
llvm-svn: 216016
Diffstat (limited to 'llvm/lib/IR/Constants.cpp')
| -rw-r--r-- | llvm/lib/IR/Constants.cpp | 63 |
1 files changed, 13 insertions, 50 deletions
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index e88069a3443..4cc1e96605f 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2857,63 +2857,26 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, Constant *To = cast<Constant>(ToV); SmallVector<Constant*, 8> NewOps; + unsigned NumUpdated = 0; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Op = getOperand(i); - NewOps.push_back(Op == From ? To : Op); + if (Op == From) { + ++NumUpdated; + Op = To; + } + NewOps.push_back(Op); } + assert(NumUpdated && "I didn't contain From!"); - Constant *Replacement = getWithOperands(NewOps); - assert(Replacement != this && "I didn't contain From!"); - - // Check if Replacement has no users (and is the same type). Ideally, this - // check would be done *before* creating Replacement, but threading this - // through constant-folding isn't trivial. - if (canBecomeReplacement(Replacement)) { - // Avoid unnecessary RAUW traffic. - auto &ExprConstants = getType()->getContext().pImpl->ExprConstants; - ExprConstants.remove(this); - - auto *CE = cast<ConstantExpr>(Replacement); - for (unsigned I = 0, E = getNumOperands(); I != E; ++I) - // Only set the operands that have actually changed. - if (getOperand(I) != CE->getOperand(I)) - setOperand(I, CE->getOperand(I)); - - CE->destroyConstant(); - ExprConstants.insert(this); + if (Constant *C = getWithOperands(NewOps, getType(), true)) { + replaceUsesOfWithOnConstantImpl(C); return; } - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); -} - -bool ConstantExpr::canBecomeReplacement(const Constant *Replacement) const { - // If Replacement already has users, use it regardless. - if (!Replacement->use_empty()) - return false; - - // Check for anything that could have changed during constant-folding. - if (getValueID() != Replacement->getValueID()) - return false; - const auto *CE = cast<ConstantExpr>(Replacement); - if (getOpcode() != CE->getOpcode()) - return false; - if (getNumOperands() != CE->getNumOperands()) - return false; - if (getRawSubclassOptionalData() != CE->getRawSubclassOptionalData()) - return false; - if (isCompare()) - if (getPredicate() != CE->getPredicate()) - return false; - if (hasIndices()) - if (getIndices() != CE->getIndices()) - return false; - - return true; + // Update to the new value. + if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace( + NewOps, this, From, To, NumUpdated, U - OperandList)) + replaceUsesOfWithOnConstantImpl(C); } Instruction *ConstantExpr::getAsInstruction() { |

