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