LLVM 22.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"
22#include <cassert>
23#include <cstddef>
24#include <iterator>
25#include <type_traits>
26#include <utility>
27
28namespace llvm {
29
30/// This class implements a map that also provides access to all stored values
31/// in a deterministic order. The values are kept in a SmallVector<*, 0> and the
32/// mapping is done with DenseMap from Keys to indexes in that vector.
33template <typename KeyT, typename ValueT,
34 typename MapType = DenseMap<KeyT, unsigned>,
36class MapVector {
37public:
38 using key_type = KeyT;
39 using value_type = typename VectorType::value_type;
40 using size_type = typename VectorType::size_type;
41
42 using iterator = typename VectorType::iterator;
43 using const_iterator = typename VectorType::const_iterator;
44 using reverse_iterator = typename VectorType::reverse_iterator;
45 using const_reverse_iterator = typename VectorType::const_reverse_iterator;
46
47 /// Clear the MapVector and return the underlying vector.
48 [[nodiscard]] VectorType takeVector() {
49 Map.clear();
50 return std::move(Vector);
51 }
52
53 /// Returns an array reference of the underlying vector.
54 [[nodiscard]] ArrayRef<value_type> getArrayRef() const { return Vector; }
55
56 [[nodiscard]] size_type size() const { return Vector.size(); }
57
58 /// Grow the MapVector so that it can contain at least \p NumEntries items
59 /// before resizing again.
60 void reserve(size_type NumEntries) {
61 Map.reserve(NumEntries);
62 Vector.reserve(NumEntries);
63 }
64
65 [[nodiscard]] iterator begin() { return Vector.begin(); }
66 [[nodiscard]] const_iterator begin() const { return Vector.begin(); }
67 [[nodiscard]] iterator end() { return Vector.end(); }
68 [[nodiscard]] const_iterator end() const { return Vector.end(); }
69
70 [[nodiscard]] reverse_iterator rbegin() { return Vector.rbegin(); }
71 [[nodiscard]] const_reverse_iterator rbegin() const {
72 return Vector.rbegin();
73 }
74 [[nodiscard]] reverse_iterator rend() { return Vector.rend(); }
75 [[nodiscard]] const_reverse_iterator rend() const { return Vector.rend(); }
76
77 [[nodiscard]] bool empty() const { return Vector.empty(); }
78
79 [[nodiscard]] std::pair<KeyT, ValueT> &front() { return Vector.front(); }
80 [[nodiscard]] const std::pair<KeyT, ValueT> &front() const {
81 return Vector.front();
82 }
83 [[nodiscard]] std::pair<KeyT, ValueT> &back() { return Vector.back(); }
84 [[nodiscard]] const std::pair<KeyT, ValueT> &back() const {
85 return Vector.back();
86 }
87
88 void clear() {
89 Map.clear();
90 Vector.clear();
91 }
92
94 std::swap(Map, RHS.Map);
95 std::swap(Vector, RHS.Vector);
96 }
97
98 ValueT &operator[](const KeyT &Key) {
99 return try_emplace_impl(Key).first->second;
100 }
101
102 // Returns a copy of the value. Only allowed if ValueT is copyable.
103 [[nodiscard]] ValueT lookup(const KeyT &Key) const {
104 static_assert(std::is_copy_constructible_v<ValueT>,
105 "Cannot call lookup() if ValueT is not copyable.");
106 typename MapType::const_iterator Pos = Map.find(Key);
107 return Pos == Map.end()? ValueT() : Vector[Pos->second].second;
108 }
109
110 template <typename... Ts>
111 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
112 return try_emplace_impl(Key, std::forward<Ts>(Args)...);
113 }
114 template <typename... Ts>
115 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
116 return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
117 }
118
119 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
120 return try_emplace_impl(KV.first, KV.second);
121 }
122 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
123 return try_emplace_impl(std::move(KV.first), std::move(KV.second));
124 }
125
126 template <typename V>
127 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
128 auto Ret = try_emplace(Key, std::forward<V>(Val));
129 if (!Ret.second)
130 Ret.first->second = std::forward<V>(Val);
131 return Ret;
132 }
133 template <typename V>
134 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
135 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
136 if (!Ret.second)
137 Ret.first->second = std::forward<V>(Val);
138 return Ret;
139 }
140
141 [[nodiscard]] bool contains(const KeyT &Key) const {
142 return Map.find(Key) != Map.end();
143 }
144
145 [[nodiscard]] size_type count(const KeyT &Key) const {
146 return contains(Key) ? 1 : 0;
147 }
148
149 [[nodiscard]] iterator find(const KeyT &Key) {
150 typename MapType::const_iterator Pos = Map.find(Key);
151 return Pos == Map.end()? Vector.end() :
152 (Vector.begin() + Pos->second);
153 }
154
155 [[nodiscard]] const_iterator find(const KeyT &Key) const {
156 typename MapType::const_iterator Pos = Map.find(Key);
157 return Pos == Map.end()? Vector.end() :
158 (Vector.begin() + Pos->second);
159 }
160
161 /// Remove the last element from the vector.
162 void pop_back() {
163 typename MapType::iterator Pos = Map.find(Vector.back().first);
164 Map.erase(Pos);
165 Vector.pop_back();
166 }
167
168 /// Remove the element given by Iterator.
169 ///
170 /// Returns an iterator to the element following the one which was removed,
171 /// which may be end().
172 ///
173 /// \note This is a deceivingly expensive operation (linear time). It's
174 /// usually better to use \a remove_if() if possible.
175 typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
176 Map.erase(Iterator->first);
177 auto Next = Vector.erase(Iterator);
178 if (Next == Vector.end())
179 return Next;
180
181 // Update indices in the map.
182 size_t Index = Next - Vector.begin();
183 for (auto &I : Map) {
184 assert(I.second != Index && "Index was already erased!");
185 if (I.second > Index)
186 --I.second;
187 }
188 return Next;
189 }
190
191 /// Remove all elements with the key value Key.
192 ///
193 /// Returns the number of elements removed.
195 auto Iterator = find(Key);
196 if (Iterator == end())
197 return 0;
198 erase(Iterator);
199 return 1;
200 }
201
202 /// Remove the elements that match the predicate.
203 ///
204 /// Erase all elements that match \c Pred in a single pass. Takes linear
205 /// time.
206 template <class Predicate> void remove_if(Predicate Pred);
207
208private:
209 MapType Map;
210 VectorType Vector;
211
212 static_assert(
213 std::is_integral_v<typename MapType::mapped_type>,
214 "The mapped_type of the specified Map must be an integral type");
215
216 template <typename KeyArgT, typename... Ts>
217 std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
218 auto [It, Inserted] = Map.try_emplace(Key);
219 if (Inserted) {
220 It->second = Vector.size();
221 Vector.emplace_back(std::piecewise_construct,
222 std::forward_as_tuple(std::forward<KeyArgT>(Key)),
223 std::forward_as_tuple(std::forward<Ts>(Args)...));
224 return {std::prev(end()), true};
225 }
226 return {begin() + It->second, false};
227 }
228};
229
230template <typename KeyT, typename ValueT, typename MapType, typename VectorType>
231template <class Function>
233 auto O = Vector.begin();
234 for (auto I = O, E = Vector.end(); I != E; ++I) {
235 if (Pred(*I)) {
236 // Erase from the map.
237 Map.erase(I->first);
238 continue;
239 }
240
241 if (I != O) {
242 // Move the value and update the index in the map.
243 *O = std::move(*I);
244 Map[O->first] = O - Vector.begin();
245 }
246 ++O;
247 }
248 // Erase trailing entries in the vector.
249 Vector.erase(O, Vector.end());
250}
251
252/// A MapVector that performs no allocations if smaller than a certain
253/// size.
254template <typename KeyT, typename ValueT, unsigned N>
256 : MapVector<KeyT, ValueT, SmallDenseMap<KeyT, unsigned, N>,
257 SmallVector<std::pair<KeyT, ValueT>, N>> {
258};
259
260} // end namespace llvm
261
262#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:58
This file defines the SmallVector class.
Value * RHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:36
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition MapVector.h:115
size_type count(const KeyT &Key) const
Definition MapVector.h:145
typename VectorType::iterator iterator
Definition MapVector.h:42
iterator end()
Definition MapVector.h:67
void pop_back()
Remove the last element from the vector.
Definition MapVector.h:162
const_reverse_iterator rbegin() const
Definition MapVector.h:71
void swap(MapVector &RHS)
Definition MapVector.h:93
reverse_iterator rend()
Definition MapVector.h:74
ValueT & operator[](const KeyT &Key)
Definition MapVector.h:98
const_iterator end() const
Definition MapVector.h:68
VectorType::iterator erase(typename VectorType::iterator Iterator)
Remove the element given by Iterator.
Definition MapVector.h:175
std::pair< iterator, bool > insert_or_assign(KeyT &&Key, V &&Val)
Definition MapVector.h:134
VectorType takeVector()
Clear the MapVector and return the underlying vector.
Definition MapVector.h:48
typename VectorType::size_type size_type
Definition MapVector.h:40
const std::pair< KeyT, ValueT > & back() const
Definition MapVector.h:84
const std::pair< KeyT, ValueT > & front() const
Definition MapVector.h:80
typename VectorType::const_reverse_iterator const_reverse_iterator
Definition MapVector.h:45
typename VectorType::value_type value_type
Definition MapVector.h:39
iterator find(const KeyT &Key)
Definition MapVector.h:149
void remove_if(Predicate Pred)
Remove the elements that match the predicate.
bool contains(const KeyT &Key) const
Definition MapVector.h:141
bool empty() const
Definition MapVector.h:77
const_iterator begin() const
Definition MapVector.h:66
iterator begin()
Definition MapVector.h:65
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition MapVector.h:127
const_iterator find(const KeyT &Key) const
Definition MapVector.h:155
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition MapVector.h:111
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition MapVector.h:119
ArrayRef< value_type > getArrayRef() const
Returns an array reference of the underlying vector.
Definition MapVector.h:54
ValueT lookup(const KeyT &Key) const
Definition MapVector.h:103
void reserve(size_type NumEntries)
Grow the MapVector so that it can contain at least NumEntries items before resizing again.
Definition MapVector.h:60
typename VectorType::reverse_iterator reverse_iterator
Definition MapVector.h:44
size_type size() const
Definition MapVector.h:56
size_type erase(const KeyT &Key)
Remove all elements with the key value Key.
Definition MapVector.h:194
typename VectorType::const_iterator const_iterator
Definition MapVector.h:43
std::pair< KeyT, ValueT > & front()
Definition MapVector.h:79
std::pair< iterator, bool > insert(std::pair< KeyT, ValueT > &&KV)
Definition MapVector.h:122
const_reverse_iterator rend() const
Definition MapVector.h:75
reverse_iterator rbegin()
Definition MapVector.h:70
std::pair< KeyT, ValueT > & back()
Definition MapVector.h:83
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.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872
A MapVector that performs no allocations if smaller than a certain size.
Definition MapVector.h:257