[llvm] r240567 - Devirtualize Constant::replaceUsesOfWithOnConstant.

Pete Cooper peter_cooper at apple.com
Wed Jun 24 11:55:25 PDT 2015


Author: pete
Date: Wed Jun 24 13:55:24 2015
New Revision: 240567

URL: http://llvm.org/viewvc/llvm-project?rev=240567&view=rev
Log:
Devirtualize Constant::replaceUsesOfWithOnConstant.

This is part of the work to devirtualize Value.

The old pattern was to call replaceUsesOfWithOnConstant which was overridden by
subclasses.  Those could then call replaceUsesOfWithOnConstantImpl on Constant
to handle deleting the current value.

To be consistent with other parts of the code, this has been changed so that we
call the method on Constant, and that dispatches to an Impl on subclasses.

As part of this, it made sense to rename the methods to be more descriptive.  The
new name is Constant::handleOperandChange, and it requires that all subclasses of
Constant implement handleOperandChangeImpl, even if they just throw an error if
they shouldn't be called.

Reviewed by Duncan Exon Smith.

Modified:
    llvm/trunk/include/llvm/IR/Constant.h
    llvm/trunk/include/llvm/IR/Constants.h
    llvm/trunk/include/llvm/IR/GlobalValue.h
    llvm/trunk/include/llvm/IR/GlobalVariable.h
    llvm/trunk/lib/IR/Constants.cpp
    llvm/trunk/lib/IR/Globals.cpp
    llvm/trunk/lib/IR/Value.cpp

Modified: llvm/trunk/include/llvm/IR/Constant.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constant.h?rev=240567&r1=240566&r2=240567&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Constant.h (original)
+++ llvm/trunk/include/llvm/IR/Constant.h Wed Jun 24 13:55:24 2015
@@ -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);
 

Modified: llvm/trunk/include/llvm/IR/Constants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constants.h?rev=240567&r1=240566&r2=240567&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Constants.h (original)
+++ llvm/trunk/include/llvm/IR/Constants.h Wed Jun 24 13:55:24 2015
@@ -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 Con
 
   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 Const
 
   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 Co
 
   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) {}

Modified: llvm/trunk/include/llvm/IR/GlobalValue.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalValue.h?rev=240567&r1=240566&r2=240567&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/GlobalValue.h (original)
+++ llvm/trunk/include/llvm/IR/GlobalValue.h Wed Jun 24 13:55:24 2015
@@ -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).

Modified: llvm/trunk/include/llvm/IR/GlobalVariable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalVariable.h?rev=240567&r1=240566&r2=240567&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/GlobalVariable.h (original)
+++ llvm/trunk/include/llvm/IR/GlobalVariable.h Wed Jun 24 13:55:24 2015
@@ -45,7 +45,6 @@ class GlobalVariable : public GlobalObje
                                                // can change from its initial
                                                // value before global
                                                // initializers are run?
-
 public:
   // allocate space for exactly one operand
   void *operator new(size_t s) {

Modified: llvm/trunk/lib/IR/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=240567&r1=240566&r2=240567&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Constants.cpp (original)
+++ llvm/trunk/lib/IR/Constants.cpp Wed Jun 24 13:55:24 2015
@@ -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::replaceUsesOfWithOnCo
   // 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::replaceUsesOfWithOnCo
   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::getSplatVa
 }
 
 //===----------------------------------------------------------------------===//
-//                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::replaceUsesOfWithOnConsta
   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::replaceUsesOfWithOnC
     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::replaceUsesOfWithOn
   }
   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::replaceUsesOfWithOn
     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::replaceUsesOfWithOnCo
   }
   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() {

Modified: llvm/trunk/lib/IR/Globals.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Globals.cpp?rev=240567&r1=240566&r2=240567&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Globals.cpp (original)
+++ llvm/trunk/lib/IR/Globals.cpp Wed Jun 24 13:55:24 2015
@@ -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

Modified: llvm/trunk/lib/IR/Value.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Value.cpp?rev=240567&r1=240566&r2=240567&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Value.cpp (original)
+++ llvm/trunk/lib/IR/Value.cpp Wed Jun 24 13:55:24 2015
@@ -369,7 +369,7 @@ void Value::replaceAllUsesWith(Value *Ne
     // 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;
       }
     }





More information about the llvm-commits mailing list