LLVM 22.0.0git
SetVector.h
Go to the documentation of this file.
1//===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- 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 set that has insertion order iteration
11/// characteristics. This is useful for keeping a set of things that need to be
12/// visited later but in a deterministic order (insertion order). The interface
13/// is purposefully minimal.
14///
15/// This file defines SetVector and SmallSetVector, which performs no
16/// allocations if the SetVector has less than a certain number of elements.
17///
18//===----------------------------------------------------------------------===//
19
20#ifndef LLVM_ADT_SETVECTOR_H
21#define LLVM_ADT_SETVECTOR_H
22
23#include "llvm/ADT/ADL.h"
24#include "llvm/ADT/ArrayRef.h"
25#include "llvm/ADT/DenseSet.h"
26#include "llvm/ADT/STLExtras.h"
30#include <cassert>
31#include <iterator>
32
33namespace llvm {
34
35/// A vector that has set insertion semantics.
36///
37/// This adapter class provides a way to keep a set of things that also has the
38/// property of a deterministic iteration order. The order of iteration is the
39/// order of insertion.
40///
41/// The key and value types are derived from the Set and Vector types
42/// respectively. This allows the vector-type operations and set-type operations
43/// to have different types. In particular, this is useful when storing pointers
44/// as "Foo *" values but looking them up as "const Foo *" keys.
45///
46/// No constraint is placed on the key and value types, although it is assumed
47/// that value_type can be converted into key_type for insertion. Users must be
48/// aware of any loss of information in this conversion. For example, setting
49/// value_type to float and key_type to int can produce very surprising results,
50/// but it is not explicitly disallowed.
51///
52/// The parameter N specifies the "small" size of the container, which is the
53/// number of elements upto which a linear scan over the Vector will be used
54/// when searching for elements instead of checking Set, due to it being better
55/// for performance. A value of 0 means that this mode of operation is not used,
56/// and is the default value.
57template <typename T, typename Vector = SmallVector<T, 0>,
58 typename Set = DenseSet<T>, unsigned N = 0>
59class SetVector {
60 // Much like in SmallPtrSet, this value should not be too high to prevent
61 // excessively long linear scans from occuring.
62 static_assert(N <= 32, "Small size should be less than or equal to 32!");
63
64public:
65 using value_type = typename Vector::value_type;
66 using key_type = typename Set::key_type;
68 using const_reference = const value_type &;
69 using set_type = Set;
71 using iterator = typename vector_type::const_iterator;
72 using const_iterator = typename vector_type::const_iterator;
73 using reverse_iterator = typename vector_type::const_reverse_iterator;
74 using const_reverse_iterator = typename vector_type::const_reverse_iterator;
75 using size_type = typename vector_type::size_type;
76
77 /// Construct an empty SetVector
78 SetVector() = default;
79
80 /// Initialize a SetVector with a range of elements
81 template<typename It>
82 SetVector(It Start, It End) {
83 insert(Start, End);
84 }
85
86 template <typename Range>
88 : SetVector(adl_begin(R), adl_end(R)) {}
89
90 ArrayRef<value_type> getArrayRef() const { return vector_; }
91
92 /// Clear the SetVector and return the underlying vector.
94 set_.clear();
95 return std::move(vector_);
96 }
97
98 /// Determine if the SetVector is empty or not.
99 bool empty() const {
100 return vector_.empty();
101 }
102
103 /// Determine the number of elements in the SetVector.
104 size_type size() const {
105 return vector_.size();
106 }
107
108 /// Get an iterator to the beginning of the SetVector.
110 return vector_.begin();
111 }
112
113 /// Get a const_iterator to the beginning of the SetVector.
115 return vector_.begin();
116 }
117
118 /// Get an iterator to the end of the SetVector.
120 return vector_.end();
121 }
122
123 /// Get a const_iterator to the end of the SetVector.
125 return vector_.end();
126 }
127
128 /// Get an reverse_iterator to the end of the SetVector.
130 return vector_.rbegin();
131 }
132
133 /// Get a const_reverse_iterator to the end of the SetVector.
135 return vector_.rbegin();
136 }
137
138 /// Get a reverse_iterator to the beginning of the SetVector.
140 return vector_.rend();
141 }
142
143 /// Get a const_reverse_iterator to the beginning of the SetVector.
145 return vector_.rend();
146 }
147
148 /// Return the first element of the SetVector.
149 const value_type &front() const {
150 assert(!empty() && "Cannot call front() on empty SetVector!");
151 return vector_.front();
152 }
153
154 /// Return the last element of the SetVector.
155 const value_type &back() const {
156 assert(!empty() && "Cannot call back() on empty SetVector!");
157 return vector_.back();
158 }
159
160 /// Index into the SetVector.
162 assert(n < vector_.size() && "SetVector access out of range!");
163 return vector_[n];
164 }
165
166 /// Insert a new element into the SetVector.
167 /// \returns true if the element was inserted into the SetVector.
168 bool insert(const value_type &X) {
169 if constexpr (canBeSmall())
170 if (isSmall()) {
171 if (!llvm::is_contained(vector_, X)) {
172 vector_.push_back(X);
173 if (vector_.size() > N)
174 makeBig();
175 return true;
176 }
177 return false;
178 }
179
180 bool result = set_.insert(X).second;
181 if (result)
182 vector_.push_back(X);
183 return result;
184 }
185
186 /// Insert a range of elements into the SetVector.
187 template<typename It>
188 void insert(It Start, It End) {
189 for (; Start != End; ++Start)
190 insert(*Start);
191 }
192
193 template <typename Range> void insert_range(Range &&R) {
194 insert(adl_begin(R), adl_end(R));
195 }
196
197 /// Remove an item from the set vector.
198 bool remove(const value_type& X) {
199 if constexpr (canBeSmall())
200 if (isSmall()) {
201 typename vector_type::iterator I = find(vector_, X);
202 if (I != vector_.end()) {
203 vector_.erase(I);
204 return true;
205 }
206 return false;
207 }
208
209 if (set_.erase(X)) {
210 typename vector_type::iterator I = find(vector_, X);
211 assert(I != vector_.end() && "Corrupted SetVector instances!");
212 vector_.erase(I);
213 return true;
214 }
215 return false;
216 }
217
218 /// Erase a single element from the set vector.
219 /// \returns an iterator pointing to the next element that followed the
220 /// element erased. This is the end of the SetVector if the last element is
221 /// erased.
223 if constexpr (canBeSmall())
224 if (isSmall())
225 return vector_.erase(I);
226
227 const key_type &V = *I;
228 assert(set_.count(V) && "Corrupted SetVector instances!");
229 set_.erase(V);
230 return vector_.erase(I);
231 }
232
233 /// Remove items from the set vector based on a predicate function.
234 ///
235 /// This is intended to be equivalent to the following code, if we could
236 /// write it:
237 ///
238 /// \code
239 /// V.erase(remove_if(V, P), V.end());
240 /// \endcode
241 ///
242 /// However, SetVector doesn't expose non-const iterators, making any
243 /// algorithm like remove_if impossible to use.
244 ///
245 /// \returns true if any element is removed.
246 template <typename UnaryPredicate>
247 bool remove_if(UnaryPredicate P) {
248 typename vector_type::iterator I = [this, P] {
249 if constexpr (canBeSmall())
250 if (isSmall())
251 return llvm::remove_if(vector_, P);
252
253 return llvm::remove_if(vector_, [&](const value_type &V) {
254 if (P(V)) {
255 set_.erase(V);
256 return true;
257 }
258 return false;
259 });
260 }();
261
262 if (I == vector_.end())
263 return false;
264 vector_.erase(I, vector_.end());
265 return true;
266 }
267
268 /// Check if the SetVector contains the given key.
269 [[nodiscard]] bool contains(const key_type &key) const {
270 if constexpr (canBeSmall())
271 if (isSmall())
272 return is_contained(vector_, key);
273
274 return set_.find(key) != set_.end();
275 }
276
277 /// Count the number of elements of a given key in the SetVector.
278 /// \returns 0 if the element is not in the SetVector, 1 if it is.
279 [[nodiscard]] size_type count(const key_type &key) const {
280 return contains(key) ? 1 : 0;
281 }
282
283 /// Completely clear the SetVector
284 void clear() {
285 set_.clear();
286 vector_.clear();
287 }
288
289 /// Remove the last element of the SetVector.
290 void pop_back() {
291 assert(!empty() && "Cannot remove an element from an empty SetVector!");
292 set_.erase(back());
293 vector_.pop_back();
294 }
295
296 [[nodiscard]] value_type pop_back_val() {
297 value_type Ret = back();
298 pop_back();
299 return Ret;
300 }
301
302 bool operator==(const SetVector &that) const {
303 return vector_ == that.vector_;
304 }
305
306 bool operator!=(const SetVector &that) const {
307 return vector_ != that.vector_;
308 }
309
310 /// Compute This := This u S, return whether 'This' changed.
311 /// TODO: We should be able to use set_union from SetOperations.h, but
312 /// SetVector interface is inconsistent with DenseSet.
313 template <class STy>
314 bool set_union(const STy &S) {
315 bool Changed = false;
316
317 for (const auto &Elem : S)
318 if (insert(Elem))
319 Changed = true;
320
321 return Changed;
322 }
323
324 /// Compute This := This - B
325 /// TODO: We should be able to use set_subtract from SetOperations.h, but
326 /// SetVector interface is inconsistent with DenseSet.
327 template <class STy>
328 void set_subtract(const STy &S) {
329 for (const auto &Elem : S)
330 remove(Elem);
331 }
332
334 set_.swap(RHS.set_);
335 vector_.swap(RHS.vector_);
336 }
337
338private:
339 [[nodiscard]] static constexpr bool canBeSmall() { return N != 0; }
340
341 [[nodiscard]] bool isSmall() const { return set_.empty(); }
342
343 void makeBig() {
344 if constexpr (canBeSmall())
345 for (const auto &entry : vector_)
346 set_.insert(entry);
347 }
348
349 set_type set_; ///< The set.
350 vector_type vector_; ///< The vector.
351};
352
353/// A SetVector that performs no allocations if smaller than
354/// a certain size.
355template <typename T, unsigned N>
356class SmallSetVector : public SetVector<T, SmallVector<T, N>, DenseSet<T>, N> {
357public:
359};
360
361} // end namespace llvm
362
363namespace std {
364
365/// Implement std::swap in terms of SetVector swap.
366template <typename T, typename V, typename S, unsigned N>
369 LHS.swap(RHS);
370}
371
372/// Implement std::swap in terms of SmallSetVector swap.
373template<typename T, unsigned N>
374inline void
376 LHS.swap(RHS);
377}
378
379} // end namespace std
380
381#endif // LLVM_ADT_SETVECTOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the DenseSet and SmallDenseSet classes.
bool End
Definition: ELF_riscv.cpp:480
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define I(x, y, z)
Definition: MD5.cpp:58
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This file contains library features backported from future STL versions.
This file defines the SmallVector class.
Value * RHS
Value * LHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Implements a dense probed hash-table based set.
Definition: DenseSet.h:263
A vector that has set insertion semantics.
Definition: SetVector.h:59
const_reverse_iterator rend() const
Get a const_reverse_iterator to the beginning of the SetVector.
Definition: SetVector.h:144
ArrayRef< value_type > getArrayRef() const
Definition: SetVector.h:90
typename vector_type::const_reverse_iterator reverse_iterator
Definition: SetVector.h:73
iterator erase(const_iterator I)
Erase a single element from the set vector.
Definition: SetVector.h:222
bool remove(const value_type &X)
Remove an item from the set vector.
Definition: SetVector.h:198
bool remove_if(UnaryPredicate P)
Remove items from the set vector based on a predicate function.
Definition: SetVector.h:247
size_type size() const
Determine the number of elements in the SetVector.
Definition: SetVector.h:104
const value_type & front() const
Return the first element of the SetVector.
Definition: SetVector.h:149
bool operator==(const SetVector &that) const
Definition: SetVector.h:302
value_type & reference
Definition: SetVector.h:67
typename vector_type::const_reverse_iterator const_reverse_iterator
Definition: SetVector.h:74
Vector vector_type
Definition: SetVector.h:70
const value_type & back() const
Return the last element of the SetVector.
Definition: SetVector.h:155
void insert_range(Range &&R)
Definition: SetVector.h:193
bool set_union(const STy &S)
Compute This := This u S, return whether 'This' changed.
Definition: SetVector.h:314
typename Vector::value_type value_type
Definition: SetVector.h:65
const_reverse_iterator rbegin() const
Get a const_reverse_iterator to the end of the SetVector.
Definition: SetVector.h:134
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition: SetVector.h:93
typename vector_type::const_iterator iterator
Definition: SetVector.h:71
iterator end()
Get an iterator to the end of the SetVector.
Definition: SetVector.h:119
SetVector()=default
Construct an empty SetVector.
SetVector(llvm::from_range_t, Range &&R)
Definition: SetVector.h:87
reverse_iterator rbegin()
Get an reverse_iterator to the end of the SetVector.
Definition: SetVector.h:129
typename vector_type::const_iterator const_iterator
Definition: SetVector.h:72
const_iterator end() const
Get a const_iterator to the end of the SetVector.
Definition: SetVector.h:124
void clear()
Completely clear the SetVector.
Definition: SetVector.h:284
bool operator!=(const SetVector &that) const
Definition: SetVector.h:306
reverse_iterator rend()
Get a reverse_iterator to the beginning of the SetVector.
Definition: SetVector.h:139
typename vector_type::size_type size_type
Definition: SetVector.h:75
const_iterator begin() const
Get a const_iterator to the beginning of the SetVector.
Definition: SetVector.h:114
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
Definition: SetVector.h:279
bool empty() const
Determine if the SetVector is empty or not.
Definition: SetVector.h:99
void insert(It Start, It End)
Insert a range of elements into the SetVector.
Definition: SetVector.h:188
const value_type & const_reference
Definition: SetVector.h:68
iterator begin()
Get an iterator to the beginning of the SetVector.
Definition: SetVector.h:109
SetVector(It Start, It End)
Initialize a SetVector with a range of elements.
Definition: SetVector.h:82
void swap(SetVector< T, Vector, Set, N > &RHS)
Definition: SetVector.h:333
typename Set::key_type key_type
Definition: SetVector.h:66
void set_subtract(const STy &S)
Compute This := This - B TODO: We should be able to use set_subtract from SetOperations....
Definition: SetVector.h:328
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:168
void pop_back()
Remove the last element of the SetVector.
Definition: SetVector.h:290
value_type pop_back_val()
Definition: SetVector.h:296
const_reference operator[](size_type n) const
Index into the SetVector.
Definition: SetVector.h:161
bool contains(const key_type &key) const
Check if the SetVector contains the given key.
Definition: SetVector.h:269
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:356
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1770
constexpr auto adl_begin(RangeT &&range) -> decltype(adl_detail::begin_impl(std::forward< RangeT >(range)))
Returns the begin iterator to range using std::begin and function found through Argument-Dependent Lo...
Definition: ADL.h:78
constexpr auto adl_end(RangeT &&range) -> decltype(adl_detail::end_impl(std::forward< RangeT >(range)))
Returns the end iterator to range using std::end and functions found through Argument-Dependent Looku...
Definition: ADL.h:86
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:1789
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1916
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:858
#define N