LLVM 22.0.0git
DenseSet.h
Go to the documentation of this file.
1//===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- 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 defines the DenseSet and SmallDenseSet classes.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ADT_DENSESET_H
15#define LLVM_ADT_DENSESET_H
16
17#include "llvm/ADT/ADL.h"
18#include "llvm/ADT/DenseMap.h"
23#include <cstddef>
24#include <initializer_list>
25#include <iterator>
26#include <utility>
27
28namespace llvm {
29
30namespace detail {
31
32struct DenseSetEmpty {};
33
34// Use the empty base class trick so we can create a DenseMap where the buckets
35// contain only a single item.
36template <typename KeyT> class DenseSetPair : public DenseSetEmpty {
37 KeyT key;
38
39public:
40 KeyT &getFirst() { return key; }
41 const KeyT &getFirst() const { return key; }
42 DenseSetEmpty &getSecond() { return *this; }
43 const DenseSetEmpty &getSecond() const { return *this; }
44};
45
46/// Base class for DenseSet and DenseSmallSet.
47///
48/// MapTy should be either
49///
50/// DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
51/// detail::DenseSetPair<ValueT>>
52///
53/// or the equivalent SmallDenseMap type. ValueInfoT must implement the
54/// DenseMapInfo "concept".
55template <typename ValueT, typename MapTy, typename ValueInfoT>
57 static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
58 "DenseMap buckets unexpectedly large!");
59 MapTy TheMap;
60
61 template <typename T>
62 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
63
64public:
68
69 explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
70
71 template <typename InputIt>
72 DenseSetImpl(const InputIt &I, const InputIt &E)
73 : DenseSetImpl(PowerOf2Ceil(std::distance(I, E))) {
74 insert(I, E);
75 }
76
77 DenseSetImpl(std::initializer_list<ValueT> Elems)
78 : DenseSetImpl(PowerOf2Ceil(Elems.size())) {
79 insert(Elems.begin(), Elems.end());
80 }
81
82 template <typename Range>
84 : DenseSetImpl(adl_begin(R), adl_end(R)) {}
85
86 bool empty() const { return TheMap.empty(); }
87 size_type size() const { return TheMap.size(); }
88 size_t getMemorySize() const { return TheMap.getMemorySize(); }
89
90 /// Grow the DenseSet so that it has at least Size buckets. Will not shrink
91 /// the Size of the set.
92 void resize(size_t Size) { TheMap.resize(Size); }
93
94 /// Grow the DenseSet so that it can contain at least \p NumEntries items
95 /// before resizing again.
96 void reserve(size_t Size) { TheMap.reserve(Size); }
97
98 void clear() { TheMap.clear(); }
99
100 bool erase(const ValueT &V) { return TheMap.erase(V); }
101
102 void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
103
104private:
105 template <bool IsConst> class DenseSetIterator {
106 friend class DenseSetImpl;
107
108 using MapIteratorT =
109 std::conditional_t<IsConst, typename MapTy::const_iterator,
110 typename MapTy::iterator>;
111
112 MapIteratorT I;
113
114 public:
115 using difference_type = typename MapIteratorT::difference_type;
116 using iterator_category = std::forward_iterator_tag;
117 using value_type = ValueT;
118 using pointer =
119 std::conditional_t<IsConst, const value_type *, value_type *>;
120 using reference =
121 std::conditional_t<IsConst, const value_type &, value_type &>;
122
123 DenseSetIterator() = default;
124 DenseSetIterator(MapIteratorT I) : I(I) {}
125
126 // Allow conversion from iterator to const_iterator.
127 template <bool C = IsConst, typename = std::enable_if_t<C>>
128 DenseSetIterator(const DenseSetIterator<false> &Other) : I(Other.I) {}
129
130 reference operator*() const { return I->getFirst(); }
131 pointer operator->() const { return &I->getFirst(); }
132
133 DenseSetIterator &operator++() {
134 ++I;
135 return *this;
136 }
137 DenseSetIterator operator++(int) {
138 auto T = *this;
139 ++I;
140 return T;
141 }
142
143 friend bool operator==(const DenseSetIterator &LHS,
144 const DenseSetIterator &RHS) {
145 return LHS.I == RHS.I;
146 }
147 friend bool operator!=(const DenseSetIterator &LHS,
148 const DenseSetIterator &RHS) {
149 return LHS.I != RHS.I;
150 }
151 };
152
153public:
154 using iterator = DenseSetIterator<false>;
155 using const_iterator = DenseSetIterator<true>;
156
157 iterator begin() { return iterator(TheMap.begin()); }
158 iterator end() { return iterator(TheMap.end()); }
159
160 const_iterator begin() const { return const_iterator(TheMap.begin()); }
161 const_iterator end() const { return const_iterator(TheMap.end()); }
162
163 iterator find(const_arg_type_t<ValueT> V) { return iterator(TheMap.find(V)); }
164 const_iterator find(const_arg_type_t<ValueT> V) const {
165 return const_iterator(TheMap.find(V));
166 }
167
168 /// Check if the set contains the given element.
169 [[nodiscard]] bool contains(const_arg_type_t<ValueT> V) const {
170 return TheMap.contains(V);
171 }
172
173 /// Return 1 if the specified key is in the set, 0 otherwise.
174 [[nodiscard]] size_type count(const_arg_type_t<ValueT> V) const {
175 return TheMap.count(V);
176 }
177
178 /// Alternative version of find() which allows a different, and possibly less
179 /// expensive, key type.
180 /// The DenseMapInfo is responsible for supplying methods
181 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
182 /// used.
183 template <class LookupKeyT> iterator find_as(const LookupKeyT &Val) {
184 return iterator(TheMap.find_as(Val));
185 }
186 template <class LookupKeyT>
187 const_iterator find_as(const LookupKeyT &Val) const {
188 return const_iterator(TheMap.find_as(Val));
189 }
190
191 void erase(iterator I) { return TheMap.erase(I.I); }
192 void erase(const_iterator CI) { return TheMap.erase(CI.I); }
193
194 std::pair<iterator, bool> insert(const ValueT &V) {
196 return TheMap.try_emplace(V, Empty);
197 }
198
199 std::pair<iterator, bool> insert(ValueT &&V) {
201 return TheMap.try_emplace(std::move(V), Empty);
202 }
203
204 /// Alternative version of insert that uses a different (and possibly less
205 /// expensive) key type.
206 template <typename LookupKeyT>
207 std::pair<iterator, bool> insert_as(const ValueT &V,
208 const LookupKeyT &LookupKey) {
209 return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey);
210 }
211 template <typename LookupKeyT>
212 std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
213 return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey);
214 }
215
216 // Range insertion of values.
217 template <typename InputIt> void insert(InputIt I, InputIt E) {
218 for (; I != E; ++I)
219 insert(*I);
220 }
221
222 template <typename Range> void insert_range(Range &&R) {
223 insert(adl_begin(R), adl_end(R));
224 }
225};
226
227/// Equality comparison for DenseSet.
228///
229/// Iterates over elements of LHS confirming that each element is also a member
230/// of RHS, and that RHS contains no additional values.
231/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
232/// case is O(N^2) (if every hash collides).
233template <typename ValueT, typename MapTy, typename ValueInfoT>
236 if (LHS.size() != RHS.size())
237 return false;
238
239 for (auto &E : LHS)
240 if (!RHS.count(E))
241 return false;
242
243 return true;
244}
245
246/// Inequality comparison for DenseSet.
247///
248/// Equivalent to !(LHS == RHS). See operator== for performance notes.
249template <typename ValueT, typename MapTy, typename ValueInfoT>
252 return !(LHS == RHS);
253}
254
255} // end namespace detail
256
257/// Implements a dense probed hash-table based set.
258template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
260 ValueT,
261 DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
262 detail::DenseSetPair<ValueT>>,
263 ValueInfoT> {
264 using BaseT =
268 ValueInfoT>;
269
270public:
271 using BaseT::BaseT;
272};
273
274/// Implements a dense probed hash-table based set with some number of buckets
275/// stored inline.
276template <typename ValueT, unsigned InlineBuckets = 4,
277 typename ValueInfoT = DenseMapInfo<ValueT>>
279 : public detail::DenseSetImpl<
280 ValueT,
281 SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
282 ValueInfoT, detail::DenseSetPair<ValueT>>,
283 ValueInfoT> {
285 ValueT,
286 SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets, ValueInfoT,
288 ValueInfoT>;
289
290public:
291 using BaseT::BaseT;
292};
293
294} // end namespace llvm
295
296#endif // LLVM_ADT_DENSESET_H
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains library features backported from future STL versions.
Value * RHS
Value * LHS
Implements a dense probed hash-table based set.
Definition: DenseSet.h:263
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition: DenseSet.h:283
Base class for DenseSet and DenseSmallSet.
Definition: DenseSet.h:56
const_iterator find(const_arg_type_t< ValueT > V) const
Definition: DenseSet.h:164
std::pair< iterator, bool > insert(ValueT &&V)
Definition: DenseSet.h:199
DenseSetImpl(llvm::from_range_t, Range &&R)
Definition: DenseSet.h:83
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:194
size_t getMemorySize() const
Definition: DenseSet.h:88
DenseSetIterator< false > iterator
Definition: DenseSet.h:154
const_iterator end() const
Definition: DenseSet.h:161
const_iterator begin() const
Definition: DenseSet.h:160
iterator find(const_arg_type_t< ValueT > V)
Definition: DenseSet.h:163
std::pair< iterator, bool > insert_as(const ValueT &V, const LookupKeyT &LookupKey)
Alternative version of insert that uses a different (and possibly less expensive) key type.
Definition: DenseSet.h:207
void reserve(size_t Size)
Grow the DenseSet so that it can contain at least NumEntries items before resizing again.
Definition: DenseSet.h:96
iterator find_as(const LookupKeyT &Val)
Alternative version of find() which allows a different, and possibly less expensive,...
Definition: DenseSet.h:183
void insert_range(Range &&R)
Definition: DenseSet.h:222
const_iterator find_as(const LookupKeyT &Val) const
Definition: DenseSet.h:187
size_type size() const
Definition: DenseSet.h:87
std::pair< iterator, bool > insert_as(ValueT &&V, const LookupKeyT &LookupKey)
Definition: DenseSet.h:212
void insert(InputIt I, InputIt E)
Definition: DenseSet.h:217
void swap(DenseSetImpl &RHS)
Definition: DenseSet.h:102
DenseSetImpl(unsigned InitialReserve=0)
Definition: DenseSet.h:69
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition: DenseSet.h:169
DenseSetImpl(const InputIt &I, const InputIt &E)
Definition: DenseSet.h:72
void resize(size_t Size)
Grow the DenseSet so that it has at least Size buckets.
Definition: DenseSet.h:92
DenseSetIterator< true > const_iterator
Definition: DenseSet.h:155
void erase(iterator I)
Definition: DenseSet.h:191
bool erase(const ValueT &V)
Definition: DenseSet.h:100
DenseSetImpl(std::initializer_list< ValueT > Elems)
Definition: DenseSet.h:77
void erase(const_iterator CI)
Definition: DenseSet.h:192
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition: DenseSet.h:174
const DenseSetEmpty & getSecond() const
Definition: DenseSet.h:43
const KeyT & getFirst() const
Definition: DenseSet.h:41
DenseSetEmpty & getSecond()
Definition: DenseSet.h:42
bool operator!=(const DenseSetImpl< ValueT, MapTy, ValueInfoT > &LHS, const DenseSetImpl< ValueT, MapTy, ValueInfoT > &RHS)
Inequality comparison for DenseSet.
Definition: DenseSet.h:250
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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
bool operator!=(uint64_t V1, const APInt &V2)
Definition: APInt.h:2113
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
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition: MathExtras.h:390
@ Other
Any other memory.
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: DenseMapInfo.h:54