LLVM 23.0.0git
MapVector.h
Go to the documentation of this file.
1//===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements a map that provides insertion order iteration. The
11/// interface is purposefully minimal. The key is assumed to be cheap to copy
12/// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
13/// a SmallVector.
14///
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_ADT_MAPVECTOR_H
18#define LLVM_ADT_MAPVECTOR_H
19
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/STLExtras.h"
23#include <cassert>
24#include <cstddef>
25#include <iterator>
26#include <type_traits>
27#include <utility>
28
29namespace llvm {
30
31/// This class implements a map that also provides access to all stored values
32/// in a deterministic order. The values are kept in a SmallVector<*, 0> and the
33/// mapping is done with DenseMap from Keys to indexes in that vector.
34template <typename KeyT, typename ValueT,
35 typename MapType = DenseMap<KeyT, unsigned>,
37 unsigned N = 0>
38class MapVector {
39public:
40 using key_type = KeyT;
41 using value_type = typename VectorType::value_type;
42 using size_type = typename VectorType::size_type;
43
44 using iterator = typename VectorType::iterator;
45 using const_iterator = typename VectorType::const_iterator;
46 using reverse_iterator = typename VectorType::reverse_iterator;
47 using const_reverse_iterator = typename VectorType::const_reverse_iterator;
48
49 /// Clear the MapVector and return the underlying vector.
50 [[nodiscard]] VectorType takeVector() {
51 Map.clear();
52 return std::move(Vector);
53 }
54
55 /// Returns an array reference of the underlying vector.
56 [[nodiscard]] ArrayRef<value_type> getArrayRef() const { return Vector; }
57
58 [[nodiscard]] size_type size() const { return Vector.size(); }
59
60 /// Grow the MapVector so that it can contain at least \p NumEntries items
61 /// before resizing again.
62 void reserve(size_type NumEntries) {
63 Map.reserve(NumEntries);
64 Vector.reserve(NumEntries);
65 }
66
67 [[nodiscard]] iterator begin() { return Vector.begin(); }
68 [[nodiscard]] const_iterator begin() const { return Vector.begin(); }
69 [[nodiscard]] iterator end() { return Vector.end(); }
70 [[nodiscard]] const_iterator end() const { return Vector.end(); }
71
72 [[nodiscard]] reverse_iterator rbegin() { return Vector.rbegin(); }
73 [[nodiscard]] const_reverse_iterator rbegin() const {
74 return Vector.rbegin();
75 }
76 [[nodiscard]] reverse_iterator rend() { return Vector.rend(); }
77 [[nodiscard]] const_reverse_iterator rend() const { return Vector.rend(); }
78
79 [[nodiscard]] bool empty() const { return Vector.empty(); }
80
81 [[nodiscard]] std::pair<KeyT, ValueT> &front() { return Vector.front(); }
82 [[nodiscard]] const std::pair<KeyT, ValueT> &front() const {
83 return Vector.front();
84 }
85 [[nodiscard]] std::pair<KeyT, ValueT> &back() { return Vector.back(); }
86 [[nodiscard]] const std::pair<KeyT, ValueT> &back() const {
87 return Vector.back();
88 }
89
90 void clear() {
91 Map.clear();
92 Vector.clear();
93 }
94
96 std::swap(Map, RHS.Map);
97 std::swap(Vector, RHS.Vector);
98 }
99
100 ValueT &operator[](const KeyT &Key) {
101 return try_emplace_impl(Key).first->second;
102 }
103
104 [[nodiscard]] auto keys() { return make_first_range(Vector); }
105 [[nodiscard]] auto keys() const { return make_first_range(Vector); }
106 [[nodiscard]] auto values() { return make_second_range(Vector); }
107 [[nodiscard]] auto values() const { return make_second_range(Vector); }
108
109 // Returns a copy of the value. Only allowed if ValueT is copyable.
110 [[nodiscard]] ValueT lookup(const KeyT &Key) const {
111 static_assert(std::is_copy_constructible_v<ValueT>,
112 "Cannot call lookup() if ValueT is not copyable.");
113 auto I = find(Key);
114 return I == end() ? ValueT() : I->second;
115 }
116
117 template <typename... Ts>
118 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
119 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
120 }
121 template <typename... Ts>
122 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
123 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
124 }
125
126 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
127 return try_emplace_impl(KV.first, KV.second);
128 }
129 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
130 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
131 }
132
133 template <typename V>
134 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
135 auto Ret = try_emplace(Key, std::forward<V>(Val));
136 if (!Ret.second)
137 Ret.first->second = std::forward<V>(Val);
138 return Ret;
139 }
140 template <typename V>
141 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
142 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
143 if (!Ret.second)
144 Ret.first->second = std::forward<V>(Val);
145 return Ret;
146 }
147
148 [[nodiscard]] bool contains(const KeyT &Key) const {
149 return find(Key) != end();
150 }
151
152 [[nodiscard]] size_type count(const KeyT &Key) const {
153 return contains(Key) ? 1 : 0;
154 }
155
156 [[nodiscard]] iterator find(const KeyT &Key) {
157 if constexpr (canBeSmall())
158 if (isSmall())
159 return findInVector(Vector, Key);
160
161 typename MapType::const_iterator Pos = Map.find(Key);
162 return Pos == Map.end() ? Vector.end() : (Vector.begin() + Pos->second);
163 }
164
165 [[nodiscard]] const_iterator find(const KeyT &Key) const {
166 if constexpr (canBeSmall())
167 if (isSmall())
168 return findInVector(Vector, Key);
169
170 typename MapType::const_iterator Pos = Map.find(Key);
171 return Pos == Map.end() ? Vector.end() : (Vector.begin() + Pos->second);
172 }
173
174 /// at - Return the entry for the specified key, or abort if no such
175 /// entry exists.
176 [[nodiscard]] ValueT &at(const KeyT &Key) {
177 auto I = find(Key);
178 assert(I != end() && "MapVector::at failed due to a missing key");
179 return I->second;
180 }
181
182 /// at - Return the entry for the specified key, or abort if no such
183 /// entry exists.
184 [[nodiscard]] const ValueT &at(const KeyT &Key) const {
185 auto I = find(Key);
186 assert(I != end() && "MapVector::at failed due to a missing key");
187 return I->second;
188 }
189
190 /// Remove the last element from the vector.
191 void pop_back() {
192 if constexpr (canBeSmall())
193 if (isSmall()) {
194 Vector.pop_back();
195 return;
196 }
197
198 typename MapType::iterator Pos = Map.find(Vector.back().first);
199 Map.erase(Pos);
200 Vector.pop_back();
201 }
202
203 /// Remove the element given by Iterator.
204 ///
205 /// Returns an iterator to the element following the one which was removed,
206 /// which may be end().
207 ///
208 /// \note This is a deceivingly expensive operation (linear time). It's
209 /// usually better to use \a remove_if() if possible.
210 typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
211 if constexpr (canBeSmall())
212 if (isSmall())
213 return Vector.erase(Iterator);
214
215 Map.erase(Iterator->first);
216 auto Next = Vector.erase(Iterator);
217 if (Next == Vector.end())
218 return Next;
219
220 // Update indices in the map.
221 size_t Index = Next - Vector.begin();
222 for (auto &I : Map) {
223 assert(I.second != Index && "Index was already erased!");
224 if (I.second > Index)
225 --I.second;
226 }
227 return Next;
228 }
229
230 /// Remove all elements with the key value Key.
231 ///
232 /// Returns the number of elements removed.
234 auto Iterator = find(Key);
235 if (Iterator == end())
236 return 0;
237 erase(Iterator);
238 return 1;
239 }
240
241 /// Remove the elements that match the predicate.
242 ///
243 /// Erase all elements that match \c Pred in a single pass. Takes linear
244 /// time.
245 template <class Predicate> void remove_if(Predicate Pred);
246
247private:
248 template <typename VectorT, typename LookupKeyT>
249 [[nodiscard]] static auto findInVector(VectorT &Vec, const LookupKeyT &Key) {
250 return find_if(Vec, [&Key](const auto &P) { return P.first == Key; });
251 }
252
253 [[nodiscard]] static constexpr bool canBeSmall() { return N != 0; }
254
255 [[nodiscard]] bool isSmall() const { return Map.empty(); }
256
257 void makeBig() {
258 if constexpr (canBeSmall()) {
259 unsigned Index = 0;
260 for (const auto &entry : Vector)
261 Map[entry.first] = Index++;
262 }
263 }
264
265 MapType Map;
266 VectorType Vector;
267
268 static_assert(N <= 32, "Small size should be less than or equal to 32!");
269
270 static_assert(
271 std::is_integral_v<typename MapType::mapped_type>,
272 "The mapped_type of the specified Map must be an integral type");
273
274 template <typename KeyArgT, typename... Ts>
275 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
276 if constexpr (canBeSmall())
277 if (isSmall()) {
278 auto I = findInVector(Vector, Key);
279 if (I != Vector.end())
280 return {I, false};
281 Vector.emplace_back(std::piecewise_construct,
282 std::forward_as_tuple(std::forward<KeyArgT>(Key)),
283 std::forward_as_tuple(std::forward<Ts>(Args)...));
284 if (Vector.size() > N)
285 makeBig();
286 return {std::prev(end()), true};
287 }
288
289 auto [It, Inserted] = Map.try_emplace(Key);
290 if (Inserted) {
291 It->second = Vector.size();
292 Vector.emplace_back(std::piecewise_construct,
293 std::forward_as_tuple(std::forward<KeyArgT>(Key)),
294 std::forward_as_tuple(std::forward<Ts>(Args)...));
295 return {std::prev(end()), true};
296 }
297 return {begin() + It->second, false};
298 }
299};
300
301template <typename KeyT, typename ValueT, typename MapType, typename VectorType,
302 unsigned N>
303template <class Function>
305 if constexpr (canBeSmall())
306 if (isSmall()) {
307 Vector.erase(llvm::remove_if(Vector, Pred), Vector.end());
308 return;
309 }
310
311 auto O = Vector.begin();
312 for (auto I = O, E = Vector.end(); I != E; ++I) {
313 if (Pred(*I)) {
314 // Erase from the map.
315 Map.erase(I->first);
316 continue;
317 }
318
319 if (I != O) {
320 // Move the value and update the index in the map.
321 *O = std::move(*I);
322 Map[O->first] = O - Vector.begin();
323 }
324 ++O;
325 }
326 // Erase trailing entries in the vector.
327 Vector.erase(O, Vector.end());
328}
329
330/// A MapVector that performs no allocations if smaller than a certain
331/// size.
332template <typename KeyT, typename ValueT, unsigned N>
333struct SmallMapVector : MapVector<KeyT, ValueT, DenseMap<KeyT, unsigned>,
334 SmallVector<std::pair<KeyT, ValueT>, N>, N> {
335};
336
337} // end namespace llvm
338
339#endif // LLVM_ADT_MAPVECTOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
#define I(x, y, z)
Definition MD5.cpp:57
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
Value * RHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
const std::pair< KeyT, ValueT > & back() const
Definition MapVector.h:86
size_type erase(const KeyT &Key)
Remove all elements with the key value Key.
Definition MapVector.h:233
void pop_back()
Remove the last element from the vector.
Definition MapVector.h:191
const_iterator begin() const
Definition MapVector.h:68
ValueT lookup(const KeyT &Key) const
Definition MapVector.h:110
ArrayRef< value_type > getArrayRef() const
Returns an array reference of the underlying vector.
Definition MapVector.h:56
iterator begin()
Definition MapVector.h:67
iterator find(const KeyT &Key)
Definition MapVector.h:156
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition MapVector.h:122
typename VectorType::const_iterator const_iterator
Definition MapVector.h:45
iterator end()
Definition MapVector.h:69
void reserve(size_type NumEntries)
Grow the MapVector so that it can contain at least NumEntries items before resizing again.
Definition MapVector.h:62
const_iterator end() const
Definition MapVector.h:70
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition MapVector.h:118
typename VectorType::iterator iterator
Definition MapVector.h:44
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition MapVector.h:134
VectorType takeVector()
Clear the MapVector and return the underlying vector.
Definition MapVector.h:50
typename VectorType::reverse_iterator reverse_iterator
Definition MapVector.h:46
bool empty() const
Definition MapVector.h:79
reverse_iterator rend()
Definition MapVector.h:76
void swap(MapVector &RHS)
Definition MapVector.h:95
bool contains(const KeyT &Key) const
Definition MapVector.h:148
auto keys() const
Definition MapVector.h:105
void remove_if(Predicate Pred)
Remove the elements that match the predicate.
auto values() const
Definition MapVector.h:107
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
Definition MapVector.h:129
ValueT & operator[](const KeyT &Key)
Definition MapVector.h:100
const std::pair< KeyT, ValueT > & front() const
Definition MapVector.h:82
std::pair< KeyT, ValueT > & back()
Definition MapVector.h:85
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
Definition MapVector.h:141
const_reverse_iterator rend() const
Definition MapVector.h:77
ValueT & at(const KeyT &Key)
at - Return the entry for the specified key, or abort if no such entry exists.
Definition MapVector.h:176
const_iterator find(const KeyT &Key) const
Definition MapVector.h:165
const ValueT & at(const KeyT &Key) const
at - Return the entry for the specified key, or abort if no such entry exists.
Definition MapVector.h:184
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition MapVector.h:126
typename VectorType::size_type size_type
Definition MapVector.h:42
size_type size() const
Definition MapVector.h:58
VectorType::iterator erase(typename VectorType::iterator Iterator)
Remove the element given by Iterator.
Definition MapVector.h:210
size_type count(const KeyT &Key) const
Definition MapVector.h:152
const_reverse_iterator rbegin() const
Definition MapVector.h:73
reverse_iterator rbegin()
Definition MapVector.h:72
std::pair< KeyT, ValueT > & front()
Definition MapVector.h:81
typename VectorType::value_type value_type
Definition MapVector.h:41
typename VectorType::const_reverse_iterator const_reverse_iterator
Definition MapVector.h:47
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Base class of all SIMD vector types.
This is an optimization pass for GlobalISel generic memory operations.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
Definition STLExtras.h:1398
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1783
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition STLExtras.h:1408
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1771
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:876
#define N
A MapVector that performs no allocations if smaller than a certain size.
Definition MapVector.h:334