Skip to content

Commit ad79a14

Browse files
authored
[ADT] Update hash function of uint64_t for DenseMap (#95734)
(Background: See the comment: #92083 (comment)) It looks like the hash function for 64bits integers are not very good: ``` static unsigned getHashValue(const unsigned long long& Val) { return (unsigned)(Val * 37ULL); } ``` Since the result is truncated to 32 bits. It looks like the higher 32 bits won't contribute to the result. So that `0x1'00000001` will have the the same results to `0x2'00000001`, `0x3'00000001`, ... Then we may meet a lot collisions in such cases. I feel it should generally good to include higher 32 bits for hashing functions. Not sure who's the appropriate reviewer, adding some people by impressions.
1 parent 57778ec commit ad79a14

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

llvm/include/llvm/ADT/DenseMapInfo.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ template<> struct DenseMapInfo<unsigned long> {
139139
static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
140140

141141
static unsigned getHashValue(const unsigned long& Val) {
142-
return (unsigned)(Val * 37UL);
142+
if constexpr (sizeof(Val) == 4)
143+
return DenseMapInfo<unsigned>::getHashValue(Val);
144+
else
145+
return detail::combineHashValue(Val >> 32, Val);
143146
}
144147

145148
static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
@@ -153,7 +156,7 @@ template<> struct DenseMapInfo<unsigned long long> {
153156
static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
154157

155158
static unsigned getHashValue(const unsigned long long& Val) {
156-
return (unsigned)(Val * 37ULL);
159+
return detail::combineHashValue(Val >> 32, Val);
157160
}
158161

159162
static bool isEqual(const unsigned long long& LHS,

0 commit comments

Comments
 (0)