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