[llvm] r215960 - IR: Reduce RAUW traffic in ConstantExpr
Duncan P. N. Exon Smith
dexonsmith at apple.com
Mon Aug 18 18:12:53 PDT 2014
Author: dexonsmith
Date: Mon Aug 18 20:12:53 2014
New Revision: 215960
URL: http://llvm.org/viewvc/llvm-project?rev=215960&view=rev
Log:
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.
Modified:
llvm/trunk/include/llvm/IR/Constants.h
llvm/trunk/lib/IR/Constants.cpp
Modified: llvm/trunk/include/llvm/IR/Constants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constants.h?rev=215960&r1=215959&r2=215960&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Constants.h (original)
+++ llvm/trunk/include/llvm/IR/Constants.h Mon Aug 18 20:12:53 2014
@@ -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 <>
Modified: llvm/trunk/lib/IR/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=215960&r1=215959&r2=215960&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Constants.cpp (original)
+++ llvm/trunk/lib/IR/Constants.cpp Mon Aug 18 20:12:53 2014
@@ -2836,6 +2836,25 @@ void ConstantExpr::replaceUsesOfWithOnCo
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::replaceUsesOfWithOnCo
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)
More information about the llvm-commits
mailing list