[llvm] r215981 - Reverting r215966, r215965, r215964, r215963, r215960, r215959, r215958, and r215957 (these commits all rely on previous commits) due to build breakage. These commits cause failed assertions when testing Clang using MSVC 2013. The asserts are triggered from the std::equal call within ArrayRef::equals due to being passed invalid input (ArrayRef.begin() is returning a nullptr which is problematic).

Aaron Ballman aaron at aaronballman.com
Tue Aug 19 07:59:03 PDT 2014


Author: aaronballman
Date: Tue Aug 19 09:59:02 2014
New Revision: 215981

URL: http://llvm.org/viewvc/llvm-project?rev=215981&view=rev
Log:
Reverting r215966, r215965, r215964, r215963, r215960, r215959, r215958, and r215957 (these commits all rely on previous commits) due to build breakage. These commits cause failed assertions when testing Clang using MSVC 2013. The asserts are triggered from the std::equal call within ArrayRef::equals due to being passed invalid input (ArrayRef.begin() is returning a nullptr which is problematic).

Modified:
    llvm/trunk/include/llvm/IR/Constant.h
    llvm/trunk/include/llvm/IR/Constants.h
    llvm/trunk/include/llvm/IR/InlineAsm.h
    llvm/trunk/lib/IR/Constants.cpp
    llvm/trunk/lib/IR/ConstantsContext.h
    llvm/trunk/lib/IR/LLVMContextImpl.cpp
    llvm/trunk/lib/IR/LLVMContextImpl.h
    llvm/trunk/unittests/IR/ConstantsTest.cpp

Modified: llvm/trunk/include/llvm/IR/Constant.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constant.h?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Constant.h (original)
+++ llvm/trunk/include/llvm/IR/Constant.h Tue Aug 19 09:59:02 2014
@@ -48,8 +48,6 @@ protected:
     : User(ty, vty, Ops, NumOps) {}
 
   void destroyConstantImpl();
-  void replaceUsesOfWithOnConstantImpl(Constant *Replacement);
-
 public:
   /// isNullValue - Return true if this is the value that would be returned by
   /// getNullValue.

Modified: llvm/trunk/include/llvm/IR/Constants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constants.h?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Constants.h (original)
+++ llvm/trunk/include/llvm/IR/Constants.h Tue Aug 19 09:59:02 2014
@@ -37,8 +37,12 @@ class PointerType;
 class VectorType;
 class SequentialType;
 
-struct ConstantExprKeyType;
-template <class ConstantClass> struct ConstantAggrKeyType;
+template<class ConstantClass, class TypeClass, class ValType>
+struct ConstantCreator;
+template<class ConstantClass, class TypeClass>
+struct ConstantArrayCreator;
+template<class ConstantClass, class TypeClass>
+struct ConvertConstantType;
 
 //===----------------------------------------------------------------------===//
 /// This is the shared class of boolean and integer constants. This class
@@ -334,7 +338,7 @@ public:
 /// ConstantArray - Constant Array Declarations
 ///
 class ConstantArray : public Constant {
-  friend struct ConstantAggrKeyType<ConstantArray>;
+  friend struct ConstantArrayCreator<ConstantArray, ArrayType>;
   ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION;
 protected:
   ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
@@ -342,10 +346,6 @@ public:
   // ConstantArray accessors
   static Constant *get(ArrayType *T, ArrayRef<Constant*> V);
 
-private:
-  static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V);
-
-public:
   /// Transparently provide more efficient getOperand methods.
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
 
@@ -376,7 +376,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Con
 // ConstantStruct - Constant Struct Declarations
 //
 class ConstantStruct : public Constant {
-  friend struct ConstantAggrKeyType<ConstantStruct>;
+  friend struct ConstantArrayCreator<ConstantStruct, StructType>;
   ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION;
 protected:
   ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
@@ -435,7 +435,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Con
 /// ConstantVector - Constant Vector Declarations
 ///
 class ConstantVector : public Constant {
-  friend struct ConstantAggrKeyType<ConstantVector>;
+  friend struct ConstantArrayCreator<ConstantVector, VectorType>;
   ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION;
 protected:
   ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
@@ -443,10 +443,6 @@ public:
   // ConstantVector accessors
   static Constant *get(ArrayRef<Constant*> V);
 
-private:
-  static Constant *getImpl(ArrayRef<Constant *> V);
-
-public:
   /// getSplat - Return a ConstantVector with the specified constant in each
   /// element.
   static Constant *getSplat(unsigned NumElts, Constant *Elt);
@@ -798,7 +794,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Blo
 /// constant expressions.  The Opcode field for the ConstantExpr class is
 /// maintained in the Value::SubclassData field.
 class ConstantExpr : public Constant {
-  friend struct ConstantExprKeyType;
+  friend struct ConstantCreator<ConstantExpr,Type,
+                            std::pair<unsigned, std::vector<Constant*> > >;
+  friend struct ConvertConstantType<ConstantExpr, Type>;
 
 protected:
   ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps)
@@ -1115,12 +1113,6 @@ 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/include/llvm/IR/InlineAsm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InlineAsm.h?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/InlineAsm.h (original)
+++ llvm/trunk/include/llvm/IR/InlineAsm.h Tue Aug 19 09:59:02 2014
@@ -25,9 +25,12 @@ namespace llvm {
 class PointerType;
 class FunctionType;
 class Module;
-
 struct InlineAsmKeyType;
-template <class ConstantClass> class ConstantUniqueMap;
+template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
+         bool HasLargeKey>
+class ConstantUniqueMap;
+template<class ConstantClass, class TypeClass, class ValType>
+struct ConstantCreator;
 
 class InlineAsm : public Value {
 public:
@@ -37,8 +40,9 @@ public:
   };
 
 private:
-  friend struct InlineAsmKeyType;
-  friend class ConstantUniqueMap<InlineAsm>;
+  friend struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType>;
+  friend class ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&,
+                                 PointerType, InlineAsm, false>;
 
   InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION;
   void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION;

Modified: llvm/trunk/lib/IR/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Constants.cpp (original)
+++ llvm/trunk/lib/IR/Constants.cpp Tue Aug 19 09:59:02 2014
@@ -803,11 +803,6 @@ ConstantArray::ConstantArray(ArrayType *
 }
 
 Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
-  if (Constant *C = getImpl(Ty, V))
-    return C;
-  return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V);
-}
-Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
   // Empty arrays are canonicalized to ConstantAggregateZero.
   if (V.empty())
     return ConstantAggregateZero::get(Ty);
@@ -816,6 +811,7 @@ Constant *ConstantArray::getImpl(ArrayTy
     assert(V[i]->getType() == Ty->getElementType() &&
            "Wrong type in array element initializer");
   }
+  LLVMContextImpl *pImpl = Ty->getContext().pImpl;
 
   // If this is an all-zero array, return a ConstantAggregateZero object.  If
   // all undef, return an UndefValue, if "all simple", then return a
@@ -897,7 +893,7 @@ Constant *ConstantArray::getImpl(ArrayTy
   }
 
   // Otherwise, we really do want to create a ConstantArray.
-  return nullptr;
+  return pImpl->ArrayConstants.getOrCreate(Ty, V);
 }
 
 /// getTypeForElements - Return an anonymous struct type to use for a constant
@@ -985,14 +981,9 @@ ConstantVector::ConstantVector(VectorTyp
 
 // ConstantVector accessors.
 Constant *ConstantVector::get(ArrayRef<Constant*> V) {
-  if (Constant *C = getImpl(V))
-    return C;
-  VectorType *Ty = VectorType::get(V.front()->getType(), V.size());
-  return Ty->getContext().pImpl->VectorConstants.getOrCreate(Ty, V);
-}
-Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
   assert(!V.empty() && "Vectors can't be empty");
   VectorType *T = VectorType::get(V.front()->getType(), V.size());
+  LLVMContextImpl *pImpl = T->getContext().pImpl;
 
   // If this is an all-undef or all-zero vector, return a
   // ConstantAggregateZero or UndefValue.
@@ -1084,7 +1075,7 @@ Constant *ConstantVector::getImpl(ArrayR
 
   // Otherwise, the element type isn't compatible with ConstantDataVector, or
   // the operand list constants a ConstantExpr or something else strange.
-  return nullptr;
+  return pImpl->VectorConstants.getOrCreate(T, V);
 }
 
 Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) {
@@ -1478,21 +1469,27 @@ void BlockAddress::replaceUsesOfWithOnCo
   // and return early.
   BlockAddress *&NewBA =
     getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)];
-  if (NewBA) {
-    replaceUsesOfWithOnConstantImpl(NewBA);
+  if (!NewBA) {
+    getBasicBlock()->AdjustBlockAddressRefCount(-1);
+
+    // Remove the old entry, this can't cause the map to rehash (just a
+    // tombstone will get added).
+    getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(),
+                                                            getBasicBlock()));
+    NewBA = this;
+    setOperand(0, NewF);
+    setOperand(1, NewBB);
+    getBasicBlock()->AdjustBlockAddressRefCount(1);
     return;
   }
 
-  getBasicBlock()->AdjustBlockAddressRefCount(-1);
+  // Otherwise, I do need to replace this with an existing value.
+  assert(NewBA != this && "I didn't contain From!");
+
+  // Everyone using this now uses the replacement.
+  replaceAllUsesWith(NewBA);
 
-  // Remove the old entry, this can't cause the map to rehash (just a
-  // tombstone will get added).
-  getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(),
-                                                          getBasicBlock()));
-  NewBA = this;
-  setOperand(0, NewF);
-  setOperand(1, NewBB);
-  getBasicBlock()->AdjustBlockAddressRefCount(1);
+  destroyConstant();
 }
 
 //---- ConstantExpr::get() implementations.
@@ -1510,7 +1507,7 @@ static inline Constant *getFoldedCast(
   LLVMContextImpl *pImpl = Ty->getContext().pImpl;
 
   // Look up the constant in the table first to ensure uniqueness.
-  ConstantExprKeyType Key(opc, C);
+  ExprMapKeyType Key(opc, C);
 
   return pImpl->ExprConstants.getOrCreate(Ty, Key);
 }
@@ -1845,7 +1842,7 @@ Constant *ConstantExpr::get(unsigned Opc
     return FC;          // Fold a few common cases.
 
   Constant *ArgVec[] = { C1, C2 };
-  ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags);
+  ExprMapKeyType Key(Opcode, ArgVec, 0, Flags);
 
   LLVMContextImpl *pImpl = C1->getContext().pImpl;
   return pImpl->ExprConstants.getOrCreate(C1->getType(), Key);
@@ -1922,7 +1919,7 @@ Constant *ConstantExpr::getSelect(Consta
     return SC;        // Fold common cases
 
   Constant *ArgVec[] = { C, V1, V2 };
-  ConstantExprKeyType Key(Instruction::Select, ArgVec);
+  ExprMapKeyType Key(Instruction::Select, ArgVec);
 
   LLVMContextImpl *pImpl = C->getContext().pImpl;
   return pImpl->ExprConstants.getOrCreate(V1->getType(), Key);
@@ -1957,8 +1954,8 @@ Constant *ConstantExpr::getGetElementPtr
            "getelementptr index type missmatch");
     ArgVec.push_back(cast<Constant>(Idxs[i]));
   }
-  const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
-                                InBounds ? GEPOperator::IsInBounds : 0);
+  const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
+                           InBounds ? GEPOperator::IsInBounds : 0);
 
   LLVMContextImpl *pImpl = C->getContext().pImpl;
   return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
@@ -1976,7 +1973,7 @@ ConstantExpr::getICmp(unsigned short pre
   // Look up the constant in the table first to ensure uniqueness
   Constant *ArgVec[] = { LHS, RHS };
   // Get the key type with both the opcode and predicate
-  const ConstantExprKeyType Key(Instruction::ICmp, ArgVec, pred);
+  const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred);
 
   Type *ResultTy = Type::getInt1Ty(LHS->getContext());
   if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
@@ -1997,7 +1994,7 @@ ConstantExpr::getFCmp(unsigned short pre
   // Look up the constant in the table first to ensure uniqueness
   Constant *ArgVec[] = { LHS, RHS };
   // Get the key type with both the opcode and predicate
-  const ConstantExprKeyType Key(Instruction::FCmp, ArgVec, pred);
+  const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred);
 
   Type *ResultTy = Type::getInt1Ty(LHS->getContext());
   if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
@@ -2018,7 +2015,7 @@ Constant *ConstantExpr::getExtractElemen
 
   // Look up the constant in the table first to ensure uniqueness
   Constant *ArgVec[] = { Val, Idx };
-  const ConstantExprKeyType Key(Instruction::ExtractElement, ArgVec);
+  const ExprMapKeyType Key(Instruction::ExtractElement, ArgVec);
 
   LLVMContextImpl *pImpl = Val->getContext().pImpl;
   Type *ReqTy = Val->getType()->getVectorElementType();
@@ -2038,7 +2035,7 @@ Constant *ConstantExpr::getInsertElement
     return FC;          // Fold a few common cases.
   // Look up the constant in the table first to ensure uniqueness
   Constant *ArgVec[] = { Val, Elt, Idx };
-  const ConstantExprKeyType Key(Instruction::InsertElement, ArgVec);
+  const ExprMapKeyType Key(Instruction::InsertElement, ArgVec);
 
   LLVMContextImpl *pImpl = Val->getContext().pImpl;
   return pImpl->ExprConstants.getOrCreate(Val->getType(), Key);
@@ -2058,7 +2055,7 @@ Constant *ConstantExpr::getShuffleVector
 
   // Look up the constant in the table first to ensure uniqueness
   Constant *ArgVec[] = { V1, V2, Mask };
-  const ConstantExprKeyType Key(Instruction::ShuffleVector, ArgVec);
+  const ExprMapKeyType Key(Instruction::ShuffleVector, ArgVec);
 
   LLVMContextImpl *pImpl = ShufTy->getContext().pImpl;
   return pImpl->ExprConstants.getOrCreate(ShufTy, Key);
@@ -2078,7 +2075,7 @@ Constant *ConstantExpr::getInsertValue(C
     return FC;
 
   Constant *ArgVec[] = { Agg, Val };
-  const ConstantExprKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs);
+  const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs);
 
   LLVMContextImpl *pImpl = Agg->getContext().pImpl;
   return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
@@ -2099,7 +2096,7 @@ Constant *ConstantExpr::getExtractValue(
     return FC;
 
   Constant *ArgVec[] = { Agg };
-  const ConstantExprKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs);
+  const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs);
 
   LLVMContextImpl *pImpl = Agg->getContext().pImpl;
   return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
@@ -2655,17 +2652,6 @@ Constant *ConstantDataVector::getSplatVa
 /// work, but would be really slow because it would have to unique each updated
 /// array instance.
 ///
-void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) {
-  // I do need to replace this with an existing value.
-  assert(Replacement != this && "I didn't contain From!");
-
-  // Everyone using this now uses the replacement.
-  replaceAllUsesWith(Replacement);
-
-  // Delete the old constant!
-  destroyConstant();
-}
-
 void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
                                                 Use *U) {
   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
@@ -2692,51 +2678,52 @@ void ConstantArray::replaceUsesOfWithOnC
     AllSame &= Val == ToC;
   }
 
+  Constant *Replacement = nullptr;
   if (AllSame && ToC->isNullValue()) {
-    replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
-    return;
-  }
-  if (AllSame && isa<UndefValue>(ToC)) {
-    replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
-    return;
-  }
-
-  // Check for any other type of constant-folding.
-  if (Constant *C = getImpl(getType(), Values)) {
-    replaceUsesOfWithOnConstantImpl(C);
-    return;
+    Replacement = ConstantAggregateZero::get(getType());
+  } else if (AllSame && isa<UndefValue>(ToC)) {
+    Replacement = UndefValue::get(getType());
+  } else {
+    // Check to see if we have this array type already.
+    LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup(
+        cast<ArrayType>(getType()), makeArrayRef(Values));
+    LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I =
+      pImpl->ArrayConstants.find(Lookup);
+
+    if (I != pImpl->ArrayConstants.map_end()) {
+      Replacement = I->first;
+    } else {
+      // Okay, the new shape doesn't exist in the system yet.  Instead of
+      // creating a new constant array, inserting it, replaceallusesof'ing the
+      // old with the new, then deleting the old... just update the current one
+      // in place!
+      pImpl->ArrayConstants.remove(this);
+
+      // Update to the new value.  Optimize for the case when we have a single
+      // operand that we're changing, but handle bulk updates efficiently.
+      if (NumUpdated == 1) {
+        unsigned OperandToUpdate = U - OperandList;
+        assert(getOperand(OperandToUpdate) == From &&
+               "ReplaceAllUsesWith broken!");
+        setOperand(OperandToUpdate, ToC);
+      } else {
+        for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
+          if (getOperand(i) == From)
+            setOperand(i, ToC);
+      }
+      pImpl->ArrayConstants.insert(this);
+      return;
+    }
   }
 
-  // Check to see if we have this array type already.
-  LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup(
-    cast<ArrayType>(getType()), makeArrayRef(Values));
-  LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I =
-    pImpl->ArrayConstants.find(Lookup);
+  // Otherwise, I do need to replace this with an existing value.
+  assert(Replacement != this && "I didn't contain From!");
 
-  if (I != pImpl->ArrayConstants.map_end()) {
-    replaceUsesOfWithOnConstantImpl(I->first);
-    return;
-  }
+  // Everyone using this now uses the replacement.
+  replaceAllUsesWith(Replacement);
 
-  // Okay, the new shape doesn't exist in the system yet.  Instead of
-  // creating a new constant array, inserting it, replaceallusesof'ing the
-  // old with the new, then deleting the old... just update the current one
-  // in place!
-  pImpl->ArrayConstants.remove(this);
-
-  // Update to the new value.  Optimize for the case when we have a single
-  // operand that we're changing, but handle bulk updates efficiently.
-  if (NumUpdated == 1) {
-    unsigned OperandToUpdate = U - OperandList;
-    assert(getOperand(OperandToUpdate) == From &&
-           "ReplaceAllUsesWith broken!");
-    setOperand(OperandToUpdate, ToC);
-  } else {
-    for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
-      if (getOperand(I) == From)
-        setOperand(I, ToC);
-  }
-  pImpl->ArrayConstants.insert(this);
+  // Delete the old constant!
+  destroyConstant();
 }
 
 void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
@@ -2776,75 +2763,63 @@ void ConstantStruct::replaceUsesOfWithOn
 
   LLVMContextImpl *pImpl = getContext().pImpl;
 
+  Constant *Replacement = nullptr;
   if (isAllZeros) {
-    replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
-    return;
-  }
-  if (isAllUndef) {
-    replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
-    return;
-  }
-
-  // Check to see if we have this struct type already.
-  LLVMContextImpl::StructConstantsTy::LookupKey Lookup(
-      cast<StructType>(getType()), makeArrayRef(Values));
-  LLVMContextImpl::StructConstantsTy::MapTy::iterator I =
+    Replacement = ConstantAggregateZero::get(getType());
+  } else if (isAllUndef) {
+    Replacement = UndefValue::get(getType());
+  } else {
+    // Check to see if we have this struct type already.
+    LLVMContextImpl::StructConstantsTy::LookupKey Lookup(
+        cast<StructType>(getType()), makeArrayRef(Values));
+    LLVMContextImpl::StructConstantsTy::MapTy::iterator I =
       pImpl->StructConstants.find(Lookup);
 
-  if (I != pImpl->StructConstants.map_end()) {
-    replaceUsesOfWithOnConstantImpl(I->first);
-    return;
+    if (I != pImpl->StructConstants.map_end()) {
+      Replacement = I->first;
+    } else {
+      // Okay, the new shape doesn't exist in the system yet.  Instead of
+      // creating a new constant struct, inserting it, replaceallusesof'ing the
+      // old with the new, then deleting the old... just update the current one
+      // in place!
+      pImpl->StructConstants.remove(this);
+
+      // Update to the new value.
+      setOperand(OperandToUpdate, ToC);
+      pImpl->StructConstants.insert(this);
+      return;
+    }
   }
 
-  // Okay, the new shape doesn't exist in the system yet.  Instead of
-  // creating a new constant struct, inserting it, replaceallusesof'ing the
-  // old with the new, then deleting the old... just update the current one
-  // in place!
-  pImpl->StructConstants.remove(this);
-
-  // Update to the new value.
-  setOperand(OperandToUpdate, ToC);
-  pImpl->StructConstants.insert(this);
+  assert(Replacement != this && "I didn't contain From!");
+
+  // Everyone using this now uses the replacement.
+  replaceAllUsesWith(Replacement);
+
+  // Delete the old constant!
+  destroyConstant();
 }
 
 void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
                                                  Use *U) {
   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
-  Constant *ToC = cast<Constant>(To);
 
   SmallVector<Constant*, 8> Values;
   Values.reserve(getNumOperands());  // Build replacement array...
-  unsigned NumUpdated = 0;
   for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
     Constant *Val = getOperand(i);
-    if (Val == From) {
-      ++NumUpdated;
-      Val = ToC;
-    }
+    if (Val == From) Val = cast<Constant>(To);
     Values.push_back(Val);
   }
 
-  if (Constant *C = getImpl(Values)) {
-    replaceUsesOfWithOnConstantImpl(C);
-    return;
-  }
+  Constant *Replacement = get(Values);
+  assert(Replacement != this && "I didn't contain From!");
 
-  // Update to the new value.  Optimize for the case when we have a single
-  // operand that we're changing, but handle bulk updates efficiently.
-  auto &pImpl = getType()->getContext().pImpl;
-  pImpl->VectorConstants.remove(this);
-
-  if (NumUpdated == 1) {
-    unsigned OperandToUpdate = U - OperandList;
-    assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
-    setOperand(OperandToUpdate, ToC);
-  } else {
-    for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
-      if (getOperand(I) == From)
-        setOperand(I, ToC);
-  }
+  // Everyone using this now uses the replacement.
+  replaceAllUsesWith(Replacement);
 
-  pImpl->VectorConstants.insert(this);
+  // Delete the old constant!
+  destroyConstant();
 }
 
 void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
@@ -2861,25 +2836,6 @@ 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);
 
@@ -2887,31 +2843,6 @@ 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)

Modified: llvm/trunk/lib/IR/ConstantsContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantsContext.h?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantsContext.h (original)
+++ llvm/trunk/lib/IR/ConstantsContext.h Tue Aug 19 09:59:02 2014
@@ -29,6 +29,8 @@
 #define DEBUG_TYPE "ir"
 
 namespace llvm {
+template<class ValType>
+struct ConstantTraits;
 
 /// UnaryConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement unary constant exprs.
@@ -312,234 +314,379 @@ struct OperandTraits<CompareConstantExpr
 };
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
 
-template <class ConstantClass> struct ConstantAggrKeyType;
-struct InlineAsmKeyType;
-struct ConstantExprKeyType;
-
-template <class ConstantClass> struct ConstantInfo;
-template <> struct ConstantInfo<ConstantExpr> {
-  typedef ConstantExprKeyType ValType;
-  typedef Type TypeClass;
+struct ExprMapKeyType {
+  ExprMapKeyType(unsigned opc,
+      ArrayRef<Constant*> ops,
+      unsigned short flags = 0,
+      unsigned short optionalflags = 0,
+      ArrayRef<unsigned> inds = None)
+        : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags),
+        operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {}
+  uint8_t opcode;
+  uint8_t subclassoptionaldata;
+  uint16_t subclassdata;
+  std::vector<Constant*> operands;
+  SmallVector<unsigned, 4> indices;
+  bool operator==(const ExprMapKeyType& that) const {
+    return this->opcode == that.opcode &&
+           this->subclassdata == that.subclassdata &&
+           this->subclassoptionaldata == that.subclassoptionaldata &&
+           this->operands == that.operands &&
+           this->indices == that.indices;
+  }
+  bool operator<(const ExprMapKeyType & that) const {
+    return std::tie(opcode, operands, subclassdata, subclassoptionaldata,
+                    indices) <
+           std::tie(that.opcode, that.operands, that.subclassdata,
+                    that.subclassoptionaldata, that.indices);
+  }
+
+  bool operator!=(const ExprMapKeyType& that) const {
+    return !(*this == that);
+  }
 };
-template <> struct ConstantInfo<InlineAsm> {
-  typedef InlineAsmKeyType ValType;
-  typedef PointerType TypeClass;
+
+struct InlineAsmKeyType {
+  InlineAsmKeyType(StringRef AsmString,
+                   StringRef Constraints, bool hasSideEffects,
+                   bool isAlignStack, InlineAsm::AsmDialect asmDialect)
+    : asm_string(AsmString), constraints(Constraints),
+      has_side_effects(hasSideEffects), is_align_stack(isAlignStack),
+      asm_dialect(asmDialect) {}
+  std::string asm_string;
+  std::string constraints;
+  bool has_side_effects;
+  bool is_align_stack;
+  InlineAsm::AsmDialect asm_dialect;
+  bool operator==(const InlineAsmKeyType& that) const {
+    return this->asm_string == that.asm_string &&
+           this->constraints == that.constraints &&
+           this->has_side_effects == that.has_side_effects &&
+           this->is_align_stack == that.is_align_stack &&
+           this->asm_dialect == that.asm_dialect;
+  }
+  bool operator<(const InlineAsmKeyType& that) const {
+    return std::tie(asm_string, constraints, has_side_effects, is_align_stack,
+                    asm_dialect) <
+           std::tie(that.asm_string, that.constraints, that.has_side_effects,
+                    that.is_align_stack, that.asm_dialect);
+  }
+
+  bool operator!=(const InlineAsmKeyType& that) const {
+    return !(*this == that);
+  }
+};
+
+// The number of operands for each ConstantCreator::create method is
+// determined by the ConstantTraits template.
+// ConstantCreator - A class that is used to create constants by
+// ConstantUniqueMap*.  This class should be partially specialized if there is
+// something strange that needs to be done to interface to the ctor for the
+// constant.
+//
+template<typename T, typename Alloc>
+struct ConstantTraits< std::vector<T, Alloc> > {
+  static unsigned uses(const std::vector<T, Alloc>& v) {
+    return v.size();
+  }
+};
+
+template<>
+struct ConstantTraits<Constant *> {
+  static unsigned uses(Constant * const & v) {
+    return 1;
+  }
+};
+
+template<class ConstantClass, class TypeClass, class ValType>
+struct ConstantCreator {
+  static ConstantClass *create(TypeClass *Ty, const ValType &V) {
+    return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
+  }
+};
+
+template<class ConstantClass, class TypeClass>
+struct ConstantArrayCreator {
+  static ConstantClass *create(TypeClass *Ty, ArrayRef<Constant*> V) {
+    return new(V.size()) ConstantClass(Ty, V);
+  }
+};
+
+template<class ConstantClass>
+struct ConstantKeyData {
+  typedef void ValType;
+  static ValType getValType(ConstantClass *C) {
+    llvm_unreachable("Unknown Constant type!");
+  }
+};
+
+template<>
+struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
+  static ConstantExpr *create(Type *Ty, const ExprMapKeyType &V,
+      unsigned short pred = 0) {
+    if (Instruction::isCast(V.opcode))
+      return new UnaryConstantExpr(V.opcode, V.operands[0], Ty);
+    if ((V.opcode >= Instruction::BinaryOpsBegin &&
+         V.opcode < Instruction::BinaryOpsEnd))
+      return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1],
+                                    V.subclassoptionaldata);
+    if (V.opcode == Instruction::Select)
+      return new SelectConstantExpr(V.operands[0], V.operands[1], 
+                                    V.operands[2]);
+    if (V.opcode == Instruction::ExtractElement)
+      return new ExtractElementConstantExpr(V.operands[0], V.operands[1]);
+    if (V.opcode == Instruction::InsertElement)
+      return new InsertElementConstantExpr(V.operands[0], V.operands[1],
+                                           V.operands[2]);
+    if (V.opcode == Instruction::ShuffleVector)
+      return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1],
+                                           V.operands[2]);
+    if (V.opcode == Instruction::InsertValue)
+      return new InsertValueConstantExpr(V.operands[0], V.operands[1],
+                                         V.indices, Ty);
+    if (V.opcode == Instruction::ExtractValue)
+      return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
+    if (V.opcode == Instruction::GetElementPtr) {
+      std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
+      return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty,
+                                               V.subclassoptionaldata);
+    }
+
+    // The compare instructions are weird. We have to encode the predicate
+    // value and it is combined with the instruction opcode by multiplying
+    // the opcode by one hundred. We must decode this to get the predicate.
+    if (V.opcode == Instruction::ICmp)
+      return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata,
+                                     V.operands[0], V.operands[1]);
+    if (V.opcode == Instruction::FCmp) 
+      return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata,
+                                     V.operands[0], V.operands[1]);
+    llvm_unreachable("Invalid ConstantExpr!");
+  }
 };
-template <> struct ConstantInfo<ConstantArray> {
-  typedef ConstantAggrKeyType<ConstantArray> ValType;
-  typedef ArrayType TypeClass;
-};
-template <> struct ConstantInfo<ConstantStruct> {
-  typedef ConstantAggrKeyType<ConstantStruct> ValType;
-  typedef StructType TypeClass;
-};
-template <> struct ConstantInfo<ConstantVector> {
-  typedef ConstantAggrKeyType<ConstantVector> ValType;
-  typedef VectorType TypeClass;
-};
-
-template <class ConstantClass> struct ConstantAggrKeyType {
-  ArrayRef<Constant *> Operands;
-  ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
-  ConstantAggrKeyType(const ConstantClass *C,
-                      SmallVectorImpl<Constant *> &Storage) {
-    assert(Storage.empty() && "Expected empty storage");
-    for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
-      Storage.push_back(C->getOperand(I));
-    Operands = Storage;
-  }
-
-  bool operator==(const ConstantAggrKeyType &X) const {
-    return Operands == X.Operands;
-  }
-  bool operator==(const ConstantClass *C) const {
-    if (Operands.size() != C->getNumOperands())
-      return false;
-    for (unsigned I = 0, E = Operands.size(); I != E; ++I)
-      if (Operands[I] != C->getOperand(I))
-        return false;
-    return true;
+
+template<>
+struct ConstantKeyData<ConstantExpr> {
+  typedef ExprMapKeyType ValType;
+  static ValType getValType(ConstantExpr *CE) {
+    std::vector<Constant*> Operands;
+    Operands.reserve(CE->getNumOperands());
+    for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
+      Operands.push_back(cast<Constant>(CE->getOperand(i)));
+    return ExprMapKeyType(CE->getOpcode(), Operands,
+        CE->isCompare() ? CE->getPredicate() : 0,
+        CE->getRawSubclassOptionalData(),
+        CE->hasIndices() ?
+          CE->getIndices() : ArrayRef<unsigned>());
   }
-  unsigned getHash() const {
-    return hash_combine_range(Operands.begin(), Operands.end());
+};
+
+template<>
+struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType> {
+  static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) {
+    return new InlineAsm(Ty, Key.asm_string, Key.constraints,
+                         Key.has_side_effects, Key.is_align_stack,
+                         Key.asm_dialect);
   }
+};
 
-  typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass;
-  ConstantClass *create(TypeClass *Ty) const {
-    return new (Operands.size()) ConstantClass(Ty, Operands);
+template<>
+struct ConstantKeyData<InlineAsm> {
+  typedef InlineAsmKeyType ValType;
+  static ValType getValType(InlineAsm *Asm) {
+    return InlineAsmKeyType(Asm->getAsmString(), Asm->getConstraintString(),
+                            Asm->hasSideEffects(), Asm->isAlignStack(),
+                            Asm->getDialect());
   }
 };
 
-struct InlineAsmKeyType {
-  StringRef AsmString;
-  StringRef Constraints;
-  bool HasSideEffects;
-  bool IsAlignStack;
-  InlineAsm::AsmDialect AsmDialect;
-
-  InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
-                   bool HasSideEffects, bool IsAlignStack,
-                   InlineAsm::AsmDialect AsmDialect)
-      : AsmString(AsmString), Constraints(Constraints),
-        HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
-        AsmDialect(AsmDialect) {}
-  InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
-      : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
-        HasSideEffects(Asm->hasSideEffects()),
-        IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {}
-
-  bool operator==(const InlineAsmKeyType &X) const {
-    return HasSideEffects == X.HasSideEffects &&
-           IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
-           AsmString == X.AsmString && Constraints == X.Constraints;
-  }
-  bool operator==(const InlineAsm *Asm) const {
-    return HasSideEffects == Asm->hasSideEffects() &&
-           IsAlignStack == Asm->isAlignStack() &&
-           AsmDialect == Asm->getDialect() &&
-           AsmString == Asm->getAsmString() &&
-           Constraints == Asm->getConstraintString();
-  }
-  unsigned getHash() const {
-    return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,
-                        AsmDialect);
-  }
-
-  typedef ConstantInfo<InlineAsm>::TypeClass TypeClass;
-  InlineAsm *create(TypeClass *Ty) const {
-    return new InlineAsm(Ty, AsmString, Constraints, HasSideEffects,
-                         IsAlignStack, AsmDialect);
-  }
-};
-
-struct ConstantExprKeyType {
-  uint8_t Opcode;
-  uint8_t SubclassOptionalData;
-  uint16_t SubclassData;
-  ArrayRef<Constant *> Ops;
-  ArrayRef<unsigned> Indexes;
-
-  ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
-                      unsigned short SubclassData = 0,
-                      unsigned short SubclassOptionalData = 0,
-                      ArrayRef<unsigned> Indexes = None)
-      : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData),
-        SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {}
-  ConstantExprKeyType(const ConstantExpr *CE,
-                      SmallVectorImpl<Constant *> &Storage)
-      : Opcode(CE->getOpcode()),
-        SubclassOptionalData(CE->getRawSubclassOptionalData()),
-        SubclassData(CE->isCompare() ? CE->getPredicate() : 0),
-        Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()) {
-    assert(Storage.empty() && "Expected empty storage");
-    for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
-      Storage.push_back(CE->getOperand(I));
-    Ops = Storage;
-  }
-
-  bool operator==(const ConstantExprKeyType &X) const {
-    return Opcode == X.Opcode && SubclassData == X.SubclassData &&
-           SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
-           Indexes == X.Indexes;
-  }
-
-  bool operator==(const ConstantExpr *CE) const {
-    if (Opcode != CE->getOpcode())
-      return false;
-    if (SubclassOptionalData != CE->getRawSubclassOptionalData())
-      return false;
-    if (Ops.size() != CE->getNumOperands())
-      return false;
-    if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0))
-      return false;
-    for (unsigned I = 0, E = Ops.size(); I != E; ++I)
-      if (Ops[I] != CE->getOperand(I))
-        return false;
-    if (Indexes != (CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()))
-      return false;
-    return true;
-  }
-
-  unsigned getHash() const {
-    return hash_combine(Opcode, SubclassOptionalData, SubclassData,
-                        hash_combine_range(Ops.begin(), Ops.end()),
-                        hash_combine_range(Indexes.begin(), Indexes.end()));
-  }
-
-  typedef ConstantInfo<ConstantExpr>::TypeClass TypeClass;
-  ConstantExpr *create(TypeClass *Ty) const {
-    switch (Opcode) {
-    default:
-      if (Instruction::isCast(Opcode))
-        return new UnaryConstantExpr(Opcode, Ops[0], Ty);
-      if ((Opcode >= Instruction::BinaryOpsBegin &&
-           Opcode < Instruction::BinaryOpsEnd))
-        return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
-                                      SubclassOptionalData);
-      llvm_unreachable("Invalid ConstantExpr!");
-    case Instruction::Select:
-      return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]);
-    case Instruction::ExtractElement:
-      return new ExtractElementConstantExpr(Ops[0], Ops[1]);
-    case Instruction::InsertElement:
-      return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
-    case Instruction::ShuffleVector:
-      return new ShuffleVectorConstantExpr(Ops[0], Ops[1], Ops[2]);
-    case Instruction::InsertValue:
-      return new InsertValueConstantExpr(Ops[0], Ops[1], Indexes, Ty);
-    case Instruction::ExtractValue:
-      return new ExtractValueConstantExpr(Ops[0], Indexes, Ty);
-    case Instruction::GetElementPtr:
-      return GetElementPtrConstantExpr::Create(Ops[0], Ops.slice(1), Ty,
-                                               SubclassOptionalData);
-    case Instruction::ICmp:
-      return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData,
-                                     Ops[0], Ops[1]);
-    case Instruction::FCmp:
-      return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData,
-                                     Ops[0], Ops[1]);
+template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
+         bool HasLargeKey = false /*true for arrays and structs*/ >
+class ConstantUniqueMap {
+public:
+  typedef std::pair<TypeClass*, ValType> MapKey;
+  typedef std::map<MapKey, ConstantClass *> MapTy;
+  typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy;
+private:
+  /// Map - This is the main map from the element descriptor to the Constants.
+  /// This is the primary way we avoid creating two of the same shape
+  /// constant.
+  MapTy Map;
+    
+  /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping
+  /// from the constants to their element in Map.  This is important for
+  /// removal of constants from the array, which would otherwise have to scan
+  /// through the map with very large keys.
+  InverseMapTy InverseMap;
+
+public:
+  typename MapTy::iterator map_begin() { return Map.begin(); }
+  typename MapTy::iterator map_end() { return Map.end(); }
+
+  void freeConstants() {
+    for (typename MapTy::iterator I=Map.begin(), E=Map.end();
+         I != E; ++I) {
+      // Asserts that use_empty().
+      delete I->second;
     }
   }
-};
+    
+  /// InsertOrGetItem - Return an iterator for the specified element.
+  /// If the element exists in the map, the returned iterator points to the
+  /// entry and Exists=true.  If not, the iterator points to the newly
+  /// inserted entry and returns Exists=false.  Newly inserted entries have
+  /// I->second == 0, and should be filled in.
+  typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, ConstantClass *>
+                                 &InsertVal,
+                                 bool &Exists) {
+    std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal);
+    Exists = !IP.second;
+    return IP.first;
+  }
+    
+private:
+  typename MapTy::iterator FindExistingElement(ConstantClass *CP) {
+    if (HasLargeKey) {
+      typename InverseMapTy::iterator IMI = InverseMap.find(CP);
+      assert(IMI != InverseMap.end() && IMI->second != Map.end() &&
+             IMI->second->second == CP &&
+             "InverseMap corrupt!");
+      return IMI->second;
+    }
+      
+    typename MapTy::iterator I =
+      Map.find(MapKey(static_cast<TypeClass*>(CP->getType()),
+                      ConstantKeyData<ConstantClass>::getValType(CP)));
+    if (I == Map.end() || I->second != CP) {
+      // FIXME: This should not use a linear scan.  If this gets to be a
+      // performance problem, someone should look at this.
+      for (I = Map.begin(); I != Map.end() && I->second != CP; ++I)
+        /* empty */;
+    }
+    return I;
+  }
 
-template <class ConstantClass> class ConstantUniqueMap {
-public:
-  typedef typename ConstantInfo<ConstantClass>::ValType ValType;
-  typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass;
-  typedef std::pair<TypeClass *, ValType> LookupKey;
+  ConstantClass *Create(TypeClass *Ty, ValRefType V,
+                        typename MapTy::iterator I) {
+    ConstantClass* Result =
+      ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V);
 
+    assert(Result->getType() == Ty && "Type specified is not correct!");
+    I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result));
+
+    if (HasLargeKey)  // Remember the reverse mapping if needed.
+      InverseMap.insert(std::make_pair(Result, I));
+
+    return Result;
+  }
+public:
+    
+  /// getOrCreate - Return the specified constant from the map, creating it if
+  /// necessary.
+  ConstantClass *getOrCreate(TypeClass *Ty, ValRefType V) {
+    MapKey Lookup(Ty, V);
+    ConstantClass* Result = nullptr;
+    
+    typename MapTy::iterator I = Map.find(Lookup);
+    // Is it in the map?  
+    if (I != Map.end())
+      Result = I->second;
+        
+    if (!Result) {
+      // If no preexisting value, create one now...
+      Result = Create(Ty, V, I);
+    }
+        
+    return Result;
+  }
+
+  void remove(ConstantClass *CP) {
+    typename MapTy::iterator I = FindExistingElement(CP);
+    assert(I != Map.end() && "Constant not found in constant table!");
+    assert(I->second == CP && "Didn't find correct element?");
+
+    if (HasLargeKey)  // Remember the reverse mapping if needed.
+      InverseMap.erase(CP);
+
+    Map.erase(I);
+  }
+
+  /// MoveConstantToNewSlot - If we are about to change C to be the element
+  /// specified by I, update our internal data structures to reflect this
+  /// fact.
+  void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) {
+    // First, remove the old location of the specified constant in the map.
+    typename MapTy::iterator OldI = FindExistingElement(C);
+    assert(OldI != Map.end() && "Constant not found in constant table!");
+    assert(OldI->second == C && "Didn't find correct element?");
+      
+     // Remove the old entry from the map.
+    Map.erase(OldI);
+    
+    // Update the inverse map so that we know that this constant is now
+    // located at descriptor I.
+    if (HasLargeKey) {
+      assert(I->second == C && "Bad inversemap entry!");
+      InverseMap[C] = I;
+    }
+  }
+
+  void dump() const {
+    DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
+  }
+};
+
+// Unique map for aggregate constants
+template<class TypeClass, class ConstantClass>
+class ConstantAggrUniqueMap {
+public:
+  typedef ArrayRef<Constant*> Operands;
+  typedef std::pair<TypeClass*, Operands> LookupKey;
 private:
   struct MapInfo {
-    typedef DenseMapInfo<ConstantClass *> ConstantClassInfo;
-    static inline ConstantClass *getEmptyKey() {
+    typedef DenseMapInfo<ConstantClass*> ConstantClassInfo;
+    typedef DenseMapInfo<Constant*> ConstantInfo;
+    typedef DenseMapInfo<TypeClass*> TypeClassInfo;
+    static inline ConstantClass* getEmptyKey() {
       return ConstantClassInfo::getEmptyKey();
     }
-    static inline ConstantClass *getTombstoneKey() {
+    static inline ConstantClass* getTombstoneKey() {
       return ConstantClassInfo::getTombstoneKey();
     }
     static unsigned getHashValue(const ConstantClass *CP) {
-      SmallVector<Constant *, 8> Storage;
-      return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
+      SmallVector<Constant*, 8> CPOperands;
+      CPOperands.reserve(CP->getNumOperands());
+      for (unsigned I = 0, E = CP->getNumOperands(); I < E; ++I)
+        CPOperands.push_back(CP->getOperand(I));
+      return getHashValue(LookupKey(CP->getType(), CPOperands));
     }
     static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
       return LHS == RHS;
     }
     static unsigned getHashValue(const LookupKey &Val) {
-      return hash_combine(Val.first, Val.second.getHash());
+      return hash_combine(Val.first, hash_combine_range(Val.second.begin(),
+                                                        Val.second.end()));
     }
     static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
       if (RHS == getEmptyKey() || RHS == getTombstoneKey())
         return false;
-      if (LHS.first != RHS->getType())
+      if (LHS.first != RHS->getType()
+          || LHS.second.size() != RHS->getNumOperands())
         return false;
-      return LHS.second == RHS;
+      for (unsigned I = 0, E = RHS->getNumOperands(); I < E; ++I) {
+        if (LHS.second[I] != RHS->getOperand(I))
+          return false;
+      }
+      return true;
     }
   };
-
 public:
   typedef DenseMap<ConstantClass *, char, MapInfo> MapTy;
 
 private:
+  /// Map - This is the main map from the element descriptor to the Constants.
+  /// This is the primary way we avoid creating two of the same shape
+  /// constant.
   MapTy Map;
 
 public:
@@ -547,33 +694,44 @@ public:
   typename MapTy::iterator map_end() { return Map.end(); }
 
   void freeConstants() {
-    for (auto &I : Map)
+    for (typename MapTy::iterator I=Map.begin(), E=Map.end();
+         I != E; ++I) {
       // Asserts that use_empty().
-      delete I.first;
+      delete I->first;
+    }
   }
 
 private:
-  ConstantClass *create(TypeClass *Ty, ValType V) {
-    ConstantClass *Result = V.create(Ty);
+  typename MapTy::iterator findExistingElement(ConstantClass *CP) {
+    return Map.find(CP);
+  }
+
+  ConstantClass *Create(TypeClass *Ty, Operands V, typename MapTy::iterator I) {
+    ConstantClass* Result =
+      ConstantArrayCreator<ConstantClass,TypeClass>::create(Ty, V);
 
     assert(Result->getType() == Ty && "Type specified is not correct!");
-    insert(Result);
+    Map[Result] = '\0';
 
     return Result;
   }
-
 public:
-  /// Return the specified constant from the map, creating it if necessary.
-  ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
+
+  /// getOrCreate - Return the specified constant from the map, creating it if
+  /// necessary.
+  ConstantClass *getOrCreate(TypeClass *Ty, Operands V) {
     LookupKey Lookup(Ty, V);
-    ConstantClass *Result = nullptr;
+    ConstantClass* Result = nullptr;
 
-    auto I = find(Lookup);
-    if (I == Map.end())
-      Result = create(Ty, V);
-    else
+    typename MapTy::iterator I = Map.find_as(Lookup);
+    // Is it in the map?
+    if (I != Map.end())
       Result = I->first;
-    assert(Result && "Unexpected nullptr");
+
+    if (!Result) {
+      // If no preexisting value, create one now...
+      Result = Create(Ty, V, I);
+    }
 
     return Result;
   }
@@ -584,17 +742,21 @@ public:
   }
 
   /// Insert the constant into its proper slot.
-  void insert(ConstantClass *CP) { Map[CP] = '\0'; }
+  void insert(ConstantClass *CP) {
+    Map[CP] = '\0';
+  }
 
   /// Remove this constant from the map
   void remove(ConstantClass *CP) {
-    typename MapTy::iterator I = Map.find(CP);
+    typename MapTy::iterator I = findExistingElement(CP);
     assert(I != Map.end() && "Constant not found in constant table!");
     assert(I->first == CP && "Didn't find correct element?");
     Map.erase(I);
   }
 
-  void dump() const { DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); }
+  void dump() const {
+    DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
+  }
 };
 
 } // end namespace llvm

Modified: llvm/trunk/lib/IR/LLVMContextImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.cpp (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.cpp Tue Aug 19 09:59:02 2014
@@ -75,7 +75,7 @@ LLVMContextImpl::~LLVMContextImpl() {
   // Free the constants.  This is important to do here to ensure that they are
   // freed before the LeakDetector is torn down.
   std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(),
-                DropFirst());
+                DropReferences());
   std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(),
                 DropFirst());
   std::for_each(StructConstants.map_begin(), StructConstants.map_end(),

Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Tue Aug 19 09:59:02 2014
@@ -272,13 +272,13 @@ public:
   
   DenseMap<Type*, ConstantAggregateZero*> CAZConstants;
 
-  typedef ConstantUniqueMap<ConstantArray> ArrayConstantsTy;
+  typedef ConstantAggrUniqueMap<ArrayType, ConstantArray> ArrayConstantsTy;
   ArrayConstantsTy ArrayConstants;
   
-  typedef ConstantUniqueMap<ConstantStruct> StructConstantsTy;
+  typedef ConstantAggrUniqueMap<StructType, ConstantStruct> StructConstantsTy;
   StructConstantsTy StructConstants;
   
-  typedef ConstantUniqueMap<ConstantVector> VectorConstantsTy;
+  typedef ConstantAggrUniqueMap<VectorType, ConstantVector> VectorConstantsTy;
   VectorConstantsTy VectorConstants;
   
   DenseMap<PointerType*, ConstantPointerNull*> CPNConstants;
@@ -289,10 +289,12 @@ public:
 
   DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
     BlockAddresses;
-  ConstantUniqueMap<ConstantExpr> ExprConstants;
-
-  ConstantUniqueMap<InlineAsm> InlineAsms;
+  ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr>
+    ExprConstants;
 
+  ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, PointerType,
+                    InlineAsm> InlineAsms;
+  
   ConstantInt *TheTrueVal;
   ConstantInt *TheFalseVal;
   

Modified: llvm/trunk/unittests/IR/ConstantsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ConstantsTest.cpp?rev=215981&r1=215980&r2=215981&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ConstantsTest.cpp (original)
+++ llvm/trunk/unittests/IR/ConstantsTest.cpp Tue Aug 19 09:59:02 2014
@@ -274,30 +274,5 @@ TEST(ConstantsTest, ReplaceWithConstantT
 
 #undef CHECK
 
-TEST(ConstantsTest, ConstantArrayReplaceWithConstant) {
-  LLVMContext Context;
-  std::unique_ptr<Module> M(new Module("MyModule", Context));
-
-  Type *IntTy = Type::getInt8Ty(Context);
-  ArrayType *ArrayTy = ArrayType::get(IntTy, 2);
-  Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0),
-                          ConstantInt::get(IntTy, 1)};
-  Constant *A01 = ConstantArray::get(ArrayTy, A01Vals);
-
-  Constant *Global = new GlobalVariable(*M, IntTy, false,
-                                        GlobalValue::ExternalLinkage, nullptr);
-  Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy);
-  Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt};
-  Constant *A0G = ConstantArray::get(ArrayTy, A0GVals);
-  ASSERT_NE(A01, A0G);
-
-  GlobalVariable *RefArray =
-      new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G);
-  ASSERT_EQ(A0G, RefArray->getInitializer());
-
-  GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1));
-  ASSERT_EQ(A01, RefArray->getInitializer());
-}
-
 }  // end anonymous namespace
 }  // end namespace llvm





More information about the llvm-commits mailing list