<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Dec 6, 2014 at 11:22 AM, Benjamin Kramer <span dir="ltr"><<a href="mailto:benny.kra@googlemail.com" target="_blank">benny.kra@googlemail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: d0k<br>
Date: Sat Dec  6 13:22:44 2014<br>
New Revision: 223588<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=223588&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=223588&view=rev</a><br>
Log:<br>
Make the DenseMap bucket type configurable and use a smaller bucket for DenseSet.<br></blockquote><div><br></div><div>Would it be possible/more natural to invert this relationship and implement DenseMap in terms of DenseSet instead of the other way around?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
DenseSet used to be implemented as DenseMap<Key, char>, which usually doubled<br>
the memory footprint of the map. Now we use a compressed set so the second<br>
element uses no memory at all. This required some surgery on DenseMap as<br>
all accesses to the bucket now have to go through methods; this should<br>
have no impact on the behavior of DenseMap though. The new default bucket<br>
type for DenseMap is a slightly extended std::pair as we expose it through<br>
DenseMap's iterator and don't want to break any existing users.<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/ADT/DenseMap.h<br>
    llvm/trunk/include/llvm/ADT/DenseSet.h<br>
    llvm/trunk/include/llvm/IR/Module.h<br>
    llvm/trunk/lib/Target/AArch64/AArch64PromoteConstant.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/ADT/DenseMap.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseMap.h?rev=223588&r1=223587&r2=223588&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseMap.h?rev=223588&r1=223587&r2=223588&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ADT/DenseMap.h (original)<br>
+++ llvm/trunk/include/llvm/ADT/DenseMap.h Sat Dec  6 13:22:44 2014<br>
@@ -31,26 +31,35 @@<br>
<br>
 namespace llvm {<br>
<br>
-template<typename KeyT, typename ValueT,<br>
-         typename KeyInfoT = DenseMapInfo<KeyT>,<br>
-         bool IsConst = false><br>
+namespace detail {<br>
+// We extend a pair to allow users to override the bucket type with their own<br>
+// implementation without requiring two members.<br>
+template <typename KeyT, typename ValueT><br>
+struct DenseMapPair : public std::pair<KeyT, ValueT> {<br>
+  KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }<br>
+  const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }<br>
+  ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }<br>
+  const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; }<br>
+};<br>
+}<br>
+<br>
+template <<br>
+    typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>,<br>
+    typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false><br>
 class DenseMapIterator;<br>
<br>
-template<typename DerivedT,<br>
-         typename KeyT, typename ValueT, typename KeyInfoT><br>
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,<br>
+          typename BucketT><br>
 class DenseMapBase {<br>
-protected:<br>
-  typedef std::pair<KeyT, ValueT> BucketT;<br>
-<br>
 public:<br>
   typedef unsigned size_type;<br>
   typedef KeyT key_type;<br>
   typedef ValueT mapped_type;<br>
   typedef BucketT value_type;<br>
<br>
-  typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator;<br>
-  typedef DenseMapIterator<KeyT, ValueT,<br>
-                           KeyInfoT, true> const_iterator;<br>
+  typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator;<br>
+  typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true><br>
+      const_iterator;<br>
   inline iterator begin() {<br>
     // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().<br>
     return empty() ? end() : iterator(getBuckets(), getBucketsEnd());<br>
@@ -88,12 +97,12 @@ public:<br>
<br>
     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();<br>
     for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {<br>
-      if (!KeyInfoT::isEqual(P->first, EmptyKey)) {<br>
-        if (!KeyInfoT::isEqual(P->first, TombstoneKey)) {<br>
-          P->second.~ValueT();<br>
+      if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {<br>
+        if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {<br>
+          P->getSecond().~ValueT();<br>
           decrementNumEntries();<br>
         }<br>
-        P->first = EmptyKey;<br>
+        P->getFirst() = EmptyKey;<br>
       }<br>
     }<br>
     assert(getNumEntries() == 0 && "Node count imbalance!");<br>
@@ -144,7 +153,7 @@ public:<br>
   ValueT lookup(const KeyT &Val) const {<br>
     const BucketT *TheBucket;<br>
     if (LookupBucketFor(Val, TheBucket))<br>
-      return TheBucket->second;<br>
+      return TheBucket->getSecond();<br>
     return ValueT();<br>
   }<br>
<br>
@@ -191,16 +200,16 @@ public:<br>
     if (!LookupBucketFor(Val, TheBucket))<br>
       return false; // not in map.<br>
<br>
-    TheBucket->second.~ValueT();<br>
-    TheBucket->first = getTombstoneKey();<br>
+    TheBucket->getSecond().~ValueT();<br>
+    TheBucket->getFirst() = getTombstoneKey();<br>
     decrementNumEntries();<br>
     incrementNumTombstones();<br>
     return true;<br>
   }<br>
   void erase(iterator I) {<br>
     BucketT *TheBucket = &*I;<br>
-    TheBucket->second.~ValueT();<br>
-    TheBucket->first = getTombstoneKey();<br>
+    TheBucket->getSecond().~ValueT();<br>
+    TheBucket->getFirst() = getTombstoneKey();<br>
     decrementNumEntries();<br>
     incrementNumTombstones();<br>
   }<br>
@@ -250,10 +259,10 @@ protected:<br>
<br>
     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();<br>
     for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {<br>
-      if (!KeyInfoT::isEqual(P->first, EmptyKey) &&<br>
-          !KeyInfoT::isEqual(P->first, TombstoneKey))<br>
-        P->second.~ValueT();<br>
-      P->first.~KeyT();<br>
+      if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&<br>
+          !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))<br>
+        P->getSecond().~ValueT();<br>
+      P->getFirst().~KeyT();<br>
     }<br>
<br>
 #ifndef NDEBUG<br>
@@ -269,7 +278,7 @@ protected:<br>
            "# initial buckets must be a power of two!");<br>
     const KeyT EmptyKey = getEmptyKey();<br>
     for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)<br>
-      new (&B->first) KeyT(EmptyKey);<br>
+      new (&B->getFirst()) KeyT(EmptyKey);<br>
   }<br>
<br>
   void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {<br>
@@ -279,21 +288,21 @@ protected:<br>
     const KeyT EmptyKey = getEmptyKey();<br>
     const KeyT TombstoneKey = getTombstoneKey();<br>
     for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {<br>
-      if (!KeyInfoT::isEqual(B->first, EmptyKey) &&<br>
-          !KeyInfoT::isEqual(B->first, TombstoneKey)) {<br>
+      if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&<br>
+          !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {<br>
         // Insert the key/value into the new table.<br>
         BucketT *DestBucket;<br>
-        bool FoundVal = LookupBucketFor(B->first, DestBucket);<br>
+        bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);<br>
         (void)FoundVal; // silence warning.<br>
         assert(!FoundVal && "Key already in new map?");<br>
-        DestBucket->first = std::move(B->first);<br>
-        new (&DestBucket->second) ValueT(std::move(B->second));<br>
+        DestBucket->getFirst() = std::move(B->getFirst());<br>
+        new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond()));<br>
         incrementNumEntries();<br>
<br>
         // Free the value.<br>
-        B->second.~ValueT();<br>
+        B->getSecond().~ValueT();<br>
       }<br>
-      B->first.~KeyT();<br>
+      B->getFirst().~KeyT();<br>
     }<br>
<br>
 #ifndef NDEBUG<br>
@@ -304,7 +313,8 @@ protected:<br>
   }<br>
<br>
   template <typename OtherBaseT><br>
-  void copyFrom(const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT>& other) {<br>
+  void copyFrom(<br>
+      const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {<br>
     assert(&other != this);<br>
     assert(getNumBuckets() == other.getNumBuckets());<br>
<br>
@@ -316,10 +326,12 @@ protected:<br>
              getNumBuckets() * sizeof(BucketT));<br>
     else<br>
       for (size_t i = 0; i < getNumBuckets(); ++i) {<br>
-        new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first);<br>
-        if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) &&<br>
-            !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey()))<br>
-          new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second);<br>
+        new (&getBuckets()[i].getFirst())<br>
+            KeyT(other.getBuckets()[i].getFirst());<br>
+        if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&<br>
+            !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))<br>
+          new (&getBuckets()[i].getSecond())<br>
+              ValueT(other.getBuckets()[i].getSecond());<br>
       }<br>
   }<br>
<br>
@@ -396,8 +408,8 @@ private:<br>
                             BucketT *TheBucket) {<br>
     TheBucket = InsertIntoBucketImpl(Key, TheBucket);<br>
<br>
-    TheBucket->first = Key;<br>
-    new (&TheBucket->second) ValueT(Value);<br>
+    TheBucket->getFirst() = Key;<br>
+    new (&TheBucket->getSecond()) ValueT(Value);<br>
     return TheBucket;<br>
   }<br>
<br>
@@ -405,16 +417,16 @@ private:<br>
                             BucketT *TheBucket) {<br>
     TheBucket = InsertIntoBucketImpl(Key, TheBucket);<br>
<br>
-    TheBucket->first = Key;<br>
-    new (&TheBucket->second) ValueT(std::move(Value));<br>
+    TheBucket->getFirst() = Key;<br>
+    new (&TheBucket->getSecond()) ValueT(std::move(Value));<br>
     return TheBucket;<br>
   }<br>
<br>
   BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) {<br>
     TheBucket = InsertIntoBucketImpl(Key, TheBucket);<br>
<br>
-    TheBucket->first = std::move(Key);<br>
-    new (&TheBucket->second) ValueT(std::move(Value));<br>
+    TheBucket->getFirst() = std::move(Key);<br>
+    new (&TheBucket->getSecond()) ValueT(std::move(Value));<br>
     return TheBucket;<br>
   }<br>
<br>
@@ -446,7 +458,7 @@ private:<br>
<br>
     // If we are writing over a tombstone, remember this.<br>
     const KeyT EmptyKey = getEmptyKey();<br>
-    if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey))<br>
+    if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))<br>
       decrementNumTombstones();<br>
<br>
     return TheBucket;<br>
@@ -480,14 +492,14 @@ private:<br>
     while (1) {<br>
       const BucketT *ThisBucket = BucketsPtr + BucketNo;<br>
       // Found Val's bucket?  If so, return it.<br>
-      if (KeyInfoT::isEqual(Val, ThisBucket->first)) {<br>
+      if (KeyInfoT::isEqual(Val, ThisBucket->getFirst())) {<br>
         FoundBucket = ThisBucket;<br>
         return true;<br>
       }<br>
<br>
       // If we found an empty bucket, the key doesn't exist in the set.<br>
       // Insert it and return the default value.<br>
-      if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) {<br>
+      if (KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey)) {<br>
         // If we've already seen a tombstone while probing, fill it in instead<br>
         // of the empty bucket we eventually probed to.<br>
         FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;<br>
@@ -496,7 +508,8 @@ private:<br>
<br>
       // If this is a tombstone, remember it.  If Val ends up not in the map, we<br>
       // prefer to return it than something that would require more probing.<br>
-      if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone)<br>
+      if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&<br>
+          !FoundTombstone)<br>
         FoundTombstone = ThisBucket;  // Remember the first tombstone found.<br>
<br>
       // Otherwise, it's a hash collision or a tombstone, continue quadratic<br>
@@ -525,16 +538,15 @@ public:<br>
   }<br>
 };<br>
<br>
-template<typename KeyT, typename ValueT,<br>
-         typename KeyInfoT = DenseMapInfo<KeyT> ><br>
-class DenseMap<br>
-    : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT>,<br>
-                          KeyT, ValueT, KeyInfoT> {<br>
+template <typename KeyT, typename ValueT,<br>
+          typename KeyInfoT = DenseMapInfo<KeyT>,<br>
+          typename BucketT = detail::DenseMapPair<KeyT, ValueT>><br>
+class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,<br>
+                                     KeyT, ValueT, KeyInfoT, BucketT> {<br>
   // Lift some types from the dependent base class into this class for<br>
   // simplicity of referring to them.<br>
-  typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT> BaseT;<br>
-  typedef typename BaseT::BucketT BucketT;<br>
-  friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT>;<br>
+  typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;<br>
+  friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;<br>
<br>
   BucketT *Buckets;<br>
   unsigned NumEntries;<br>
@@ -677,17 +689,17 @@ private:<br>
   }<br>
 };<br>
<br>
-template<typename KeyT, typename ValueT,<br>
-         unsigned InlineBuckets = 4,<br>
-         typename KeyInfoT = DenseMapInfo<KeyT> ><br>
+template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,<br>
+          typename KeyInfoT = DenseMapInfo<KeyT>,<br>
+          typename BucketT = detail::DenseMapPair<KeyT, ValueT>><br>
 class SmallDenseMap<br>
-    : public DenseMapBase<SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT>,<br>
-                          KeyT, ValueT, KeyInfoT> {<br>
+    : public DenseMapBase<<br>
+          SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,<br>
+          ValueT, KeyInfoT, BucketT> {<br>
   // Lift some types from the dependent base class into this class for<br>
   // simplicity of referring to them.<br>
-  typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT> BaseT;<br>
-  typedef typename BaseT::BucketT BucketT;<br>
-  friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT>;<br>
+  typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;<br>
+  friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;<br>
<br>
   unsigned Small : 1;<br>
   unsigned NumEntries : 31;<br>
@@ -744,23 +756,23 @@ public:<br>
       for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {<br>
         BucketT *LHSB = &getInlineBuckets()[i],<br>
                 *RHSB = &RHS.getInlineBuckets()[i];<br>
-        bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) &&<br>
-                            !KeyInfoT::isEqual(LHSB->first, TombstoneKey));<br>
-        bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) &&<br>
-                            !KeyInfoT::isEqual(RHSB->first, TombstoneKey));<br>
+        bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) &&<br>
+                            !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey));<br>
+        bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) &&<br>
+                            !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey));<br>
         if (hasLHSValue && hasRHSValue) {<br>
           // Swap together if we can...<br>
           std::swap(*LHSB, *RHSB);<br>
           continue;<br>
         }<br>
         // Swap separately and handle any assymetry.<br>
-        std::swap(LHSB->first, RHSB->first);<br>
+        std::swap(LHSB->getFirst(), RHSB->getFirst());<br>
         if (hasLHSValue) {<br>
-          new (&RHSB->second) ValueT(std::move(LHSB->second));<br>
-          LHSB->second.~ValueT();<br>
+          new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));<br>
+          LHSB->getSecond().~ValueT();<br>
         } else if (hasRHSValue) {<br>
-          new (&LHSB->second) ValueT(std::move(RHSB->second));<br>
-          RHSB->second.~ValueT();<br>
+          new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond()));<br>
+          RHSB->getSecond().~ValueT();<br>
         }<br>
       }<br>
       return;<br>
@@ -785,12 +797,12 @@ public:<br>
     for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {<br>
       BucketT *NewB = &LargeSide.getInlineBuckets()[i],<br>
               *OldB = &SmallSide.getInlineBuckets()[i];<br>
-      new (&NewB->first) KeyT(std::move(OldB->first));<br>
-      OldB->first.~KeyT();<br>
-      if (!KeyInfoT::isEqual(NewB->first, EmptyKey) &&<br>
-          !KeyInfoT::isEqual(NewB->first, TombstoneKey)) {<br>
-        new (&NewB->second) ValueT(std::move(OldB->second));<br>
-        OldB->second.~ValueT();<br>
+      new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst()));<br>
+      OldB->getFirst().~KeyT();<br>
+      if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) &&<br>
+          !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) {<br>
+        new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond()));<br>
+        OldB->getSecond().~ValueT();<br>
       }<br>
     }<br>
<br>
@@ -852,16 +864,16 @@ public:<br>
       const KeyT EmptyKey = this->getEmptyKey();<br>
       const KeyT TombstoneKey = this->getTombstoneKey();<br>
       for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) {<br>
-        if (!KeyInfoT::isEqual(P->first, EmptyKey) &&<br>
-            !KeyInfoT::isEqual(P->first, TombstoneKey)) {<br>
+        if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&<br>
+            !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {<br>
           assert(size_t(TmpEnd - TmpBegin) < InlineBuckets &&<br>
                  "Too many inline buckets!");<br>
-          new (&TmpEnd->first) KeyT(std::move(P->first));<br>
-          new (&TmpEnd->second) ValueT(std::move(P->second));<br>
+          new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst()));<br>
+          new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond()));<br>
           ++TmpEnd;<br>
-          P->second.~ValueT();<br>
+          P->getSecond().~ValueT();<br>
         }<br>
-        P->first.~KeyT();<br>
+        P->getFirst().~KeyT();<br>
       }<br>
<br>
       // Now make this map use the large rep, and move all the entries back<br>
@@ -972,13 +984,12 @@ private:<br>
   }<br>
 };<br>
<br>
-template<typename KeyT, typename ValueT,<br>
-         typename KeyInfoT, bool IsConst><br>
+template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,<br>
+          bool IsConst><br>
 class DenseMapIterator {<br>
-  typedef std::pair<KeyT, ValueT> Bucket;<br>
-  typedef DenseMapIterator<KeyT, ValueT,<br>
-                           KeyInfoT, true> ConstIterator;<br>
-  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>;<br>
+  typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;<br>
+  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;<br>
+<br>
 public:<br>
   typedef ptrdiff_t difference_type;<br>
   typedef typename std::conditional<IsConst, const Bucket, Bucket>::type<br>
@@ -999,9 +1010,9 @@ public:<br>
   // If IsConst is true this is a converting constructor from iterator to<br>
   // const_iterator and the default copy constructor is used.<br>
   // Otherwise this is a copy constructor for iterator.<br>
-  DenseMapIterator(const DenseMapIterator<KeyT, ValueT,<br>
-                                          KeyInfoT, false>& I)<br>
-    : Ptr(I.Ptr), End(I.End) {}<br>
+  DenseMapIterator(<br>
+      const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false> &I)<br>
+      : Ptr(I.Ptr), End(I.End) {}<br>
<br>
   reference operator*() const {<br>
     return *Ptr;<br>
@@ -1031,9 +1042,8 @@ private:<br>
     const KeyT Empty = KeyInfoT::getEmptyKey();<br>
     const KeyT Tombstone = KeyInfoT::getTombstoneKey();<br>
<br>
-    while (Ptr != End &&<br>
-           (KeyInfoT::isEqual(Ptr->first, Empty) ||<br>
-            KeyInfoT::isEqual(Ptr->first, Tombstone)))<br>
+    while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) ||<br>
+                          KeyInfoT::isEqual(Ptr->getFirst(), Tombstone)))<br>
       ++Ptr;<br>
   }<br>
 };<br>
<br>
Modified: llvm/trunk/include/llvm/ADT/DenseSet.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseSet.h?rev=223588&r1=223587&r2=223588&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseSet.h?rev=223588&r1=223587&r2=223588&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ADT/DenseSet.h (original)<br>
+++ llvm/trunk/include/llvm/ADT/DenseSet.h Sat Dec  6 13:22:44 2014<br>
@@ -18,13 +18,29 @@<br>
<br>
 namespace llvm {<br>
<br>
+namespace detail {<br>
+struct DenseSetEmpty {};<br>
+<br>
+// Use the empty base class trick so we can create a DenseMap where the buckets<br>
+// contain only a single item.<br>
+template <typename KeyT> class DenseSetPair : public DenseSetEmpty {<br>
+  KeyT key;<br>
+<br>
+public:<br>
+  KeyT &getFirst() { return key; }<br>
+  const KeyT &getFirst() const { return key; }<br>
+  DenseSetEmpty &getSecond() { return *this; }<br>
+  const DenseSetEmpty &getSecond() const { return *this; }<br>
+};<br>
+}<br>
+<br>
 /// DenseSet - This implements a dense probed hash-table based set.<br>
-///<br>
-/// FIXME: This is currently implemented directly in terms of DenseMap, this<br>
-/// should be optimized later if there is a need.<br>
 template<typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT> ><br>
 class DenseSet {<br>
-  typedef DenseMap<ValueT, char, ValueInfoT> MapTy;<br>
+  typedef DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,<br>
+                   detail::DenseSetPair<ValueT>> MapTy;<br>
+  static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),<br>
+                "DenseMap buckets unexpectedly large!");<br>
   MapTy TheMap;<br>
 public:<br>
   typedef ValueT key_type;<br>
@@ -72,8 +88,8 @@ public:<br>
<br>
     Iterator(const typename MapTy::iterator &i) : I(i) {}<br>
<br>
-    ValueT& operator*() { return I->first; }<br>
-    ValueT* operator->() { return &I->first; }<br>
+    ValueT &operator*() { return I->getFirst(); }<br>
+    ValueT *operator->() { return &I->getFirst(); }<br>
<br>
     Iterator& operator++() { ++I; return *this; }<br>
     bool operator==(const Iterator& X) const { return I == X.I; }<br>
@@ -92,8 +108,8 @@ public:<br>
<br>
     ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}<br>
<br>
-    const ValueT& operator*() { return I->first; }<br>
-    const ValueT* operator->() { return &I->first; }<br>
+    const ValueT &operator*() { return I->getFirst(); }<br>
+    const ValueT *operator->() { return &I->getFirst(); }<br>
<br>
     ConstIterator& operator++() { ++I; return *this; }<br>
     bool operator==(const ConstIterator& X) const { return I == X.I; }<br>
@@ -129,7 +145,8 @@ public:<br>
   void erase(ConstIterator CI) { return TheMap.erase(CI.I); }<br>
<br>
   std::pair<iterator, bool> insert(const ValueT &V) {<br>
-    return TheMap.insert(std::make_pair(V, 0));<br>
+    detail::DenseSetEmpty Empty;<br>
+    return TheMap.insert(std::make_pair(V, Empty));<br>
   }<br>
<br>
   // Range insertion of values.<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Module.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=223588&r1=223587&r2=223588&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=223588&r1=223587&r2=223588&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/Module.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Module.h Sat Dec  6 13:22:44 2014<br>
@@ -33,8 +33,6 @@ class GVMaterializer;<br>
 class LLVMContext;<br>
 class RandomNumberGenerator;<br>
 class StructType;<br>
-template<typename T> struct DenseMapInfo;<br>
-template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap;<br>
<br>
 template<> struct ilist_traits<Function><br>
   : public SymbolTableListTraits<Function, Module> {<br>
<br>
Modified: llvm/trunk/lib/Target/AArch64/AArch64PromoteConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64PromoteConstant.cpp?rev=223588&r1=223587&r2=223588&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64PromoteConstant.cpp?rev=223588&r1=223587&r2=223588&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/AArch64/AArch64PromoteConstant.cpp (original)<br>
+++ llvm/trunk/lib/Target/AArch64/AArch64PromoteConstant.cpp Sat Dec  6 13:22:44 2014<br>
@@ -193,7 +193,7 @@ private:<br>
     // Inserting into the DenseMap may invalidate existing iterator.<br>
     // Keep a copy of the key to find the iterator to erase.<br>
     Instruction *OldInstr = IPI->first;<br>
-    InsertPts.insert(InsertionPoints::value_type(NewPt, IPI->second));<br>
+    InsertPts[NewPt] = std::move(IPI->second);<br>
     // Erase IPI.<br>
     IPI = InsertPts.find(OldInstr);<br>
     InsertPts.erase(IPI);<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>