[llvm] DenseMapInfo: support std::optional<T> (PR #147851)

Elijah Kin via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 10 09:05:07 PDT 2025


https://github.com/elijahkin updated https://github.com/llvm/llvm-project/pull/147851

>From c93c4c476b3fb07b56783b327ea2f63034b47b56 Mon Sep 17 00:00:00 2001
From: Elijah Kin <elijah.m.kin at gmail.com>
Date: Wed, 9 Jul 2025 16:05:28 -0700
Subject: [PATCH 1/7] [ADT] Implement DenseMapInfo of std::optional<T>

---
 llvm/include/llvm/ADT/DenseMapInfo.h | 29 ++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 07c37e353a40b..65c607910d089 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -320,6 +320,35 @@ struct DenseMapInfo<Enum, std::enable_if_t<std::is_enum_v<Enum>>> {
 
   static bool isEqual(const Enum &LHS, const Enum &RHS) { return LHS == RHS; }
 };
+
+template <typename T>
+struct DenseMapInfo<std::optional<T>> {
+  using Optional = std::optional<T>;
+  using Info = DenseMapInfo<T>;
+
+  static inline Optional getEmptyKey() {
+    return std::make_optional(Info::getEmptyKey());
+  }
+
+  static inline Optional getTombstoneKey() {
+    return std::make_optional(Info::getTombstoneKey());
+  }
+
+  static unsigned getHashValue(const Optional &OptionalVal) {
+    return detail::combineHashValue(
+        OptionalVal.has_value(),
+        Info::getHashValue(OptionalVal.value_or(Info::getEmptyKey())));
+  }
+
+  static bool isEqual(const Optional &LHS, const Optional &RHS) {
+    if (LHS.has_value() && RHS.has_value()) {
+      return Info::isEqual(LHS.value(), RHS.value());
+    } else if (!LHS.has_value() && !RHS.has_value()) {
+      return true;
+    }
+    return false;
+  }
+};
 } // end namespace llvm
 
 #endif // LLVM_ADT_DENSEMAPINFO_H

>From f7a244c61bc7431a3fd4d7a3a5ecad215a2e4623 Mon Sep 17 00:00:00 2001
From: Elijah Kin <elijah.m.kin at gmail.com>
Date: Wed, 9 Jul 2025 16:23:33 -0700
Subject: [PATCH 2/7] Registering std::optional<uint32_t> for testing

---
 llvm/unittests/ADT/DenseMapTest.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index c95f96c4bb3c6..ca04dc055fd11 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -15,6 +15,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include <map>
+#include <optional>
 #include <set>
 #include <utility>
 #include <variant>
@@ -117,11 +118,13 @@ typedef ::testing::Types<DenseMap<uint32_t, uint32_t>,
                          DenseMap<uint32_t *, uint32_t *>,
                          DenseMap<CtorTester, CtorTester, CtorTesterMapInfo>,
                          DenseMap<EnumClass, uint32_t>,
+                         DenseMap<std::optional<uint32_t>, uint32_t>,
                          SmallDenseMap<uint32_t, uint32_t>,
                          SmallDenseMap<uint32_t *, uint32_t *>,
                          SmallDenseMap<CtorTester, CtorTester, 4,
                                        CtorTesterMapInfo>,
-                         SmallDenseMap<EnumClass, uint32_t>
+                         SmallDenseMap<EnumClass, uint32_t>,
+                         SmallDenseMap<std::optional<uint32_t>, uint32_t>
                          > DenseMapTestTypes;
 // clang-format on
 

>From c8b3e811002abae1d05d4640d558789d88c22d33 Mon Sep 17 00:00:00 2001
From: Elijah Kin <elijah.m.kin at gmail.com>
Date: Wed, 9 Jul 2025 16:46:58 -0700
Subject: [PATCH 3/7] Avoiding else after return

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

diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 65c607910d089..2dd2ff4f6f022 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -341,12 +341,10 @@ struct DenseMapInfo<std::optional<T>> {
   }
 
   static bool isEqual(const Optional &LHS, const Optional &RHS) {
-    if (LHS.has_value() && RHS.has_value()) {
+    if (LHS && RHS) {
       return Info::isEqual(LHS.value(), RHS.value());
-    } else if (!LHS.has_value() && !RHS.has_value()) {
-      return true;
     }
-    return false;
+    return !LHS && !RHS;
   }
 };
 } // end namespace llvm

>From fb6a46e7b8f69762f4b9915b2588db7c3087001c Mon Sep 17 00:00:00 2001
From: Elijah Kin <elijah.m.kin at gmail.com>
Date: Wed, 9 Jul 2025 17:16:49 -0700
Subject: [PATCH 4/7] Including <optional> in DenseMapInfo

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

diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 2dd2ff4f6f022..2afde292e03bf 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 <optional>
 #include <tuple>
 #include <type_traits>
 #include <utility>

>From bf9ece3f82a182c0e9c83ecdfd4456ec933f6702 Mon Sep 17 00:00:00 2001
From: Elijah Kin <elijah.m.kin at gmail.com>
Date: Wed, 9 Jul 2025 17:26:55 -0700
Subject: [PATCH 5/7] Remove newline after template

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

diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 2afde292e03bf..1c20c25ec385d 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -322,8 +322,7 @@ struct DenseMapInfo<Enum, std::enable_if_t<std::is_enum_v<Enum>>> {
   static bool isEqual(const Enum &LHS, const Enum &RHS) { return LHS == RHS; }
 };
 
-template <typename T>
-struct DenseMapInfo<std::optional<T>> {
+template <typename T> struct DenseMapInfo<std::optional<T>> {
   using Optional = std::optional<T>;
   using Info = DenseMapInfo<T>;
 

>From ddae4e75df2b44b219cd4c7289587379335cc517 Mon Sep 17 00:00:00 2001
From: Elijah Kin <elijah.m.kin at gmail.com>
Date: Thu, 10 Jul 2025 09:03:41 -0700
Subject: [PATCH 6/7] Avoid make_optional

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

diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 1c20c25ec385d..b850223c953da 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -326,13 +326,9 @@ template <typename T> struct DenseMapInfo<std::optional<T>> {
   using Optional = std::optional<T>;
   using Info = DenseMapInfo<T>;
 
-  static inline Optional getEmptyKey() {
-    return std::make_optional(Info::getEmptyKey());
-  }
+  static inline Optional getEmptyKey() { return {Info::getEmptyKey()}; }
 
-  static inline Optional getTombstoneKey() {
-    return std::make_optional(Info::getTombstoneKey());
-  }
+  static inline Optional getTombstoneKey() { return {Info::getTombstoneKey()}; }
 
   static unsigned getHashValue(const Optional &OptionalVal) {
     return detail::combineHashValue(

>From 6d62db86e2d318793f1f1d749c8c5993f72a518e Mon Sep 17 00:00:00 2001
From: Elijah Kin <elijah.m.kin at gmail.com>
Date: Thu, 10 Jul 2025 09:04:55 -0700
Subject: [PATCH 7/7] Adding getTestKey and getTestValue for std::optional<T>

---
 llvm/unittests/ADT/DenseMapTest.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index ca04dc055fd11..e3e8e8cf059ec 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -87,6 +87,14 @@ struct CtorTesterMapInfo {
 CtorTester getTestKey(int i, CtorTester *) { return CtorTester(i); }
 CtorTester getTestValue(int i, CtorTester *) { return CtorTester(42 + i); }
 
+std::optional<uint32_t> getTestKey(int i, std::optional<uint32_t> *) {
+  return i;
+}
+
+std::optional<uint32_t> getTestValue(int i, std::optional<uint32_t> *) {
+  return 42 + i;
+}
+
 // Test fixture, with helper functions implemented by forwarding to global
 // function overloads selected by component types of the type parameter. This
 // allows all of the map implementations to be tested with shared



More information about the llvm-commits mailing list