diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 8c1f6aa41c8..019b4343a13 100644 --- a/include/llvm/IR/Constant.h +++ b/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/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 32eece77bde..0c7a84fc8bf 100644 --- a/include/llvm/IR/Constants.h +++ b/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 Val); @@ -377,8 +381,6 @@ public: return cast(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 Val); @@ -438,8 +441,6 @@ public: return cast(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 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/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 4bca80edb4d..f2379705d46 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/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/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 7b291605d45..a0159830ba3 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -45,7 +45,6 @@ class GlobalVariable : public GlobalObject, public ilist_node { // 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/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index 9b2bb27a88e..308e6bde3d1 100644 --- a/lib/IR/Constants.cpp +++ b/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(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(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(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(ToC)) { - replaceUsesOfWithOnConstantImpl(UndefValue::get(getType())); - return; - } + if (AllSame && ToC->isNullValue()) + return ConstantAggregateZero::get(getType()); + + if (AllSame && isa(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(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(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(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(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(ToV) && "Cannot make Constant refer to non-constant!"); Constant *To = cast(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/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 49ac236778c..1d0282677bf 100644 --- a/lib/IR/Globals.cpp +++ b/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/lib/IR/Value.cpp b/lib/IR/Value.cpp index eb5c2253f4e..78d1adb5e70 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -369,7 +369,7 @@ void Value::replaceAllUsesWith(Value *New) { // constant because they are uniqued. if (auto *C = dyn_cast(U.getUser())) { if (!isa(C)) { - C->replaceUsesOfWithOnConstant(this, New, &U); + C->handleOperandChange(this, New, &U); continue; } }