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