DenseSet.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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. // This file defines the DenseSet and SmallDenseSet classes.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_ADT_DENSESET_H
  13. #define LLVM_ADT_DENSESET_H
  14. #include "llvm/ADT/DenseMap.h"
  15. #include "llvm/ADT/DenseMapInfo.h"
  16. #include "llvm/Support/MathExtras.h"
  17. #include "llvm/Support/type_traits.h"
  18. #include <algorithm>
  19. #include <cstddef>
  20. #include <initializer_list>
  21. #include <iterator>
  22. #include <utility>
  23. namespace llvm {
  24. namespace detail {
  25. struct DenseSetEmpty {};
  26. // Use the empty base class trick so we can create a DenseMap where the buckets
  27. // contain only a single item.
  28. template <typename KeyT> class DenseSetPair : public DenseSetEmpty {
  29. KeyT key;
  30. public:
  31. KeyT &getFirst() { return key; }
  32. const KeyT &getFirst() const { return key; }
  33. DenseSetEmpty &getSecond() { return *this; }
  34. const DenseSetEmpty &getSecond() const { return *this; }
  35. };
  36. /// Base class for DenseSet and DenseSmallSet.
  37. ///
  38. /// MapTy should be either
  39. ///
  40. /// DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
  41. /// detail::DenseSetPair<ValueT>>
  42. ///
  43. /// or the equivalent SmallDenseMap type. ValueInfoT must implement the
  44. /// DenseMapInfo "concept".
  45. template <typename ValueT, typename MapTy, typename ValueInfoT>
  46. class DenseSetImpl {
  47. static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
  48. "DenseMap buckets unexpectedly large!");
  49. MapTy TheMap;
  50. template <typename T>
  51. using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
  52. public:
  53. using key_type = ValueT;
  54. using value_type = ValueT;
  55. using size_type = unsigned;
  56. explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
  57. template <typename InputIt>
  58. DenseSetImpl(const InputIt &I, const InputIt &E)
  59. : DenseSetImpl(PowerOf2Ceil(std::distance(I, E))) {
  60. insert(I, E);
  61. }
  62. DenseSetImpl(std::initializer_list<ValueT> Elems)
  63. : DenseSetImpl(PowerOf2Ceil(Elems.size())) {
  64. insert(Elems.begin(), Elems.end());
  65. }
  66. bool empty() const { return TheMap.empty(); }
  67. size_type size() const { return TheMap.size(); }
  68. size_t getMemorySize() const { return TheMap.getMemorySize(); }
  69. /// Grow the DenseSet so that it has at least Size buckets. Will not shrink
  70. /// the Size of the set.
  71. void resize(size_t Size) { TheMap.resize(Size); }
  72. /// Grow the DenseSet so that it can contain at least \p NumEntries items
  73. /// before resizing again.
  74. void reserve(size_t Size) { TheMap.reserve(Size); }
  75. void clear() {
  76. TheMap.clear();
  77. }
  78. /// Return 1 if the specified key is in the set, 0 otherwise.
  79. size_type count(const_arg_type_t<ValueT> V) const {
  80. return TheMap.count(V);
  81. }
  82. bool erase(const ValueT &V) {
  83. return TheMap.erase(V);
  84. }
  85. void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
  86. // Iterators.
  87. class ConstIterator;
  88. class Iterator {
  89. typename MapTy::iterator I;
  90. friend class DenseSetImpl;
  91. friend class ConstIterator;
  92. public:
  93. using difference_type = typename MapTy::iterator::difference_type;
  94. using value_type = ValueT;
  95. using pointer = value_type *;
  96. using reference = value_type &;
  97. using iterator_category = std::forward_iterator_tag;
  98. Iterator() = default;
  99. Iterator(const typename MapTy::iterator &i) : I(i) {}
  100. ValueT &operator*() { return I->getFirst(); }
  101. const ValueT &operator*() const { return I->getFirst(); }
  102. ValueT *operator->() { return &I->getFirst(); }
  103. const ValueT *operator->() const { return &I->getFirst(); }
  104. Iterator& operator++() { ++I; return *this; }
  105. Iterator operator++(int) { auto T = *this; ++I; return T; }
  106. friend bool operator==(const Iterator &X, const Iterator &Y) {
  107. return X.I == Y.I;
  108. }
  109. friend bool operator!=(const Iterator &X, const Iterator &Y) {
  110. return X.I != Y.I;
  111. }
  112. };
  113. class ConstIterator {
  114. typename MapTy::const_iterator I;
  115. friend class DenseSetImpl;
  116. friend class Iterator;
  117. public:
  118. using difference_type = typename MapTy::const_iterator::difference_type;
  119. using value_type = ValueT;
  120. using pointer = const value_type *;
  121. using reference = const value_type &;
  122. using iterator_category = std::forward_iterator_tag;
  123. ConstIterator() = default;
  124. ConstIterator(const Iterator &B) : I(B.I) {}
  125. ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
  126. const ValueT &operator*() const { return I->getFirst(); }
  127. const ValueT *operator->() const { return &I->getFirst(); }
  128. ConstIterator& operator++() { ++I; return *this; }
  129. ConstIterator operator++(int) { auto T = *this; ++I; return T; }
  130. friend bool operator==(const ConstIterator &X, const ConstIterator &Y) {
  131. return X.I == Y.I;
  132. }
  133. friend bool operator!=(const ConstIterator &X, const ConstIterator &Y) {
  134. return X.I != Y.I;
  135. }
  136. };
  137. using iterator = Iterator;
  138. using const_iterator = ConstIterator;
  139. iterator begin() { return Iterator(TheMap.begin()); }
  140. iterator end() { return Iterator(TheMap.end()); }
  141. const_iterator begin() const { return ConstIterator(TheMap.begin()); }
  142. const_iterator end() const { return ConstIterator(TheMap.end()); }
  143. iterator find(const_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); }
  144. const_iterator find(const_arg_type_t<ValueT> V) const {
  145. return ConstIterator(TheMap.find(V));
  146. }
  147. /// Check if the set contains the given element.
  148. bool contains(const_arg_type_t<ValueT> V) const {
  149. return TheMap.find(V) != TheMap.end();
  150. }
  151. /// Alternative version of find() which allows a different, and possibly less
  152. /// expensive, key type.
  153. /// The DenseMapInfo is responsible for supplying methods
  154. /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
  155. /// used.
  156. template <class LookupKeyT>
  157. iterator find_as(const LookupKeyT &Val) {
  158. return Iterator(TheMap.find_as(Val));
  159. }
  160. template <class LookupKeyT>
  161. const_iterator find_as(const LookupKeyT &Val) const {
  162. return ConstIterator(TheMap.find_as(Val));
  163. }
  164. void erase(Iterator I) { return TheMap.erase(I.I); }
  165. void erase(ConstIterator CI) { return TheMap.erase(CI.I); }
  166. std::pair<iterator, bool> insert(const ValueT &V) {
  167. detail::DenseSetEmpty Empty;
  168. return TheMap.try_emplace(V, Empty);
  169. }
  170. std::pair<iterator, bool> insert(ValueT &&V) {
  171. detail::DenseSetEmpty Empty;
  172. return TheMap.try_emplace(std::move(V), Empty);
  173. }
  174. /// Alternative version of insert that uses a different (and possibly less
  175. /// expensive) key type.
  176. template <typename LookupKeyT>
  177. std::pair<iterator, bool> insert_as(const ValueT &V,
  178. const LookupKeyT &LookupKey) {
  179. return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey);
  180. }
  181. template <typename LookupKeyT>
  182. std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
  183. return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey);
  184. }
  185. // Range insertion of values.
  186. template<typename InputIt>
  187. void insert(InputIt I, InputIt E) {
  188. for (; I != E; ++I)
  189. insert(*I);
  190. }
  191. };
  192. /// Equality comparison for DenseSet.
  193. ///
  194. /// Iterates over elements of LHS confirming that each element is also a member
  195. /// of RHS, and that RHS contains no additional values.
  196. /// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
  197. /// case is O(N^2) (if every hash collides).
  198. template <typename ValueT, typename MapTy, typename ValueInfoT>
  199. bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
  200. const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
  201. if (LHS.size() != RHS.size())
  202. return false;
  203. for (auto &E : LHS)
  204. if (!RHS.count(E))
  205. return false;
  206. return true;
  207. }
  208. /// Inequality comparison for DenseSet.
  209. ///
  210. /// Equivalent to !(LHS == RHS). See operator== for performance notes.
  211. template <typename ValueT, typename MapTy, typename ValueInfoT>
  212. bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
  213. const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
  214. return !(LHS == RHS);
  215. }
  216. } // end namespace detail
  217. /// Implements a dense probed hash-table based set.
  218. template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
  219. class DenseSet : public detail::DenseSetImpl<
  220. ValueT, DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
  221. detail::DenseSetPair<ValueT>>,
  222. ValueInfoT> {
  223. using BaseT =
  224. detail::DenseSetImpl<ValueT,
  225. DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
  226. detail::DenseSetPair<ValueT>>,
  227. ValueInfoT>;
  228. public:
  229. using BaseT::BaseT;
  230. };
  231. /// Implements a dense probed hash-table based set with some number of buckets
  232. /// stored inline.
  233. template <typename ValueT, unsigned InlineBuckets = 4,
  234. typename ValueInfoT = DenseMapInfo<ValueT>>
  235. class SmallDenseSet
  236. : public detail::DenseSetImpl<
  237. ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
  238. ValueInfoT, detail::DenseSetPair<ValueT>>,
  239. ValueInfoT> {
  240. using BaseT = detail::DenseSetImpl<
  241. ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
  242. ValueInfoT, detail::DenseSetPair<ValueT>>,
  243. ValueInfoT>;
  244. public:
  245. using BaseT::BaseT;
  246. };
  247. } // end namespace llvm
  248. #endif // LLVM_ADT_DENSESET_H