[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