summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/Constant.h16
-rw-r--r--llvm/include/llvm/IR/Constants.h21
-rw-r--r--llvm/include/llvm/IR/GlobalValue.h2
-rw-r--r--llvm/include/llvm/IR/GlobalVariable.h1
-rw-r--r--llvm/lib/IR/Constants.cpp139
-rw-r--r--llvm/lib/IR/Globals.cpp4
-rw-r--r--llvm/lib/IR/Value.cpp2
7 files changed, 100 insertions, 85 deletions
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 8c1f6aa41c8..019b4343a13 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -47,8 +47,6 @@ protected:
Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps)
: User(ty, vty, Ops, NumOps) {}
- void replaceUsesOfWithOnConstantImpl(Constant *Replacement);
-
public:
/// isNullValue - Return true if this is the value that would be returned by
/// getNullValue.
@@ -140,8 +138,8 @@ public:
V->getValueID() <= ConstantLastVal;
}
- /// replaceUsesOfWithOnConstant - This method is a special form of
- /// User::replaceUsesOfWith (which does not work on constants) that does work
+ /// This method is a special form of User::replaceUsesOfWith
+ /// (which does not work on constants) that does work
/// on constants. Basically this method goes through the trouble of building
/// a new constant that is equivalent to the current one, with all uses of
/// From replaced with uses of To. After this construction is completed, all
@@ -150,15 +148,7 @@ public:
/// use Value::replaceAllUsesWith, which automatically dispatches to this
/// method as needed.
///
- virtual void replaceUsesOfWithOnConstant(Value *, Value *, Use *) {
- // Provide a default implementation for constants (like integers) that
- // cannot use any other values. This cannot be called at runtime, but needs
- // to be here to avoid link errors.
- assert(getNumOperands() == 0 && "replaceUsesOfWithOnConstant must be "
- "implemented for all constants that have operands!");
- llvm_unreachable("Constants that do not have operands cannot be using "
- "'From'!");
- }
+ void handleOperandChange(Value *, Value *, Use *);
static Constant *getNullValue(Type* Ty);
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 32eece77bde..0c7a84fc8bf 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -53,6 +53,7 @@ class ConstantInt : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
// allocate space for exactly zero operands
@@ -238,6 +239,7 @@ class ConstantFP : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
ConstantFP(Type *Ty, const APFloat& V);
@@ -308,6 +310,7 @@ class ConstantAggregateZero : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
explicit ConstantAggregateZero(Type *ty)
@@ -356,6 +359,7 @@ class ConstantArray : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
@@ -377,8 +381,6 @@ public:
return cast<ArrayType>(Value::getType());
}
- void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override;
-
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Value *V) {
return V->getValueID() == ConstantArrayVal;
@@ -401,6 +403,7 @@ class ConstantStruct : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
@@ -438,8 +441,6 @@ public:
return cast<StructType>(Value::getType());
}
- void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override;
-
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Value *V) {
return V->getValueID() == ConstantStructVal;
@@ -463,6 +464,7 @@ class ConstantVector : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
@@ -492,8 +494,6 @@ public:
/// elements have the same value, return that value. Otherwise return NULL.
Constant *getSplatValue() const;
- void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override;
-
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Value *V) {
return V->getValueID() == ConstantVectorVal;
@@ -516,6 +516,7 @@ class ConstantPointerNull : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
explicit ConstantPointerNull(PointerType *T)
@@ -569,6 +570,7 @@ class ConstantDataSequential : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data)
@@ -804,6 +806,7 @@ class BlockAddress : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
public:
/// get - Return a BlockAddress for the specified function and basic block.
@@ -825,8 +828,6 @@ public:
Function *getFunction() const { return (Function*)Op<0>().get(); }
BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); }
- void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override;
-
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
return V->getValueID() == BlockAddressVal;
@@ -853,6 +854,7 @@ class ConstantExpr : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps)
@@ -1185,8 +1187,6 @@ public:
/// would make it harder to remove ConstantExprs altogether.
Instruction *getAsInstruction();
- void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override;
-
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
return V->getValueID() == ConstantExprVal;
@@ -1223,6 +1223,7 @@ class UndefValue : public Constant {
friend class Constant;
void destroyConstantImpl();
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {}
diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h
index 4bca80edb4d..f2379705d46 100644
--- a/llvm/include/llvm/IR/GlobalValue.h
+++ b/llvm/include/llvm/IR/GlobalValue.h
@@ -92,7 +92,7 @@ private:
friend class Constant;
void destroyConstantImpl();
- void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override;
+ Value *handleOperandChangeImpl(Value *From, Value *To, Use *U);
protected:
/// \brief The intrinsic ID for this subclass (which must be a Function).
diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h
index 7b291605d45..a0159830ba3 100644
--- a/llvm/include/llvm/IR/GlobalVariable.h
+++ b/llvm/include/llvm/IR/GlobalVariable.h
@@ -45,7 +45,6 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
// can change from its initial
// value before global
// initializers are run?
-
public:
// allocate space for exactly one operand
void *operator new(size_t s) {
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 9b2bb27a88e..308e6bde3d1 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -1531,7 +1531,7 @@ void BlockAddress::destroyConstantImpl() {
getBasicBlock()->AdjustBlockAddressRefCount(-1);
}
-void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
+Value *BlockAddress::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
// This could be replacing either the Basic Block or the Function. In either
// case, we have to remove the map entry.
Function *NewF = getFunction();
@@ -1546,10 +1546,8 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
// and return early.
BlockAddress *&NewBA =
getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)];
- if (NewBA) {
- replaceUsesOfWithOnConstantImpl(NewBA);
- return;
- }
+ if (NewBA)
+ return NewBA;
getBasicBlock()->AdjustBlockAddressRefCount(-1);
@@ -1561,6 +1559,10 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
setOperand(0, NewF);
setOperand(1, NewBB);
getBasicBlock()->AdjustBlockAddressRefCount(1);
+
+ // If we just want to keep the existing value, then return null.
+ // Callers know that this means we shouldn't delete this value.
+ return nullptr;
}
//---- ConstantExpr::get() implementations.
@@ -2822,20 +2824,36 @@ Constant *ConstantDataVector::getSplatValue() const {
}
//===----------------------------------------------------------------------===//
-// replaceUsesOfWithOnConstant implementations
+// handleOperandChange implementations
-/// replaceUsesOfWithOnConstant - Update this constant array to change uses of
+/// 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
+/// ConstantArray::handleOperandChange 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 Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) {
+void Constant::handleOperandChange(Value *From, Value *To, Use *U) {
+ Value *Replacement = nullptr;
+ switch (getValueID()) {
+ default:
+ llvm_unreachable("Not a constant!");
+#define HANDLE_CONSTANT(Name) \
+ case Value::Name##Val: \
+ Replacement = cast<Name>(this)->handleOperandChangeImpl(From, To, U); \
+ break;
+#include "llvm/IR/Value.def"
+ }
+
+ // If handleOperandChangeImpl returned nullptr, then it handled
+ // replacing itself and we don't want to delete or replace anything else here.
+ if (!Replacement)
+ return;
+
// I do need to replace this with an existing value.
assert(Replacement != this && "I didn't contain From!");
@@ -2846,8 +2864,34 @@ void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) {
destroyConstant();
}
-void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
- Use *U) {
+Value *ConstantInt::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantFP::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *UndefValue::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantPointerNull::handleOperandChangeImpl(Value *From, Value *To,
+ Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantAggregateZero::handleOperandChangeImpl(Value *From, Value *To,
+ Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantDataSequential::handleOperandChangeImpl(Value *From, Value *To,
+ Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantArray::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
@@ -2871,29 +2915,22 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
AllSame &= Val == ToC;
}
- if (AllSame && ToC->isNullValue()) {
- replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
- return;
- }
- if (AllSame && isa<UndefValue>(ToC)) {
- replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
- return;
- }
+ if (AllSame && ToC->isNullValue())
+ return ConstantAggregateZero::get(getType());
+
+ if (AllSame && isa<UndefValue>(ToC))
+ return UndefValue::get(getType());
// Check for any other type of constant-folding.
- if (Constant *C = getImpl(getType(), Values)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
+ if (Constant *C = getImpl(getType(), Values))
+ return C;
// Update to the new value.
- if (Constant *C = getContext().pImpl->ArrayConstants.replaceOperandsInPlace(
- Values, this, From, ToC, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->ArrayConstants.replaceOperandsInPlace(
+ Values, this, From, ToC, NumUpdated, U - OperandList);
}
-void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
- Use *U) {
+Value *ConstantStruct::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
@@ -2928,23 +2965,18 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
}
Values[OperandToUpdate] = ToC;
- if (isAllZeros) {
- replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
- return;
- }
- if (isAllUndef) {
- replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
- return;
- }
+ if (isAllZeros)
+ return ConstantAggregateZero::get(getType());
+
+ if (isAllUndef)
+ return UndefValue::get(getType());
// Update to the new value.
- if (Constant *C = getContext().pImpl->StructConstants.replaceOperandsInPlace(
- Values, this, From, ToC))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->StructConstants.replaceOperandsInPlace(
+ Values, this, From, ToC);
}
-void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
- Use *U) {
+Value *ConstantVector::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
@@ -2960,20 +2992,16 @@ void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
Values.push_back(Val);
}
- if (Constant *C = getImpl(Values)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
+ if (Constant *C = getImpl(Values))
+ return C;
// Update to the new value.
Use *OperandList = getOperandList();
- if (Constant *C = getContext().pImpl->VectorConstants.replaceOperandsInPlace(
- Values, this, From, ToC, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->VectorConstants.replaceOperandsInPlace(
+ Values, this, From, ToC, NumUpdated, U - OperandList);
}
-void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
- Use *U) {
+Value *ConstantExpr::handleOperandChangeImpl(Value *From, Value *ToV, Use *U) {
assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
Constant *To = cast<Constant>(ToV);
@@ -2989,16 +3017,13 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
}
assert(NumUpdated && "I didn't contain From!");
- if (Constant *C = getWithOperands(NewOps, getType(), true)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
+ if (Constant *C = getWithOperands(NewOps, getType(), true))
+ return C;
// Update to the new value.
Use *OperandList = getOperandList();
- if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace(
- NewOps, this, From, To, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->ExprConstants.replaceOperandsInPlace(
+ NewOps, this, From, To, NumUpdated, U - OperandList);
}
Instruction *ConstantExpr::getAsInstruction() {
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 49ac236778c..1d0282677bf 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -48,8 +48,8 @@ void GlobalValue::destroyConstantImpl() {
llvm_unreachable("You can't GV->destroyConstantImpl()!");
}
-void GlobalValue::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
- llvm_unreachable("You can't GV->replaceUsesOfWithOnConstant()!");
+Value *GlobalValue::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
}
/// copyAttributesFrom - copy all additional attributes (those not needed to
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index eb5c2253f4e..78d1adb5e70 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -369,7 +369,7 @@ void Value::replaceAllUsesWith(Value *New) {
// constant because they are uniqued.
if (auto *C = dyn_cast<Constant>(U.getUser())) {
if (!isa<GlobalValue>(C)) {
- C->replaceUsesOfWithOnConstant(this, New, &U);
+ C->handleOperandChange(this, New, &U);
continue;
}
}
OpenPOWER on IntegriCloud