[llvm] [ADT] Update hash function of uint64_t for DenseMap (PR #95734)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 16 20:48:31 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-adt

Author: Chuanqi Xu (ChuanqiXu9)

<details>
<summary>Changes</summary>

(Background: See the comment:
https://github.com/llvm/llvm-project/pull/92083#issuecomment-2168121729)

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/95734.diff


1 Files Affected:

- (modified) llvm/include/llvm/ADT/DenseMapInfo.h (+1-1) 


``````````diff
diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 5b7dce7b53c62..61869d8e7fbb0 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -151,7 +151,7 @@ template<> struct DenseMapInfo<unsigned long long> {
   static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
 
   static unsigned getHashValue(const unsigned long long& Val) {
-    return (unsigned)(Val * 37ULL);
+    return DenseMapInfo<unsigned>(Val) ^ DenseMapInfo<unsigned>(Val >> 32);
   }
 
   static bool isEqual(const unsigned long long& LHS,

``````````

</details>


https://github.com/llvm/llvm-project/pull/95734


More information about the llvm-commits mailing list