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