forked from OSchip/llvm-project
Make the DenseMap bucket type configurable and use a smaller bucket for DenseSet.
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. llvm-svn: 223588
This commit is contained in:
parent
8e5dc53784
commit
89e5306f43
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue