[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