[llvm] [DenseMap] Do not align pointer sentinel values (NFC) (PR #146595)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 1 13:15:43 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-adt

Author: Nikita Popov (nikic)

<details>
<summary>Changes</summary>

DenseMapInfo for pointers currently uses empty/tombstone values that are aligned (by assuming a very conservative alignment). However, this means that we have to work with larger immediates.

This patch proposes to use the values -1 and -2 instead, without caring about pointer alignment. This puts us into unspecified territory from the perspective of the C standard, but general implementer consensus (including Clang) is that raw pointers do not carry alignment guarantees, only memory accesses do.

We already have lots of places that rely on this using variations on `reinterpret_cast<T*>(-1)`, so it seems odd to insist on strict standard conformance in this one place.

This is a small improvement for both compile-time and clang binary size: https://llvm-compile-time-tracker.com/compare.php?from=b8b74945514358f1ebeac0874172f37fc7bfa38e&to=3c83bf05608d720d6ff88adfaca7191331eeb30f&stat=instructions:u

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


2 Files Affected:

- (modified) llvm/include/llvm/ADT/DenseMapInfo.h (+4-21) 
- (modified) llvm/include/llvm/ADT/PointerUnion.h (+10-4) 


``````````diff
diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 07c37e353a40b..b371611e7d948 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -56,30 +56,13 @@ struct DenseMapInfo {
   //static bool isEqual(const T &LHS, const T &RHS);
 };
 
-// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
-// that are aligned to alignof(T) bytes, but try to avoid requiring T to be
-// complete. This allows clients to instantiate DenseMap<T*, ...> with forward
-// declared key types. Assume that no pointer key type requires more than 4096
-// bytes of alignment.
-template<typename T>
-struct DenseMapInfo<T*> {
-  // The following should hold, but it would require T to be complete:
-  // static_assert(alignof(T) <= (1 << Log2MaxAlign),
-  //               "DenseMap does not support pointer keys requiring more than "
-  //               "Log2MaxAlign bits of alignment");
-  static constexpr uintptr_t Log2MaxAlign = 12;
-
+template <typename T> struct DenseMapInfo<T *> {
   static inline T* getEmptyKey() {
-    uintptr_t Val = static_cast<uintptr_t>(-1);
-    Val <<= Log2MaxAlign;
-    return reinterpret_cast<T*>(Val);
+    // We assume that raw pointers do not carry alignment requirements.
+    return reinterpret_cast<T *>(-1);
   }
 
-  static inline T* getTombstoneKey() {
-    uintptr_t Val = static_cast<uintptr_t>(-2);
-    Val <<= Log2MaxAlign;
-    return reinterpret_cast<T*>(Val);
-  }
+  static inline T *getTombstoneKey() { return reinterpret_cast<T *>(-2); }
 
   static unsigned getHashValue(const T *PtrVal) {
     return (unsigned((uintptr_t)PtrVal) >> 4) ^
diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h
index cdbd76d7f505b..86248a2cf836f 100644
--- a/llvm/include/llvm/ADT/PointerUnion.h
+++ b/llvm/include/llvm/ADT/PointerUnion.h
@@ -286,13 +286,19 @@ struct PointerLikeTypeTraits<PointerUnion<PTs...>> {
 // Teach DenseMap how to use PointerUnions as keys.
 template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
   using Union = PointerUnion<PTs...>;
-  using FirstInfo =
-      DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>;
+  using FirstTypeTraits = PointerLikeTypeTraits<
+      typename pointer_union_detail::GetFirstType<PTs...>::type>;
 
-  static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
+  static inline Union getEmptyKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= FirstTypeTraits::NumLowBitsAvailable;
+    return FirstTypeTraits::getFromVoidPointer(reinterpret_cast<void *>(Val));
+  }
 
   static inline Union getTombstoneKey() {
-    return Union(FirstInfo::getTombstoneKey());
+    uintptr_t Val = static_cast<uintptr_t>(-2);
+    Val <<= FirstTypeTraits::NumLowBitsAvailable;
+    return FirstTypeTraits::getFromVoidPointer(reinterpret_cast<void *>(Val));
   }
 
   static unsigned getHashValue(const Union &UnionVal) {

``````````

</details>


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


More information about the llvm-commits mailing list