mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
IR: Reduce RAUW traffic in ConstantExpr
Avoid RAUW-ing `ConstantExpr` when an operand changes unless the new `ConstantExpr` already has users. This prevents the RAUW from rippling up the expression tree unnecessarily. This commit indirectly adds test coverage for r215953 (this is how I came across the bug). This is part of PR20515. llvm-svn: 215960
This commit is contained in:
parent
b39b2d0a5d
commit
d82edcc72a
@ -1107,6 +1107,12 @@ private:
|
||||
void setValueSubclassData(unsigned short D) {
|
||||
Value::setValueSubclassData(D);
|
||||
}
|
||||
|
||||
/// \brief Check whether this can become its replacement.
|
||||
///
|
||||
/// For use during \a replaceUsesOfWithOnConstant(), check whether we know
|
||||
/// how to turn this into \a Replacement, thereby reducing RAUW traffic.
|
||||
bool canBecomeReplacement(const Constant *Replacement) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
@ -2836,6 +2836,25 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
// Everyone using this now uses the replacement.
|
||||
replaceAllUsesWith(Replacement);
|
||||
|
||||
@ -2843,6 +2862,31 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
|
||||
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;
|
||||
}
|
||||
|
||||
Instruction *ConstantExpr::getAsInstruction() {
|
||||
SmallVector<Value*,4> ValueOperands;
|
||||
for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
|
||||
|
Loading…
Reference in New Issue
Block a user