[llvm] [ADT] Modernize IndexedMap to use llvm::identity_cxx20 (NFC) (PR #164568)

Kazu Hirata via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 22 08:51:48 PDT 2025


https://github.com/kazutakahirata updated https://github.com/llvm/llvm-project/pull/164568

>From 1c04cee59adae37c3bec49d93763c11425e7e96c Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Sun, 19 Oct 2025 18:02:42 -0700
Subject: [PATCH 1/2] [ADT] Modernize IndexedMap to use llvm::identity_cxx20
 (NFC)

The legacy llvm::identity differs from std::identity in C++20.
llvm::identity is a template struct with an ::argument_type member. In
contrast, llvm::identity_cxx20 (and std::identity) is a non-template
struct with a templated call operator and no ::argument_type.

This patch modernizes llvm::IndexedMap by updating its default functor
to llvm::identity_cxx20.  A new template parameter IndexT now
fulfills the role of ::argument_type.

To avoid modifying numerous existing IndexedMap uses with custom
functors (e.g., VirtReg2IndexFunctor), the detail::DeduceIndexType
helper automatically deduces IndexT.  It deduces ::argument_type for
legacy functors and unsigned for llvm::identity_cxx20.
---
 llvm/include/llvm/ADT/IndexedMap.h | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/ADT/IndexedMap.h b/llvm/include/llvm/ADT/IndexedMap.h
index cda0316dc78fa..8526db9cdf4e8 100644
--- a/llvm/include/llvm/ADT/IndexedMap.h
+++ b/llvm/include/llvm/ADT/IndexedMap.h
@@ -21,14 +21,33 @@
 #define LLVM_ADT_INDEXEDMAP_H
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/identity.h"
 #include <cassert>
+#include <type_traits>
 
 namespace llvm {
 
-template <typename T, typename ToIndexT = identity<unsigned>> class IndexedMap {
-  using IndexT = typename ToIndexT::argument_type;
+namespace detail {
+// Helper to compute the IndexT for IndexedMap.
+template <typename ToIndexT, typename = void> struct DeduceIndexType {
+  using type =
+      std::conditional_t<std::is_same_v<ToIndexT, llvm::identity_cxx20>,
+                         unsigned, void>;
+};
+
+template <typename ToIndexT>
+struct DeduceIndexType<ToIndexT,
+                       std::void_t<typename ToIndexT::argument_type>> {
+  using type = typename ToIndexT::argument_type;
+};
+} // namespace detail
+
+template <typename T, typename ToIndexT = llvm::identity_cxx20,
+          typename IndexT = typename detail::DeduceIndexType<ToIndexT>::type>
+class IndexedMap {
+  static_assert(!std::is_same_v<IndexT, void>,
+                "Could not deduce index type from the provided functor.");
   // Prefer SmallVector with zero inline storage over std::vector. IndexedMaps
   // can grow very large and SmallVector grows more efficiently as long as T
   // is trivially copyable.

>From 8869a6e3754a205681f7d25677c45e9c8b909a84 Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Wed, 22 Oct 2025 07:56:35 -0700
Subject: [PATCH 2/2] [ADT] Modernize IndexedMap with llvm::identity_cxx20
 (NFC)

C++ is evolving in the direction of removing type alias
"argument_type" from functors.

This patch changes the default functor type to llvm::identity_cxx20,
backported from C++20, while templatizing those methods that use
toIndex_ with IndexT.  This way we no longer need to take
argument_type from ToIndexT.

Now, identity_cxx20()(int) is of type int, causing mixed sign
comparisons, so this patch first assigns the result to a temporary
variable of type unsigned before feeding it to assert.
---
 llvm/include/llvm/ADT/IndexedMap.h | 42 ++++++++++--------------------
 1 file changed, 14 insertions(+), 28 deletions(-)

diff --git a/llvm/include/llvm/ADT/IndexedMap.h b/llvm/include/llvm/ADT/IndexedMap.h
index 8526db9cdf4e8..e6b8c36ceed8a 100644
--- a/llvm/include/llvm/ADT/IndexedMap.h
+++ b/llvm/include/llvm/ADT/IndexedMap.h
@@ -20,34 +20,14 @@
 #ifndef LLVM_ADT_INDEXEDMAP_H
 #define LLVM_ADT_INDEXEDMAP_H
 
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallVector.h"
 #include <cassert>
-#include <type_traits>
 
 namespace llvm {
 
-namespace detail {
-// Helper to compute the IndexT for IndexedMap.
-template <typename ToIndexT, typename = void> struct DeduceIndexType {
-  using type =
-      std::conditional_t<std::is_same_v<ToIndexT, llvm::identity_cxx20>,
-                         unsigned, void>;
-};
-
-template <typename ToIndexT>
-struct DeduceIndexType<ToIndexT,
-                       std::void_t<typename ToIndexT::argument_type>> {
-  using type = typename ToIndexT::argument_type;
-};
-} // namespace detail
-
-template <typename T, typename ToIndexT = llvm::identity_cxx20,
-          typename IndexT = typename detail::DeduceIndexType<ToIndexT>::type>
+template <typename T, typename ToIndexT = llvm::identity_cxx20>
 class IndexedMap {
-  static_assert(!std::is_same_v<IndexT, void>,
-                "Could not deduce index type from the provided functor.");
   // Prefer SmallVector with zero inline storage over std::vector. IndexedMaps
   // can grow very large and SmallVector grows more efficiently as long as T
   // is trivially copyable.
@@ -62,14 +42,17 @@ class IndexedMap {
 
   explicit IndexedMap(const T &val) : nullVal_(val) {}
 
-  typename StorageT::reference operator[](IndexT n) {
-    assert(toIndex_(n) < storage_.size() && "index out of bounds!");
-    return storage_[toIndex_(n)];
+  template <typename IndexT> typename StorageT::reference operator[](IndexT n) {
+    unsigned Index = toIndex_(n);
+    assert(Index < storage_.size() && "index out of bounds!");
+    return storage_[Index];
   }
 
+  template <typename IndexT>
   typename StorageT::const_reference operator[](IndexT n) const {
-    assert(toIndex_(n) < storage_.size() && "index out of bounds!");
-    return storage_[toIndex_(n)];
+    unsigned Index = toIndex_(n);
+    assert(Index < storage_.size() && "index out of bounds!");
+    return storage_[Index];
   }
 
   void reserve(typename StorageT::size_type s) { storage_.reserve(s); }
@@ -78,13 +61,16 @@ class IndexedMap {
 
   void clear() { storage_.clear(); }
 
-  void grow(IndexT n) {
+  template <typename IndexT> void grow(IndexT n) {
     unsigned NewSize = toIndex_(n) + 1;
     if (NewSize > storage_.size())
       resize(NewSize);
   }
 
-  bool inBounds(IndexT n) const { return toIndex_(n) < storage_.size(); }
+  template <typename IndexT> bool inBounds(IndexT n) const {
+    unsigned Index = toIndex_(n);
+    return Index < storage_.size();
+  }
 
   typename StorageT::size_type size() const { return storage_.size(); }
 };



More information about the llvm-commits mailing list