[llvm] [ADT] Remove unused DenseMapInfo::getEmptyKey (PR #201998)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 6 11:50:35 PDT 2026


https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/201998

>From 7b3b809922aa9013c1fefa73775ffe987e2a8874 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 5 Jun 2026 19:08:21 -0700
Subject: [PATCH 1/4] [ADT] Remove unused DenseMapInfo::getEmptyKey

After #201281 DenseMapInfo<T>::getEmptyKey() is no longer used by
DenseMap. Remove the unused getEmptyKey definitions and dead sentinel
uses.
---
 llvm/include/llvm/ADT/APFixedPoint.h          |  8 -----
 llvm/include/llvm/ADT/APInt.h                 |  6 ----
 llvm/include/llvm/ADT/APSInt.h                |  4 ---
 llvm/include/llvm/ADT/ArrayRef.h              | 12 +------
 llvm/include/llvm/ADT/BitVector.h             |  1 -
 llvm/include/llvm/ADT/CachedHashString.h      | 14 +++------
 llvm/include/llvm/ADT/DenseMapInfo.h          | 31 ++-----------------
 llvm/include/llvm/ADT/DenseMapInfoVariant.h   |  4 ---
 llvm/include/llvm/ADT/Hashing.h               |  1 -
 llvm/include/llvm/ADT/ImmutableList.h         |  4 ---
 llvm/include/llvm/ADT/PointerEmbeddedInt.h    |  2 --
 llvm/include/llvm/ADT/PointerIntPair.h        |  6 ----
 llvm/include/llvm/ADT/PointerSumType.h        |  4 ---
 llvm/include/llvm/ADT/PointerUnion.h          |  2 --
 llvm/include/llvm/ADT/SmallBitVector.h        |  1 -
 llvm/include/llvm/ADT/SmallVector.h           |  4 ---
 llvm/include/llvm/ADT/StringRef.h             | 11 +------
 .../llvm/Support/FileSystem/UniqueID.h        |  5 ---
 llvm/include/llvm/Support/TypeSize.h          |  3 --
 llvm/include/llvm/Support/UniqueBBID.h        |  5 ---
 llvm/include/llvm/Support/VersionTuple.h      |  1 -
 llvm/lib/Support/StringRef.cpp                |  1 -
 llvm/unittests/ADT/DenseMapTest.cpp           |  5 ---
 llvm/unittests/ADT/DenseSetTest.cpp           |  2 --
 llvm/unittests/ADT/MapVectorTest.cpp          |  1 -
 .../Support/ReverseIterationTest.cpp          |  5 ---
 26 files changed, 9 insertions(+), 134 deletions(-)

diff --git a/llvm/include/llvm/ADT/APFixedPoint.h b/llvm/include/llvm/ADT/APFixedPoint.h
index 790a5e775fb56..9a88365d91955 100644
--- a/llvm/include/llvm/ADT/APFixedPoint.h
+++ b/llvm/include/llvm/ADT/APFixedPoint.h
@@ -139,10 +139,6 @@ inline hash_code hash_value(const FixedPointSemantics &Val) {
 }
 
 template <> struct DenseMapInfo<FixedPointSemantics> {
-  static inline FixedPointSemantics getEmptyKey() {
-    return FixedPointSemantics(0, 0, false, false, false);
-  }
-
   static unsigned getHashValue(const FixedPointSemantics &Val) {
     return hash_value(Val);
   }
@@ -315,10 +311,6 @@ inline hash_code hash_value(const APFixedPoint &Val) {
 }
 
 template <> struct DenseMapInfo<APFixedPoint> {
-  static inline APFixedPoint getEmptyKey() {
-    return APFixedPoint(DenseMapInfo<FixedPointSemantics>::getEmptyKey());
-  }
-
   static unsigned getHashValue(const APFixedPoint &Val) {
     return hash_value(Val);
   }
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 1a4788248e554..df163c54f66cf 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -2527,12 +2527,6 @@ LLVM_ABI void LoadIntFromMemory(APInt &IntVal, const uint8_t *Src,
 
 /// Provide DenseMapInfo for APInt.
 template <> struct DenseMapInfo<APInt, void> {
-  static inline APInt getEmptyKey() {
-    APInt V(nullptr, 0);
-    V.U.VAL = ~0ULL;
-    return V;
-  }
-
   LLVM_ABI static unsigned getHashValue(const APInt &Key);
 
   static bool isEqual(const APInt &LHS, const APInt &RHS) {
diff --git a/llvm/include/llvm/ADT/APSInt.h b/llvm/include/llvm/ADT/APSInt.h
index c5f8ad731bdb0..17d055f7193a5 100644
--- a/llvm/include/llvm/ADT/APSInt.h
+++ b/llvm/include/llvm/ADT/APSInt.h
@@ -367,10 +367,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
 
 /// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt.
 template <> struct DenseMapInfo<APSInt, void> {
-  static inline APSInt getEmptyKey() {
-    return APSInt(DenseMapInfo<APInt, void>::getEmptyKey());
-  }
-
   static unsigned getHashValue(const APSInt &Key) {
     return DenseMapInfo<APInt, void>::getHashValue(Key);
   }
diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h
index badac76affdc9..6f12564c00c1e 100644
--- a/llvm/include/llvm/ADT/ArrayRef.h
+++ b/llvm/include/llvm/ADT/ArrayRef.h
@@ -564,21 +564,11 @@ inline XXH128_hash_t xxh3_128bits(ArrayRef<uint8_t> data) {
 
 // Provide DenseMapInfo for ArrayRefs.
 template <typename T> struct DenseMapInfo<ArrayRef<T>, void> {
-  static inline ArrayRef<T> getEmptyKey() {
-    return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
-                       size_t(0));
-  }
-
   static unsigned getHashValue(ArrayRef<T> Val) {
-    assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
     return (unsigned)(hash_value(Val));
   }
 
-  static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
-    if (RHS.data() == getEmptyKey().data())
-      return LHS.data() == getEmptyKey().data();
-    return LHS == RHS;
-  }
+  static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) { return LHS == RHS; }
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/ADT/BitVector.h b/llvm/include/llvm/ADT/BitVector.h
index 72c8a84c15ecf..a9902f603081c 100644
--- a/llvm/include/llvm/ADT/BitVector.h
+++ b/llvm/include/llvm/ADT/BitVector.h
@@ -847,7 +847,6 @@ inline BitVector::size_type capacity_in_bytes(const BitVector &X) {
 }
 
 template <> struct DenseMapInfo<BitVector> {
-  static inline BitVector getEmptyKey() { return {}; }
   static unsigned getHashValue(const BitVector &V) {
     return DenseMapInfo<std::pair<BitVector::size_type, ArrayRef<uintptr_t>>>::
         getHashValue(std::make_pair(V.size(), V.getData()));
diff --git a/llvm/include/llvm/ADT/CachedHashString.h b/llvm/include/llvm/ADT/CachedHashString.h
index cc26216176198..e28944b271298 100644
--- a/llvm/include/llvm/ADT/CachedHashString.h
+++ b/llvm/include/llvm/ADT/CachedHashString.h
@@ -48,11 +48,7 @@ class CachedHashStringRef {
 };
 
 template <> struct DenseMapInfo<CachedHashStringRef> {
-  static CachedHashStringRef getEmptyKey() {
-    return CachedHashStringRef(DenseMapInfo<StringRef>::getEmptyKey(), 0);
-  }
   static unsigned getHashValue(const CachedHashStringRef &S) {
-    assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!");
     return S.hash();
   }
   static bool isEqual(const CachedHashStringRef &LHS,
@@ -72,7 +68,10 @@ class CachedHashString {
   uint32_t Size;
   uint32_t Hash;
 
-  static char *getEmptyKeyPtr() { return DenseMapInfo<char *>::getEmptyKey(); }
+  static char *getEmptyKeyPtr() {
+    return reinterpret_cast<char *>(static_cast<uintptr_t>(-1)
+                                    << DenseMapInfo<char *>::Log2MaxAlign);
+  }
 
   bool isEmpty() const { return P == getEmptyKeyPtr(); }
 
@@ -142,12 +141,7 @@ class CachedHashString {
 };
 
 template <> struct DenseMapInfo<CachedHashString> {
-  static CachedHashString getEmptyKey() {
-    return CachedHashString(CachedHashString::ConstructEmptyTy(),
-                            CachedHashString::getEmptyKeyPtr());
-  }
   static unsigned getHashValue(const CachedHashString &S) {
-    assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!");
     return S.hash();
   }
   static bool isEqual(const CachedHashString &LHS,
diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index e8e21e4a15e66..273033a21df0e 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -52,7 +52,6 @@ inline unsigned combineHashValue(unsigned a, unsigned b) {
 /// just be `void`.
 template<typename T, typename Enable = void>
 struct DenseMapInfo {
-  // static constexpr T getEmptyKey();
   // static unsigned getHashValue(const T &Val);
   // static bool isEqual(const T &LHS, const T &RHS);
 };
@@ -70,12 +69,6 @@ struct DenseMapInfo<T*> {
   //               "Log2MaxAlign bits of alignment");
   static constexpr uintptr_t Log2MaxAlign = 12;
 
-  static constexpr T *getEmptyKey() {
-    uintptr_t Val = static_cast<uintptr_t>(-1);
-    Val <<= Log2MaxAlign;
-    return reinterpret_cast<T*>(Val);
-  }
-
   static unsigned getHashValue(const T *PtrVal) {
     return densemap::detail::mix(reinterpret_cast<uintptr_t>(PtrVal));
   }
@@ -85,7 +78,6 @@ struct DenseMapInfo<T*> {
 
 // Provide DenseMapInfo for chars.
 template<> struct DenseMapInfo<char> {
-  static constexpr char getEmptyKey() { return ~0; }
   static unsigned getHashValue(const char& Val) { return Val * 37U; }
 
   static bool isEqual(const char &LHS, const char &RHS) {
@@ -102,8 +94,6 @@ template<> struct DenseMapInfo<char> {
 template <typename T>
 struct DenseMapInfo<
     T, std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, char>>> {
-  static constexpr T getEmptyKey() { return std::numeric_limits<T>::max(); }
-
   static unsigned getHashValue(const T &Val) {
     if constexpr (std::is_unsigned_v<T> && sizeof(T) > sizeof(unsigned))
       return densemap::detail::mix(Val);
@@ -122,10 +112,6 @@ struct DenseMapInfo<std::pair<T, U>> {
   using FirstInfo = DenseMapInfo<T>;
   using SecondInfo = DenseMapInfo<U>;
 
-  static constexpr Pair getEmptyKey() {
-    return {FirstInfo::getEmptyKey(), SecondInfo::getEmptyKey()};
-  }
-
   static unsigned getHashValue(const Pair& PairVal) {
     return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
                                     SecondInfo::getHashValue(PairVal.second));
@@ -149,10 +135,6 @@ struct DenseMapInfo<std::pair<T, U>> {
 template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
   using Tuple = std::tuple<Ts...>;
 
-  static constexpr Tuple getEmptyKey() {
-    return Tuple(DenseMapInfo<Ts>::getEmptyKey()...);
-  }
-
   template <unsigned I> static unsigned getHashValueImpl(const Tuple &values) {
     if constexpr (I == sizeof...(Ts)) {
       return 0;
@@ -195,11 +177,6 @@ struct DenseMapInfo<Enum, std::enable_if_t<std::is_enum_v<Enum>>> {
   // If you hit this error, you can fix by switching to `enum class`, or adding
   // an explicit underlying type (e.g. `enum X : int`) to the enum's definition.
 
-  static constexpr Enum getEmptyKey() {
-    constexpr Enum V = static_cast<Enum>(Info::getEmptyKey());
-    return V;
-  }
-
   static unsigned getHashValue(const Enum &Val) {
     return Info::getHashValue(static_cast<UnderlyingType>(Val));
   }
@@ -211,12 +188,10 @@ template <typename T> struct DenseMapInfo<std::optional<T>> {
   using Optional = std::optional<T>;
   using Info = DenseMapInfo<T>;
 
-  static constexpr Optional getEmptyKey() { return {Info::getEmptyKey()}; }
-
   static unsigned getHashValue(const Optional &OptionalVal) {
-    return detail::combineHashValue(
-        OptionalVal.has_value(),
-        Info::getHashValue(OptionalVal.value_or(Info::getEmptyKey())));
+    if (OptionalVal)
+      return detail::combineHashValue(1, Info::getHashValue(*OptionalVal));
+    return detail::combineHashValue(0, 0);
   }
 
   static bool isEqual(const Optional &LHS, const Optional &RHS) {
diff --git a/llvm/include/llvm/ADT/DenseMapInfoVariant.h b/llvm/include/llvm/ADT/DenseMapInfoVariant.h
index 9729f2a300098..c09f1881c7ff2 100644
--- a/llvm/include/llvm/ADT/DenseMapInfoVariant.h
+++ b/llvm/include/llvm/ADT/DenseMapInfoVariant.h
@@ -25,10 +25,6 @@ template <typename... Ts> struct DenseMapInfo<std::variant<Ts...>> {
   using Variant = std::variant<Ts...>;
   using FirstT = std::variant_alternative_t<0, Variant>;
 
-  static inline Variant getEmptyKey() {
-    return Variant(std::in_place_index<0>, DenseMapInfo<FirstT>::getEmptyKey());
-  }
-
   static unsigned getHashValue(const Variant &Val) {
     return std::visit(
         [&Val](auto &&Alternative) {
diff --git a/llvm/include/llvm/ADT/Hashing.h b/llvm/include/llvm/ADT/Hashing.h
index 5565b09543233..99310a35f80c5 100644
--- a/llvm/include/llvm/ADT/Hashing.h
+++ b/llvm/include/llvm/ADT/Hashing.h
@@ -391,7 +391,6 @@ template <typename T> hash_code hash_value(const std::optional<T> &arg) {
 }
 
 template <> struct DenseMapInfo<hash_code, void> {
-  static constexpr hash_code getEmptyKey() { return hash_code(-1); }
   static constexpr unsigned getHashValue(hash_code val) {
     return static_cast<unsigned>(size_t(val));
   }
diff --git a/llvm/include/llvm/ADT/ImmutableList.h b/llvm/include/llvm/ADT/ImmutableList.h
index ef3f8a21db470..7694f571a8283 100644
--- a/llvm/include/llvm/ADT/ImmutableList.h
+++ b/llvm/include/llvm/ADT/ImmutableList.h
@@ -220,10 +220,6 @@ class ImmutableListFactory {
 //===----------------------------------------------------------------------===//
 
 template <typename T> struct DenseMapInfo<ImmutableList<T>, void> {
-  static inline ImmutableList<T> getEmptyKey() {
-    return reinterpret_cast<ImmutableListImpl<T>*>(-1);
-  }
-
   static unsigned getHashValue(ImmutableList<T> X) {
     uintptr_t PtrVal = reinterpret_cast<uintptr_t>(X.getInternalPointer());
     return (unsigned((uintptr_t)PtrVal) >> 4) ^
diff --git a/llvm/include/llvm/ADT/PointerEmbeddedInt.h b/llvm/include/llvm/ADT/PointerEmbeddedInt.h
index 76b03a40a9e27..c728b715518f6 100644
--- a/llvm/include/llvm/ADT/PointerEmbeddedInt.h
+++ b/llvm/include/llvm/ADT/PointerEmbeddedInt.h
@@ -101,8 +101,6 @@ struct DenseMapInfo<PointerEmbeddedInt<IntT, Bits>> {
   using T = PointerEmbeddedInt<IntT, Bits>;
   using IntInfo = DenseMapInfo<IntT>;
 
-  static inline T getEmptyKey() { return IntInfo::getEmptyKey(); }
-
   static unsigned getHashValue(const T &Arg) {
     return IntInfo::getHashValue(Arg);
   }
diff --git a/llvm/include/llvm/ADT/PointerIntPair.h b/llvm/include/llvm/ADT/PointerIntPair.h
index db6714ffcfe91..c2db63382e13f 100644
--- a/llvm/include/llvm/ADT/PointerIntPair.h
+++ b/llvm/include/llvm/ADT/PointerIntPair.h
@@ -217,12 +217,6 @@ template <typename PointerTy, unsigned IntBits, typename IntType>
 struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>, void> {
   using Ty = PointerIntPair<PointerTy, IntBits, IntType>;
 
-  static Ty getEmptyKey() {
-    uintptr_t Val = static_cast<uintptr_t>(-1);
-    Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable;
-    return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
-  }
-
   static unsigned getHashValue(Ty V) {
     uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());
     return unsigned(IV) ^ unsigned(IV >> 9);
diff --git a/llvm/include/llvm/ADT/PointerSumType.h b/llvm/include/llvm/ADT/PointerSumType.h
index beaaf49a32b52..7d167bfffee0b 100644
--- a/llvm/include/llvm/ADT/PointerSumType.h
+++ b/llvm/include/llvm/ADT/PointerSumType.h
@@ -255,10 +255,6 @@ struct DenseMapInfo<PointerSumType<TagT, MemberTs...>> {
       typename HelperT::template Lookup<HelperT::MinTag>::PointerT;
   using SomePointerInfo = DenseMapInfo<SomePointerT>;
 
-  static inline SumType getEmptyKey() {
-    return SumType::template create<SomeTag>(SomePointerInfo::getEmptyKey());
-  }
-
   static unsigned getHashValue(const SumType &Arg) {
     uintptr_t OpaqueValue = Arg.getOpaqueValue();
     return DenseMapInfo<uintptr_t>::getHashValue(OpaqueValue);
diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h
index 15565ee3ff51a..1577f15fa37c6 100644
--- a/llvm/include/llvm/ADT/PointerUnion.h
+++ b/llvm/include/llvm/ADT/PointerUnion.h
@@ -426,8 +426,6 @@ template <typename... PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
   using Union = PointerUnion<PTs...>;
   using FirstInfo = DenseMapInfo<TypeAtIndex<0, PTs...>>;
 
-  static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
-
   static unsigned getHashValue(const Union &UnionVal) {
     auto Key = reinterpret_cast<uintptr_t>(UnionVal.getOpaqueValue());
     return DenseMapInfo<uintptr_t>::getHashValue(Key);
diff --git a/llvm/include/llvm/ADT/SmallBitVector.h b/llvm/include/llvm/ADT/SmallBitVector.h
index 78049cbb44da5..01bd502d1552b 100644
--- a/llvm/include/llvm/ADT/SmallBitVector.h
+++ b/llvm/include/llvm/ADT/SmallBitVector.h
@@ -728,7 +728,6 @@ operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) {
 }
 
 template <> struct DenseMapInfo<SmallBitVector> {
-  static inline SmallBitVector getEmptyKey() { return SmallBitVector(); }
   static unsigned getHashValue(const SmallBitVector &V) {
     uintptr_t Store;
     return DenseMapInfo<
diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h
index 7e375792df4c0..ae369c2508113 100644
--- a/llvm/include/llvm/ADT/SmallVector.h
+++ b/llvm/include/llvm/ADT/SmallVector.h
@@ -1349,10 +1349,6 @@ extern template class llvm::SmallVectorBase<uint64_t>;
 
 // Provide DenseMapInfo for SmallVector of a type which has info.
 template <typename T, unsigned N> struct DenseMapInfo<llvm::SmallVector<T, N>> {
-  static SmallVector<T, N> getEmptyKey() {
-    return {DenseMapInfo<T>::getEmptyKey()};
-  }
-
   static unsigned getHashValue(const SmallVector<T, N> &V) {
     return static_cast<unsigned>(hash_combine_range(V));
   }
diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h
index f15e120451638..9a8c8d21bf3cd 100644
--- a/llvm/include/llvm/ADT/StringRef.h
+++ b/llvm/include/llvm/ADT/StringRef.h
@@ -951,18 +951,9 @@ inline uint64_t xxh3_64bits(StringRef data) {
 
 // Provide DenseMapInfo for StringRefs.
 template <> struct DenseMapInfo<StringRef, void> {
-  static inline StringRef getEmptyKey() {
-    return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
-                     0);
-  }
-
   LLVM_ABI static unsigned getHashValue(StringRef Val);
 
-  static bool isEqual(StringRef LHS, StringRef RHS) {
-    if (RHS.data() == getEmptyKey().data())
-      return LHS.data() == getEmptyKey().data();
-    return LHS == RHS;
-  }
+  static bool isEqual(StringRef LHS, StringRef RHS) { return LHS == RHS; }
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/Support/FileSystem/UniqueID.h b/llvm/include/llvm/Support/FileSystem/UniqueID.h
index 3bfd8b7405505..60bf36be39e41 100644
--- a/llvm/include/llvm/Support/FileSystem/UniqueID.h
+++ b/llvm/include/llvm/Support/FileSystem/UniqueID.h
@@ -53,11 +53,6 @@ class UniqueID {
 
 // Support UniqueIDs as DenseMap keys.
 template <> struct DenseMapInfo<llvm::sys::fs::UniqueID> {
-  static inline llvm::sys::fs::UniqueID getEmptyKey() {
-    auto EmptyKey = DenseMapInfo<std::pair<uint64_t, uint64_t>>::getEmptyKey();
-    return {EmptyKey.first, EmptyKey.second};
-  }
-
   static hash_code getHashValue(const llvm::sys::fs::UniqueID &Tag) {
     return hash_value(std::make_pair(Tag.getDevice(), Tag.getFile()));
   }
diff --git a/llvm/include/llvm/Support/TypeSize.h b/llvm/include/llvm/Support/TypeSize.h
index c60bae2872f92..9e99ec26aeb83 100644
--- a/llvm/include/llvm/Support/TypeSize.h
+++ b/llvm/include/llvm/Support/TypeSize.h
@@ -431,9 +431,6 @@ operator<<(raw_ostream &OS,
 }
 
 template <> struct DenseMapInfo<ElementCount, void> {
-  static inline ElementCount getEmptyKey() {
-    return ElementCount::getScalable(~0U);
-  }
   static unsigned getHashValue(const ElementCount &EltCnt) {
     unsigned HashVal = EltCnt.getKnownMinValue() * 37U;
     if (EltCnt.isScalable())
diff --git a/llvm/include/llvm/Support/UniqueBBID.h b/llvm/include/llvm/Support/UniqueBBID.h
index f29e6126b5f94..b252710afff12 100644
--- a/llvm/include/llvm/Support/UniqueBBID.h
+++ b/llvm/include/llvm/Support/UniqueBBID.h
@@ -44,11 +44,6 @@ struct PrefetchHint {
 
 // Provides DenseMapInfo for UniqueBBID.
 template <> struct DenseMapInfo<UniqueBBID> {
-  static inline UniqueBBID getEmptyKey() {
-    unsigned EmptyKey = DenseMapInfo<unsigned>::getEmptyKey();
-    return UniqueBBID{EmptyKey, EmptyKey};
-  }
-
   static unsigned getHashValue(const UniqueBBID &Val) {
     return DenseMapInfo<unsigned>::getHashValue(Val.BaseID) ^
            DenseMapInfo<unsigned>::getHashValue(Val.CloneID);
diff --git a/llvm/include/llvm/Support/VersionTuple.h b/llvm/include/llvm/Support/VersionTuple.h
index ac2e3c7af25e1..cae3a88e7a429 100644
--- a/llvm/include/llvm/Support/VersionTuple.h
+++ b/llvm/include/llvm/Support/VersionTuple.h
@@ -215,7 +215,6 @@ LLVM_ABI raw_ostream &operator<<(raw_ostream &Out, const VersionTuple &V);
 
 // Provide DenseMapInfo for version tuples.
 template <> struct DenseMapInfo<VersionTuple> {
-  static inline VersionTuple getEmptyKey() { return VersionTuple(0x7FFFFFFF); }
   static unsigned getHashValue(const VersionTuple &Value) {
     unsigned Result = Value.getMajor();
     if (auto Minor = Value.getMinor())
diff --git a/llvm/lib/Support/StringRef.cpp b/llvm/lib/Support/StringRef.cpp
index be1c63ef82114..02270a6e223af 100644
--- a/llvm/lib/Support/StringRef.cpp
+++ b/llvm/lib/Support/StringRef.cpp
@@ -610,6 +610,5 @@ bool StringRef::getAsDouble(double &Result, bool AllowInexact) const {
 hash_code llvm::hash_value(StringRef S) { return hash_combine_range(S); }
 
 unsigned DenseMapInfo<StringRef, void>::getHashValue(StringRef Val) {
-  assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
   return (unsigned)(hash_value(Val));
 }
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index 88c3fd112cc98..2907a1fefdb03 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -85,7 +85,6 @@ class CtorTester {
 std::set<CtorTester *> CtorTester::Constructed;
 
 struct CtorTesterMapInfo {
-  static inline CtorTester getEmptyKey() { return CtorTester(-1); }
   static unsigned getHashValue(const CtorTester &Val) {
     return Val.getValue() * 37u;
   }
@@ -731,7 +730,6 @@ TEST(DenseMapCustomTest, LookupOrConstness) {
 // Key traits that allows lookup with either an unsigned or char* key;
 // In the latter case, "a" == 0, "b" == 1 and so on.
 struct TestDenseMapInfo {
-  static inline unsigned getEmptyKey() { return ~0; }
   static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
   static unsigned getHashValue(const char* Val) {
     return (unsigned)(Val[0] - 'a') * 37U;
@@ -787,7 +785,6 @@ TEST(DenseMapCustomTest, SmallDenseMapInitializerList) {
 }
 
 struct ContiguousDenseMapInfo {
-  static inline unsigned getEmptyKey() { return ~0; }
   static unsigned getHashValue(const unsigned& Val) { return Val; }
   static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
     return LHS == RHS;
@@ -912,7 +909,6 @@ struct AlwaysEqType {
 namespace llvm {
 template <typename T>
 struct DenseMapInfo<T, std::enable_if_t<std::is_base_of_v<A, T>>> {
-  static inline T getEmptyKey() { return {static_cast<int>(~0)}; }
   static unsigned getHashValue(const T &Val) { return Val.value; }
   static bool isEqual(const T &LHS, const T &RHS) {
     return LHS.value == RHS.value;
@@ -921,7 +917,6 @@ struct DenseMapInfo<T, std::enable_if_t<std::is_base_of_v<A, T>>> {
 
 template <> struct DenseMapInfo<AlwaysEqType> {
   using T = AlwaysEqType;
-  static inline T getEmptyKey() { return {}; }
   static unsigned getHashValue(const T &Val) { return 0; }
   static bool isEqual(const T &LHS, const T &RHS) {
     return false;
diff --git a/llvm/unittests/ADT/DenseSetTest.cpp b/llvm/unittests/ADT/DenseSetTest.cpp
index 5466292dc5992..11500e835b23d 100644
--- a/llvm/unittests/ADT/DenseSetTest.cpp
+++ b/llvm/unittests/ADT/DenseSetTest.cpp
@@ -82,7 +82,6 @@ TEST(DenseSetTest, RemoveIf) {
 }
 
 struct TestDenseSetInfo {
-  static inline unsigned getEmptyKey() { return ~0; }
   static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
   static unsigned getHashValue(const char* Val) {
     return (unsigned)(Val[0] - 'a') * 37U;
@@ -229,7 +228,6 @@ int CountCopyAndMove::Move = 0;
 namespace llvm {
 // Specialization required to insert a CountCopyAndMove into a DenseSet.
 template <> struct DenseMapInfo<CountCopyAndMove> {
-  static inline CountCopyAndMove getEmptyKey() { return CountCopyAndMove(-1); };
   static unsigned getHashValue(const CountCopyAndMove &Val) {
     return Val.Value;
   }
diff --git a/llvm/unittests/ADT/MapVectorTest.cpp b/llvm/unittests/ADT/MapVectorTest.cpp
index c2eabe4a0f850..40833b2c1a794 100644
--- a/llvm/unittests/ADT/MapVectorTest.cpp
+++ b/llvm/unittests/ADT/MapVectorTest.cpp
@@ -35,7 +35,6 @@ struct A : CountCopyAndMove {
 
 namespace llvm {
 template <> struct DenseMapInfo<A> {
-  static inline A getEmptyKey() { return 0x7fffffff; }
   static unsigned getHashValue(const A &Val) { return (unsigned)(Val.v * 37U); }
   static bool isEqual(const A &LHS, const A &RHS) { return LHS.v == RHS.v; }
 };
diff --git a/llvm/unittests/Support/ReverseIterationTest.cpp b/llvm/unittests/Support/ReverseIterationTest.cpp
index 8d0c3365523a7..8118ccbe525ff 100644
--- a/llvm/unittests/Support/ReverseIterationTest.cpp
+++ b/llvm/unittests/Support/ReverseIterationTest.cpp
@@ -61,11 +61,6 @@ struct PtrLikeInt { int value; };
 namespace llvm {
 
 template<> struct DenseMapInfo<PtrLikeInt *> {
-  static PtrLikeInt *getEmptyKey() {
-    static PtrLikeInt EmptyKey;
-    return &EmptyKey;
-  }
-
   static int getHashValue(const PtrLikeInt *P) {
     return P->value;
   }

>From 05e793ea754bbf0720cdfddc91261b4baecc7df1 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 5 Jun 2026 21:44:47 -0700
Subject: [PATCH 2/4] Simplify nullopt hash to return 0

---
 llvm/include/llvm/ADT/DenseMapInfo.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 273033a21df0e..848ccb0950cb5 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -191,7 +191,7 @@ template <typename T> struct DenseMapInfo<std::optional<T>> {
   static unsigned getHashValue(const Optional &OptionalVal) {
     if (OptionalVal)
       return detail::combineHashValue(1, Info::getHashValue(*OptionalVal));
-    return detail::combineHashValue(0, 0);
+    return 0;
   }
 
   static bool isEqual(const Optional &LHS, const Optional &RHS) {

>From b3abb77264fd7f6bef991b86bfbb5e74583dab31 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 5 Jun 2026 22:01:01 -0700
Subject: [PATCH 3/4] Unify char into the generic integral DenseMapInfo

---
 llvm/include/llvm/ADT/DenseMapInfo.h | 19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 848ccb0950cb5..d3a44eb7efd5a 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -76,24 +76,9 @@ struct DenseMapInfo<T*> {
   static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
 };
 
-// Provide DenseMapInfo for chars.
-template<> struct DenseMapInfo<char> {
-  static unsigned getHashValue(const char& Val) { return Val * 37U; }
-
-  static bool isEqual(const char &LHS, const char &RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for all integral types except char.
-//
-// The "char" case is excluded because it uses ~0 as the empty key despite
-// "char" being a signed type.  "std::is_same_v<T, char>" is included below
-// for clarity; technically, we do not need it because the explicit
-// specialization above "wins",
+// Provide DenseMapInfo for all integral types.
 template <typename T>
-struct DenseMapInfo<
-    T, std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, char>>> {
+struct DenseMapInfo<T, std::enable_if_t<std::is_integral_v<T>>> {
   static unsigned getHashValue(const T &Val) {
     if constexpr (std::is_unsigned_v<T> && sizeof(T) > sizeof(unsigned))
       return densemap::detail::mix(Val);

>From 9fcd0835b85e1ca0fb930f6521d06b13e9056374 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 6 Jun 2026 11:50:23 -0700
Subject: [PATCH 4/4] Rebase onto main; remove dead empty-key helpers per
 review

---
 llvm/include/llvm/ADT/CachedHashString.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/llvm/include/llvm/ADT/CachedHashString.h b/llvm/include/llvm/ADT/CachedHashString.h
index e28944b271298..2200d70e57b37 100644
--- a/llvm/include/llvm/ADT/CachedHashString.h
+++ b/llvm/include/llvm/ADT/CachedHashString.h
@@ -75,13 +75,6 @@ class CachedHashString {
 
   bool isEmpty() const { return P == getEmptyKeyPtr(); }
 
-  struct ConstructEmptyTy {};
-
-  CachedHashString(ConstructEmptyTy, char *EmptyKeyPtr)
-      : P(EmptyKeyPtr), Size(0), Hash(0) {
-    assert(isEmpty());
-  }
-
   // TODO: Use small-string optimization to avoid allocating.
 
 public:



More information about the llvm-commits mailing list