[llvm] [ADT] Modernize IndexedMap with llvm::identity_cxx20 (NFC) (PR #164568)
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 22 13:00:26 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/3] [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/3] [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(); }
};
>From 20e337977fd4b63e2ba306e852b949b1ad56343a Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Wed, 22 Oct 2025 12:32:29 -0700
Subject: [PATCH 3/3] [ADT] Move llvm::identity into IndexedMap (NFC)
This patch moves llvm::identity to IndexedMap for two reasons:
- llvm::identity is used only IndexedMap.
- llvm::identity is not suitable for general use as it is not quite
the same as std::identity despite the comments in identity.h.
Also, this patch renames the class to IdentityIndex and places it in
the "detail" namespace.
---
llvm/include/llvm/ADT/IndexedMap.h | 35 +++++++++++--------
llvm/include/llvm/ADT/identity.h | 31 ----------------
llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h | 1 -
3 files changed, 20 insertions(+), 47 deletions(-)
delete mode 100644 llvm/include/llvm/ADT/identity.h
diff --git a/llvm/include/llvm/ADT/IndexedMap.h b/llvm/include/llvm/ADT/IndexedMap.h
index e6b8c36ceed8a..fca7981270dbb 100644
--- a/llvm/include/llvm/ADT/IndexedMap.h
+++ b/llvm/include/llvm/ADT/IndexedMap.h
@@ -20,14 +20,25 @@
#ifndef LLVM_ADT_INDEXEDMAP_H
#define LLVM_ADT_INDEXEDMAP_H
-#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
namespace llvm {
-template <typename T, typename ToIndexT = llvm::identity_cxx20>
+namespace detail {
+template <class Ty> struct IdentityIndex {
+ using is_transparent = void;
+ using argument_type = Ty;
+
+ Ty &operator()(Ty &self) const { return self; }
+ const Ty &operator()(const Ty &self) const { return self; }
+};
+} // namespace detail
+
+template <typename T, typename ToIndexT = detail::IdentityIndex<unsigned>>
class IndexedMap {
+ using IndexT = typename ToIndexT::argument_type;
// 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.
@@ -42,17 +53,14 @@ class IndexedMap {
explicit IndexedMap(const T &val) : nullVal_(val) {}
- template <typename IndexT> typename StorageT::reference operator[](IndexT n) {
- unsigned Index = toIndex_(n);
- assert(Index < storage_.size() && "index out of bounds!");
- return storage_[Index];
+ typename StorageT::reference operator[](IndexT n) {
+ assert(toIndex_(n) < storage_.size() && "index out of bounds!");
+ return storage_[toIndex_(n)];
}
- template <typename IndexT>
typename StorageT::const_reference operator[](IndexT n) const {
- unsigned Index = toIndex_(n);
- assert(Index < storage_.size() && "index out of bounds!");
- return storage_[Index];
+ assert(toIndex_(n) < storage_.size() && "index out of bounds!");
+ return storage_[toIndex_(n)];
}
void reserve(typename StorageT::size_type s) { storage_.reserve(s); }
@@ -61,16 +69,13 @@ class IndexedMap {
void clear() { storage_.clear(); }
- template <typename IndexT> void grow(IndexT n) {
+ void grow(IndexT n) {
unsigned NewSize = toIndex_(n) + 1;
if (NewSize > storage_.size())
resize(NewSize);
}
- template <typename IndexT> bool inBounds(IndexT n) const {
- unsigned Index = toIndex_(n);
- return Index < storage_.size();
- }
+ bool inBounds(IndexT n) const { return toIndex_(n) < storage_.size(); }
typename StorageT::size_type size() const { return storage_.size(); }
};
diff --git a/llvm/include/llvm/ADT/identity.h b/llvm/include/llvm/ADT/identity.h
deleted file mode 100644
index 88d033fc01141..0000000000000
--- a/llvm/include/llvm/ADT/identity.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- llvm/ADT/Identity.h - Provide std::identity from C++20 ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides an implementation of std::identity from C++20.
-//
-// No library is required when using these functions.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ADT_IDENTITY_H
-#define LLVM_ADT_IDENTITY_H
-
-namespace llvm {
-
-// Similar to `std::identity` from C++20.
-template <class Ty> struct identity {
- using is_transparent = void;
- using argument_type = Ty;
-
- Ty &operator()(Ty &self) const { return self; }
- const Ty &operator()(const Ty &self) const { return self; }
-};
-
-} // namespace llvm
-
-#endif // LLVM_ADT_IDENTITY_H
diff --git a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
index 4eacbdca163d9..26d708060ed6d 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -18,7 +18,6 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SparseMultiSet.h"
-#include "llvm/ADT/identity.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
More information about the llvm-commits
mailing list