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 <>
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);
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)