Skip to content

Commit 65b4a77

Browse files
authored
[sanitizer] Optimize DenseMap::{find,erase}
Port the ADT optimization #100517. In addition, add `contains` (https://reviews.llvm.org/D145895) while changing `count`. Pull Request: #101785
1 parent bb4f9c6 commit 65b4a77

File tree

1 file changed

+41
-29
lines changed

1 file changed

+41
-29
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_dense_map.h

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,14 @@ class DenseMapBase {
6969
setNumTombstones(0);
7070
}
7171

72+
/// Return true if the specified key is in the map, false otherwise.
73+
bool contains(const KeyT &Key) const { return doFind(Key) != nullptr; }
74+
7275
/// Return 1 if the specified key is in the map, 0 otherwise.
73-
size_type count(const KeyT &Key) const {
74-
const BucketT *TheBucket;
75-
return LookupBucketFor(Key, TheBucket) ? 1 : 0;
76-
}
76+
size_type count(const KeyT &Key) const { return contains(Key) ? 1 : 0; }
7777

78-
value_type *find(const KeyT &Key) {
79-
BucketT *TheBucket;
80-
if (LookupBucketFor(Key, TheBucket))
81-
return TheBucket;
82-
return nullptr;
83-
}
84-
const value_type *find(const KeyT &Key) const {
85-
const BucketT *TheBucket;
86-
if (LookupBucketFor(Key, TheBucket))
87-
return TheBucket;
88-
return nullptr;
89-
}
78+
value_type *find(const KeyT &Key) { return doFind(Key); }
79+
const value_type *find(const KeyT &Key) const { return doFind(Key); }
9080

9181
/// Alternate version of find() which allows a different, and possibly
9282
/// less expensive, key type.
@@ -95,25 +85,18 @@ class DenseMapBase {
9585
/// type used.
9686
template <class LookupKeyT>
9787
value_type *find_as(const LookupKeyT &Key) {
98-
BucketT *TheBucket;
99-
if (LookupBucketFor(Key, TheBucket))
100-
return TheBucket;
101-
return nullptr;
88+
return doFind(Key);
10289
}
10390
template <class LookupKeyT>
10491
const value_type *find_as(const LookupKeyT &Key) const {
105-
const BucketT *TheBucket;
106-
if (LookupBucketFor(Key, TheBucket))
107-
return TheBucket;
108-
return nullptr;
92+
return doFind(Key);
10993
}
11094

11195
/// lookup - Return the entry for the specified key, or a default
11296
/// constructed value if no such entry exists.
11397
ValueT lookup(const KeyT &Key) const {
114-
const BucketT *TheBucket;
115-
if (LookupBucketFor(Key, TheBucket))
116-
return TheBucket->getSecond();
98+
if (const BucketT *Bucket = doFind(Key))
99+
return Bucket->getSecond();
117100
return ValueT();
118101
}
119102

@@ -184,8 +167,8 @@ class DenseMapBase {
184167
}
185168

186169
bool erase(const KeyT &Val) {
187-
BucketT *TheBucket;
188-
if (!LookupBucketFor(Val, TheBucket))
170+
BucketT *TheBucket = doFind(Val);
171+
if (!TheBucket)
189172
return false; // not in map.
190173

191174
TheBucket->getSecond().~ValueT();
@@ -449,6 +432,35 @@ class DenseMapBase {
449432
return TheBucket;
450433
}
451434

435+
template <typename LookupKeyT>
436+
BucketT *doFind(const LookupKeyT &Val) {
437+
BucketT *BucketsPtr = getBuckets();
438+
const unsigned NumBuckets = getNumBuckets();
439+
if (NumBuckets == 0)
440+
return nullptr;
441+
442+
const KeyT EmptyKey = getEmptyKey();
443+
unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1);
444+
unsigned ProbeAmt = 1;
445+
while (true) {
446+
BucketT *Bucket = BucketsPtr + BucketNo;
447+
if (LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
448+
return Bucket;
449+
if (LIKELY(KeyInfoT::isEqual(Bucket->getFirst(), EmptyKey)))
450+
return nullptr;
451+
452+
// Otherwise, it's a hash collision or a tombstone, continue quadratic
453+
// probing.
454+
BucketNo += ProbeAmt++;
455+
BucketNo &= NumBuckets - 1;
456+
}
457+
}
458+
459+
template <typename LookupKeyT>
460+
const BucketT *doFind(const LookupKeyT &Val) const {
461+
return const_cast<DenseMapBase *>(this)->doFind(Val);
462+
}
463+
452464
/// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
453465
/// FoundBucket. If the bucket contains the key and a value, this returns
454466
/// true, otherwise it returns a bucket with an empty marker or tombstone and

0 commit comments

Comments
 (0)