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;
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>
89
90 [[nodiscard]] ArrayRef<value_type> getArrayRef() const { return vector_; }
91
92 /// Clear the SetVector and return the underlying vector.
93 [[nodiscard]] Vector takeVector() {
94 set_.clear();
95 return std::move(vector_);
96 }
97
98 /// Determine if the SetVector is empty or not.
99 [[nodiscard]] bool empty() const { return vector_.empty(); }
100
101 /// Determine the number of elements in the SetVector.
102 [[nodiscard]] size_type size() const { return vector_.size(); }
103
104 /// Get an iterator to the beginning of the SetVector.
105 [[nodiscard]] iterator begin() { return vector_.begin(); }
106
107 /// Get a const_iterator to the beginning of the SetVector.
108 [[nodiscard]] const_iterator begin() const { return vector_.begin(); }
109
110 /// Get an iterator to the end of the SetVector.
111 [[nodiscard]] iterator end() { return vector_.end(); }
112
113 /// Get a const_iterator to the end of the SetVector.
114 [[nodiscard]] const_iterator end() const { return vector_.end(); }
115
116 /// Get an reverse_iterator to the end of the SetVector.
117 [[nodiscard]] reverse_iterator rbegin() { return vector_.rbegin(); }
118
119 /// Get a const_reverse_iterator to the end of the SetVector.
120 [[nodiscard]] const_reverse_iterator rbegin() const {
121 return vector_.rbegin();
122 }
123
124 /// Get a reverse_iterator to the beginning of the SetVector.
125 [[nodiscard]] reverse_iterator rend() { return vector_.rend(); }
126
127 /// Get a const_reverse_iterator to the beginning of the SetVector.
128 [[nodiscard]] const_reverse_iterator rend() const { return vector_.rend(); }
129
130 /// Return the first element of the SetVector.
131 [[nodiscard]] const value_type &front() const {
132 assert(!empty() && "Cannot call front() on empty SetVector!");
133 return vector_.front();
134 }
135
136 /// Return the last element of the SetVector.
137 [[nodiscard]] const value_type &back() const {
138 assert(!empty() && "Cannot call back() on empty SetVector!");
139 return vector_.back();
140 }
141
142 /// Index into the SetVector.
144 assert(n < vector_.size() && "SetVector access out of range!");
145 return vector_[n];
146 }
147
148 /// Insert a new element into the SetVector.
149 /// \returns true if the element was inserted into the SetVector.
150 bool insert(const value_type &X) {
151 if constexpr (canBeSmall())
152 if (isSmall()) {
153 if (!llvm::is_contained(vector_, X)) {
154 vector_.push_back(X);
155 if (vector_.size() > N)
156 makeBig();
157 return true;
158 }
159 return false;
160 }
161
162 bool result = set_.insert(X).second;
163 if (result)
164 vector_.push_back(X);
165 return result;
166 }
167
168 /// Insert a range of elements into the SetVector.
169 template<typename It>
170 void insert(It Start, It End) {
171 for (; Start != End; ++Start)
172 insert(*Start);
173 }
174
175 template <typename Range> void insert_range(Range &&R) {
176 insert(adl_begin(R), adl_end(R));
177 }
178
179 /// Remove an item from the set vector.
180 bool remove(const value_type& X) {
181 if constexpr (canBeSmall())
182 if (isSmall()) {
183 typename vector_type::iterator I = find(vector_, X);
184 if (I != vector_.end()) {
185 vector_.erase(I);
186 return true;
187 }
188 return false;
189 }
190
191 if (set_.erase(X)) {
192 typename vector_type::iterator I = find(vector_, X);
193 assert(I != vector_.end() && "Corrupted SetVector instances!");
194 vector_.erase(I);
195 return true;
196 }
197 return false;
198 }
199
200 /// Erase a single element from the set vector.
201 /// \returns an iterator pointing to the next element that followed the
202 /// element erased. This is the end of the SetVector if the last element is
203 /// erased.
205 if constexpr (canBeSmall())
206 if (isSmall())
207 return vector_.erase(I);
208
209 const key_type &V = *I;
210 assert(set_.count(V) && "Corrupted SetVector instances!");
211 set_.erase(V);
212 return vector_.erase(I);
213 }
214
215 /// Remove items from the set vector based on a predicate function.
216 ///
217 /// This is intended to be equivalent to the following code, if we could
218 /// write it:
219 ///
220 /// \code
221 /// V.erase(remove_if(V, P), V.end());
222 /// \endcode
223 ///
224 /// However, SetVector doesn't expose non-const iterators, making any
225 /// algorithm like remove_if impossible to use.
226 ///
227 /// \returns true if any element is removed.
228 template <typename UnaryPredicate>
229 bool remove_if(UnaryPredicate P) {
230 typename vector_type::iterator I = [this, P] {
231 if constexpr (canBeSmall())
232 if (isSmall())
233 return llvm::remove_if(vector_, P);
234
235 return llvm::remove_if(vector_, [&](const value_type &V) {
236 if (P(V)) {
237 set_.erase(V);
238 return true;
239 }
240 return false;
241 });
242 }();
243
244 if (I == vector_.end())
245 return false;
246 vector_.erase(I, vector_.end());
247 return true;
248 }
249
250 /// Check if the SetVector contains the given key.
251 [[nodiscard]] bool contains(const key_type &key) const {
252 if constexpr (canBeSmall())
253 if (isSmall())
254 return is_contained(vector_, key);
255
256 return set_.find(key) != set_.end();
257 }
258
259 /// Count the number of elements of a given key in the SetVector.
260 /// \returns 0 if the element is not in the SetVector, 1 if it is.
261 [[nodiscard]] size_type count(const key_type &key) const {
262 return contains(key) ? 1 : 0;
263 }
264
265 /// Completely clear the SetVector
266 void clear() {
267 set_.clear();
268 vector_.clear();
269 }
270
271 /// Remove the last element of the SetVector.
272 void pop_back() {
273 assert(!empty() && "Cannot remove an element from an empty SetVector!");
274 set_.erase(back());
275 vector_.pop_back();
276 }
277
278 [[nodiscard]] value_type pop_back_val() {
279 value_type Ret = back();
280 pop_back();
281 return Ret;
282 }
283
284 [[nodiscard]] bool operator==(const SetVector &that) const {
285 return vector_ == that.vector_;
286 }
287
288 [[nodiscard]] bool operator!=(const SetVector &that) const {
289 return vector_ != that.vector_;
290 }
291
292 /// Compute This := This u S, return whether 'This' changed.
293 /// TODO: We should be able to use set_union from SetOperations.h, but
294 /// SetVector interface is inconsistent with DenseSet.
295 template <class STy>
296 bool set_union(const STy &S) {
297 bool Changed = false;
298
299 for (const auto &Elem : S)
300 if (insert(Elem))
301 Changed = true;
302
303 return Changed;
304 }
305
306 /// Compute This := This - B
307 /// TODO: We should be able to use set_subtract from SetOperations.h, but
308 /// SetVector interface is inconsistent with DenseSet.
309 template <class STy>
310 void set_subtract(const STy &S) {
311 for (const auto &Elem : S)
312 remove(Elem);
313 }
314
316 set_.swap(RHS.set_);
317 vector_.swap(RHS.vector_);
318 }
319
320private:
321 [[nodiscard]] static constexpr bool canBeSmall() { return N != 0; }
322
323 [[nodiscard]] bool isSmall() const { return set_.empty(); }
324
325 void makeBig() {
326 if constexpr (canBeSmall())
327 for (const auto &entry : vector_)
328 set_.insert(entry);
329 }
330
331 set_type set_; ///< The set.
332 vector_type vector_; ///< The vector.
333};
334
335/// A SetVector that performs no allocations if smaller than
336/// a certain size.
337template <typename T, unsigned N>
338class SmallSetVector : public SetVector<T, SmallVector<T, N>, DenseSet<T>, N> {
339public:
341};
342
343} // end namespace llvm
344
345namespace std {
346
347/// Implement std::swap in terms of SetVector swap.
348template <typename T, typename V, typename S, unsigned N>
353
354/// Implement std::swap in terms of SmallSetVector swap.
355template<typename T, unsigned N>
356inline void
360
361} // end namespace std
362
363#endif // LLVM_ADT_SETVECTOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the DenseSet and SmallDenseSet classes.
#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.
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton 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:279
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:128
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:204
bool remove(const value_type &X)
Remove an item from the set vector.
Definition SetVector.h:180
bool remove_if(UnaryPredicate P)
Remove items from the set vector based on a predicate function.
Definition SetVector.h:229
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:102
const value_type & front() const
Return the first element of the SetVector.
Definition SetVector.h:131
bool operator==(const SetVector &that) const
Definition SetVector.h:284
typename vector_type::const_reverse_iterator const_reverse_iterator
Definition SetVector.h:74
SmallVector< EdgeType *, 0 > vector_type
Definition SetVector.h:70
const value_type & back() const
Return the last element of the SetVector.
Definition SetVector.h:137
void insert_range(Range &&R)
Definition SetVector.h:175
bool set_union(const STy &S)
Compute This := This u S, return whether 'This' changed.
Definition SetVector.h:296
typename SmallVector< EdgeType *, 0 >::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:120
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition SetVector.h:93
typename vector_type::const_iterator iterator
Definition SetVector.h:71
DenseSet< EdgeType * > set_type
Definition SetVector.h:69
iterator end()
Get an iterator to the end of the SetVector.
Definition SetVector.h:111
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:117
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:114
void clear()
Completely clear the SetVector.
Definition SetVector.h:266
bool operator!=(const SetVector &that) const
Definition SetVector.h:288
reverse_iterator rend()
Get a reverse_iterator to the beginning of the SetVector.
Definition SetVector.h:125
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:108
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
Definition SetVector.h:261
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:170
const value_type & const_reference
Definition SetVector.h:68
iterator begin()
Get an iterator to the beginning of the SetVector.
Definition SetVector.h:105
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:315
typename DenseSet< EdgeType * >::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:310
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:150
void pop_back()
Remove the last element of the SetVector.
Definition SetVector.h:272
value_type pop_back_val()
Definition SetVector.h:278
const_reference operator[](size_type n) const
Index into the SetVector.
Definition SetVector.h:143
bool contains(const key_type &key) const
Check if the SetVector contains the given key.
Definition SetVector.h:251
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:338
std::reverse_iterator< const_iterator > const_reverse_iterator
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Changed
This is an optimization pass for GlobalISel generic memory operations.
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:1731
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:1750
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1877
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872
#define N