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