[llvm] [ADT] Refactor DenseMapInfo for integer types (NFC) (PR #155549)
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 27 08:24:49 PDT 2025
https://github.com/kazutakahirata updated https://github.com/llvm/llvm-project/pull/155549
>From b367166de18261d5027f1e7d59ef75ad8cdd3d8d Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Mon, 25 Aug 2025 11:47:04 -0700
Subject: [PATCH 1/2] [ADT] Refactor DenseMapInfo for integer types (NFC)
This patch consolidates DenseMapInfo<T> for integer types T with a
common templated implementation. DenseMapInfo<char> is excluded
because it uses ~0 for the empty key despite char being a signed type.
Also, we preserve the tombstone key value for long, which is:
std::numeric_limits<long>::max() - 1
---
llvm/include/llvm/ADT/DenseMapInfo.h | 133 +++++----------------------
1 file changed, 22 insertions(+), 111 deletions(-)
diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 9d8fd893540a3..a3a459930b38a 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -17,6 +17,7 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
+#include <limits>
#include <optional>
#include <tuple>
#include <type_traits>
@@ -101,122 +102,32 @@ template<> struct DenseMapInfo<char> {
}
};
-// Provide DenseMapInfo for unsigned chars.
-template <> struct DenseMapInfo<unsigned char> {
- static constexpr unsigned char getEmptyKey() { return ~0; }
- static constexpr unsigned char getTombstoneKey() { return ~0 - 1; }
- static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; }
-
- static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) {
- return LHS == RHS;
- }
-};
-
-// Provide DenseMapInfo for unsigned shorts.
-template <> struct DenseMapInfo<unsigned short> {
- static constexpr unsigned short getEmptyKey() { return 0xFFFF; }
- static constexpr unsigned short getTombstoneKey() { return 0xFFFF - 1; }
- static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
-
- static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
- return LHS == RHS;
- }
-};
-
-// Provide DenseMapInfo for unsigned ints.
-template<> struct DenseMapInfo<unsigned> {
- static constexpr unsigned getEmptyKey() { return ~0U; }
- static constexpr unsigned getTombstoneKey() { return ~0U - 1; }
- static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
-
- static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
- return LHS == RHS;
- }
-};
-
-// Provide DenseMapInfo for unsigned longs.
-template<> struct DenseMapInfo<unsigned long> {
- static constexpr unsigned long getEmptyKey() { return ~0UL; }
- static constexpr unsigned long getTombstoneKey() { return ~0UL - 1L; }
-
- static unsigned getHashValue(const unsigned long& Val) {
- if constexpr (sizeof(Val) == 4)
- return DenseMapInfo<unsigned>::getHashValue(Val);
+// 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",
+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 constexpr T getTombstoneKey() {
+ if constexpr (std::is_unsigned_v<T> || std::is_same_v<T, long>)
+ return std::numeric_limits<T>::max() - 1;
else
- return densemap::detail::mix(Val);
+ return std::numeric_limits<T>::min();
}
- static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
- return LHS == RHS;
- }
-};
-
-// Provide DenseMapInfo for unsigned long longs.
-template<> struct DenseMapInfo<unsigned long long> {
- static constexpr unsigned long long getEmptyKey() { return ~0ULL; }
- static constexpr unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
-
- static unsigned getHashValue(const unsigned long long& Val) {
- return densemap::detail::mix(Val);
- }
-
- static bool isEqual(const unsigned long long& LHS,
- const unsigned long long& RHS) {
- return LHS == RHS;
- }
-};
-
-// Provide DenseMapInfo for shorts.
-template <> struct DenseMapInfo<short> {
- static constexpr short getEmptyKey() { return 0x7FFF; }
- static constexpr short getTombstoneKey() { return -0x7FFF - 1; }
- static unsigned getHashValue(const short &Val) { return Val * 37U; }
- static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
-};
-
-// Provide DenseMapInfo for ints.
-template<> struct DenseMapInfo<int> {
- static constexpr int getEmptyKey() { return 0x7fffffff; }
- static constexpr int getTombstoneKey() { return -0x7fffffff - 1; }
- static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
-
- static bool isEqual(const int& LHS, const int& RHS) {
- return LHS == RHS;
- }
-};
-
-// Provide DenseMapInfo for longs.
-template<> struct DenseMapInfo<long> {
- static constexpr long getEmptyKey() {
- return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
- }
-
- static constexpr long getTombstoneKey() { return getEmptyKey() - 1L; }
-
- static unsigned getHashValue(const long& Val) {
- return (unsigned)(Val * 37UL);
- }
-
- static bool isEqual(const long& LHS, const long& RHS) {
- return LHS == RHS;
- }
-};
-
-// Provide DenseMapInfo for long longs.
-template<> struct DenseMapInfo<long long> {
- static constexpr long long getEmptyKey() { return 0x7fffffffffffffffLL; }
- static constexpr long long getTombstoneKey() {
- return -0x7fffffffffffffffLL - 1;
- }
-
- static unsigned getHashValue(const long long& Val) {
- return (unsigned)(Val * 37ULL);
+ static unsigned getHashValue(const T &Val) {
+ if constexpr (std::is_unsigned_v<T> && sizeof(T) > sizeof(unsigned))
+ return densemap::detail::mix(Val);
+ else
+ return (unsigned)(Val * 37U);
}
- static bool isEqual(const long long& LHS,
- const long long& RHS) {
- return LHS == RHS;
- }
+ static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; }
};
// Provide DenseMapInfo for all pairs whose members have info.
>From 3f646753ce34196cdb2fd64c0a1ddcd8b9b1d7f1 Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Wed, 27 Aug 2025 08:24:28 -0700
Subject: [PATCH 2/2] Address a comment.
---
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 a3a459930b38a..930bd4baca31d 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -124,7 +124,7 @@ struct DenseMapInfo<
if constexpr (std::is_unsigned_v<T> && sizeof(T) > sizeof(unsigned))
return densemap::detail::mix(Val);
else
- return (unsigned)(Val * 37U);
+ return static_cast<unsigned>(Val * 37U);
}
static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; }
More information about the llvm-commits
mailing list