LLVM 24.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"
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.
54template <typename ValueT, typename MapTy> class DenseSetImpl {
55 static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
56 "DenseMap buckets unexpectedly large!");
57 MapTy TheMap;
58
59 template <typename T>
60 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
61
62public:
63 using key_type = ValueT;
64 using value_type = ValueT;
66
67 explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
68
69 template <typename InputIt>
70 DenseSetImpl(const InputIt &I, const InputIt &E)
71 : DenseSetImpl(PowerOf2Ceil(std::distance(I, E))) {
72 insert(I, E);
73 }
74
75 DenseSetImpl(std::initializer_list<ValueT> Elems)
76 : DenseSetImpl(PowerOf2Ceil(Elems.size())) {
77 insert(Elems.begin(), Elems.end());
78 }
79
80 template <typename Range>
83
84 [[nodiscard]] bool empty() const { return TheMap.empty(); }
85 [[nodiscard]] size_type size() const { return TheMap.size(); }
86 [[nodiscard]] size_t getMemorySize() const { return TheMap.getMemorySize(); }
87
88 /// Grow the DenseSet so that it has at least Size buckets. Will not shrink
89 /// the Size of the set.
90 void resize(size_t Size) { TheMap.resize(Size); }
91
92 /// Grow the DenseSet so that it can contain at least \p NumEntries items
93 /// before resizing again.
94 void reserve(size_t Size) { TheMap.reserve(Size); }
95
96 void clear() { TheMap.clear(); }
97
98 bool erase(const ValueT &V) { return TheMap.erase(V); }
99
100 /// Remove all elements for which \p Pred returns true. This is the safe
101 /// replacement for erase-while-iterating; see DenseMap::remove_if. The
102 /// predicate must not access the set being modified. Returns whether
103 /// anything was removed; if so, all iterators are invalidated.
104 template <typename Predicate> bool remove_if(Predicate Pred) {
105 return TheMap.remove_if([&](const typename MapTy::value_type &KV) {
106 return Pred(KV.getFirst());
107 });
108 }
109
110 void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
111
112private:
113 template <bool IsConst> class DenseSetIterator {
114 friend class DenseSetImpl;
115
116 using MapIteratorT =
117 std::conditional_t<IsConst, typename MapTy::const_iterator,
118 typename MapTy::iterator>;
119
120 MapIteratorT I;
121
122 public:
123 using difference_type = typename MapIteratorT::difference_type;
124 using iterator_category = std::forward_iterator_tag;
125 using value_type = ValueT;
126 using pointer =
127 std::conditional_t<IsConst, const value_type *, value_type *>;
128 using reference =
129 std::conditional_t<IsConst, const value_type &, value_type &>;
130
131 DenseSetIterator() = default;
132 DenseSetIterator(MapIteratorT I) : I(I) {}
133
134 // Allow conversion from iterator to const_iterator.
135 template <bool C = IsConst, typename = std::enable_if_t<C>>
136 DenseSetIterator(const DenseSetIterator<false> &Other) : I(Other.I) {}
137
138 reference operator*() const { return I->getFirst(); }
139 pointer operator->() const { return &I->getFirst(); }
140
141 DenseSetIterator &operator++() {
142 ++I;
143 return *this;
144 }
145 DenseSetIterator operator++(int) {
146 auto T = *this;
147 ++I;
148 return T;
149 }
150
151 friend bool operator==(const DenseSetIterator &LHS,
152 const DenseSetIterator &RHS) {
153 return LHS.I == RHS.I;
154 }
155 friend bool operator!=(const DenseSetIterator &LHS,
156 const DenseSetIterator &RHS) {
157 return LHS.I != RHS.I;
158 }
159 };
160
161public:
162 using iterator = DenseSetIterator<false>;
163 using const_iterator = DenseSetIterator<true>;
164
165 [[nodiscard]] iterator begin() { return iterator(TheMap.begin()); }
166 [[nodiscard]] iterator end() { return iterator(TheMap.end()); }
167
168 [[nodiscard]] const_iterator begin() const {
169 return const_iterator(TheMap.begin());
170 }
171 [[nodiscard]] const_iterator end() const {
172 return const_iterator(TheMap.end());
173 }
174
175 [[nodiscard]] iterator find(const_arg_type_t<ValueT> V) {
176 return iterator(TheMap.find(V));
177 }
178 [[nodiscard]] const_iterator find(const_arg_type_t<ValueT> V) const {
179 return const_iterator(TheMap.find(V));
180 }
181
182 /// Check if the set contains the given element.
183 [[nodiscard]] bool contains(const_arg_type_t<ValueT> V) const {
184 return TheMap.contains(V);
185 }
186
187 /// Return 1 if the specified key is in the set, 0 otherwise.
188 [[nodiscard]] size_type count(const_arg_type_t<ValueT> V) const {
189 return TheMap.count(V);
190 }
191
192 /// Alternative version of find() which allows a different, and possibly less
193 /// expensive, key type.
194 /// The DenseMapInfo is responsible for supplying methods
195 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
196 /// used.
197 template <class LookupKeyT>
198 [[nodiscard]] iterator find_as(const LookupKeyT &Val) {
199 return iterator(TheMap.find_as(Val));
200 }
201 template <class LookupKeyT>
202 [[nodiscard]]
203 const_iterator find_as(const LookupKeyT &Val) const {
204 return const_iterator(TheMap.find_as(Val));
205 }
206
207 void erase(iterator I) { return TheMap.erase(I.I); }
208 void erase(const_iterator CI) { return TheMap.erase(CI.I); }
209
210 std::pair<iterator, bool> insert(const ValueT &V) {
211 return TheMap.try_emplace(V);
212 }
213
214 std::pair<iterator, bool> insert(ValueT &&V) {
215 return TheMap.try_emplace(std::move(V));
216 }
217
218 /// Alternative version of insert that uses a different (and possibly less
219 /// expensive) key type.
220 template <typename LookupKeyT>
221 std::pair<iterator, bool> insert_as(const ValueT &V,
222 const LookupKeyT &LookupKey) {
223 return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey);
224 }
225 template <typename LookupKeyT>
226 std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
227 return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey);
228 }
229
230 // Range insertion of values.
231 template <typename InputIt> void insert(InputIt I, InputIt E) {
232 for (; I != E; ++I)
233 insert(*I);
234 }
235
236 template <typename Range> void insert_range(Range &&R) {
237 insert(adl_begin(R), adl_end(R));
238 }
239};
240
241/// Equality comparison for DenseSet.
242///
243/// Iterates over elements of LHS confirming that each element is also a member
244/// of RHS, and that RHS contains no additional values.
245/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
246/// case is O(N^2) (if every hash collides).
247template <typename ValueT, typename MapTy>
250 if (LHS.size() != RHS.size())
251 return false;
252
253 for (auto &E : LHS)
254 if (!RHS.count(E))
255 return false;
256
257 return true;
258}
259
260/// Inequality comparison for DenseSet.
261///
262/// Equivalent to !(LHS == RHS). See operator== for performance notes.
263template <typename ValueT, typename MapTy>
266 return !(LHS == RHS);
267}
268
269template <typename ValueT, typename ValueInfoT>
272
273template <typename ValueT, unsigned InlineBuckets, typename ValueInfoT>
275 DenseSetImpl<ValueT, SmallDenseMap<ValueT, DenseSetEmpty, InlineBuckets,
276 ValueInfoT, DenseSetPair<ValueT>>>;
277
278} // end namespace detail
279
280/// Implements a dense probed hash-table based set.
281template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
283 : public detail::DenseSet<ValueT, ValueInfoT> {
285
286public:
287 using BaseT::BaseT;
288};
289
290/// Implements a dense probed hash-table based set with some number of buckets
291/// stored inline.
292template <typename ValueT, unsigned InlineBuckets = 4,
293 typename ValueInfoT = DenseMapInfo<ValueT>>
295 : public detail::SmallDenseSet<ValueT, InlineBuckets, ValueInfoT> {
297
298public:
299 using BaseT::BaseT;
300};
301
302} // end namespace llvm
303
304#endif // LLVM_ADT_DENSESET_H
SDValue Pred
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ATTRIBUTE_WARN_UNUSED
Definition Compiler.h:240
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
#define I(x, y, z)
Definition MD5.cpp:57
bool operator==(const MergedFunctionsInfo &LHS, const MergedFunctionsInfo &RHS)
#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:283
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:295
Base class for DenseSet and DenseSmallSet.
Definition DenseSet.h:54
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:210
DenseSetIterator< false > iterator
Definition DenseSet.h:162
std::pair< iterator, bool > insert_as(const ValueT &V, const LookupKeyT &LookupKey)
Definition DenseSet.h:221
DenseSetImpl(unsigned InitialReserve=0)
Definition DenseSet.h:67
DenseSetIterator< true > const_iterator
Definition DenseSet.h:163
std::pair< iterator, bool > insert_as(ValueT &&V, const LookupKeyT &LookupKey)
Definition DenseSet.h:226
const DenseSetEmpty & getSecond() const
Definition DenseSet.h:43
const KeyT & getFirst() const
Definition DenseSet.h:41
DenseSetEmpty & getSecond()
Definition DenseSet.h:42
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
bool operator!=(const DenseSetImpl< ValueT, MapTy > &LHS, const DenseSetImpl< ValueT, MapTy > &RHS)
Inequality comparison for DenseSet.
Definition DenseSet.h:264
DenseSetImpl< ValueT, SmallDenseMap< ValueT, DenseSetEmpty, InlineBuckets, ValueInfoT, DenseSetPair< ValueT > > > SmallDenseSet
Definition DenseSet.h:274
bool operator==(const DenseSetImpl< ValueT, MapTy > &LHS, const DenseSetImpl< ValueT, MapTy > &RHS)
Equality comparison for DenseSet.
Definition DenseSet.h:248
DenseSetImpl< ValueT, DenseMap< ValueT, DenseSetEmpty, ValueInfoT, DenseSetPair< ValueT > > > DenseSet
Definition DenseSet.h:270
This is an optimization pass for GlobalISel generic memory operations.
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
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition MathExtras.h:380
@ Other
Any other memory.
Definition ModRef.h:68
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
An information struct used to provide DenseMap with the various necessary components for a given valu...
std::conditional_t< std::is_pointer_v< T >, typename add_const_past_pointer< T >::type, const T & > type
Definition type_traits.h:53