SmallPtrSet.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. //===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the SmallPtrSet class. See the doxygen comment for
  11. // SmallPtrSetImplBase for more details on the algorithm used.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_ADT_SMALLPTRSET_H
  15. #define LLVM_ADT_SMALLPTRSET_H
  16. #include "llvm/Support/Compiler.h"
  17. #include "llvm/Support/DataTypes.h"
  18. #include "llvm/Support/PointerLikeTypeTraits.h"
  19. #include <cassert>
  20. #include <cstddef>
  21. #include <cstring>
  22. #include <iterator>
  23. #include <utility>
  24. namespace llvm {
  25. class SmallPtrSetIteratorImpl;
  26. /// SmallPtrSetImplBase - This is the common code shared among all the
  27. /// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one
  28. /// for small and one for large sets.
  29. ///
  30. /// Small sets use an array of pointers allocated in the SmallPtrSet object,
  31. /// which is treated as a simple array of pointers. When a pointer is added to
  32. /// the set, the array is scanned to see if the element already exists, if not
  33. /// the element is 'pushed back' onto the array. If we run out of space in the
  34. /// array, we grow into the 'large set' case. SmallSet should be used when the
  35. /// sets are often small. In this case, no memory allocation is used, and only
  36. /// light-weight and cache-efficient scanning is used.
  37. ///
  38. /// Large sets use a classic exponentially-probed hash table. Empty buckets are
  39. /// represented with an illegal pointer value (-1) to allow null pointers to be
  40. /// inserted. Tombstones are represented with another illegal pointer value
  41. /// (-2), to allow deletion. The hash table is resized when the table is 3/4 or
  42. /// more. When this happens, the table is doubled in size.
  43. ///
  44. class SmallPtrSetImplBase {
  45. friend class SmallPtrSetIteratorImpl;
  46. protected:
  47. /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
  48. const void **SmallArray;
  49. /// CurArray - This is the current set of buckets. If equal to SmallArray,
  50. /// then the set is in 'small mode'.
  51. const void **CurArray;
  52. /// CurArraySize - The allocated size of CurArray, always a power of two.
  53. unsigned CurArraySize;
  54. // If small, this is # elts allocated consecutively
  55. unsigned NumElements;
  56. unsigned NumTombstones;
  57. // Helpers to copy and move construct a SmallPtrSet.
  58. SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that);
  59. SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize,
  60. SmallPtrSetImplBase &&that);
  61. explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) :
  62. SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
  63. assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
  64. "Initial size must be a power of two!");
  65. clear();
  66. }
  67. ~SmallPtrSetImplBase();
  68. public:
  69. typedef unsigned size_type;
  70. bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; }
  71. size_type size() const { return NumElements; }
  72. void clear() {
  73. // If the capacity of the array is huge, and the # elements used is small,
  74. // shrink the array.
  75. if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32)
  76. return shrink_and_clear();
  77. // Fill the array with empty markers.
  78. memset(CurArray, -1, CurArraySize*sizeof(void*));
  79. NumElements = 0;
  80. NumTombstones = 0;
  81. }
  82. protected:
  83. static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); }
  84. static void *getEmptyMarker() {
  85. // Note that -1 is chosen to make clear() efficiently implementable with
  86. // memset and because it's not a valid pointer value.
  87. return reinterpret_cast<void*>(-1);
  88. }
  89. /// insert_imp - This returns true if the pointer was new to the set, false if
  90. /// it was already in the set. This is hidden from the client so that the
  91. /// derived class can check that the right type of pointer is passed in.
  92. std::pair<const void *const *, bool> insert_imp(const void *Ptr);
  93. /// erase_imp - If the set contains the specified pointer, remove it and
  94. /// return true, otherwise return false. This is hidden from the client so
  95. /// that the derived class can check that the right type of pointer is passed
  96. /// in.
  97. bool erase_imp(const void * Ptr);
  98. bool count_imp(const void * Ptr) const {
  99. if (isSmall()) {
  100. // Linear search for the item.
  101. for (const void *const *APtr = SmallArray,
  102. *const *E = SmallArray+NumElements; APtr != E; ++APtr)
  103. if (*APtr == Ptr)
  104. return true;
  105. return false;
  106. }
  107. // Big set case.
  108. return *FindBucketFor(Ptr) == Ptr;
  109. }
  110. private:
  111. bool isSmall() const { return CurArray == SmallArray; }
  112. const void * const *FindBucketFor(const void *Ptr) const;
  113. void shrink_and_clear();
  114. /// Grow - Allocate a larger backing store for the buckets and move it over.
  115. void Grow(unsigned NewSize);
  116. void operator=(const SmallPtrSetImplBase &RHS) = delete;
  117. protected:
  118. /// swap - Swaps the elements of two sets.
  119. /// Note: This method assumes that both sets have the same small size.
  120. void swap(SmallPtrSetImplBase &RHS);
  121. void CopyFrom(const SmallPtrSetImplBase &RHS);
  122. void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
  123. };
  124. /// SmallPtrSetIteratorImpl - This is the common base class shared between all
  125. /// instances of SmallPtrSetIterator.
  126. class SmallPtrSetIteratorImpl {
  127. protected:
  128. const void *const *Bucket;
  129. const void *const *End;
  130. public:
  131. explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
  132. : Bucket(BP), End(E) {
  133. AdvanceIfNotValid();
  134. }
  135. bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
  136. return Bucket == RHS.Bucket;
  137. }
  138. bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
  139. return Bucket != RHS.Bucket;
  140. }
  141. protected:
  142. /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket
  143. /// that is. This is guaranteed to stop because the end() bucket is marked
  144. /// valid.
  145. void AdvanceIfNotValid() {
  146. assert(Bucket <= End);
  147. while (Bucket != End &&
  148. (*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
  149. *Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
  150. ++Bucket;
  151. }
  152. };
  153. /// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
  154. template<typename PtrTy>
  155. class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
  156. typedef PointerLikeTypeTraits<PtrTy> PtrTraits;
  157. public:
  158. typedef PtrTy value_type;
  159. typedef PtrTy reference;
  160. typedef PtrTy pointer;
  161. typedef std::ptrdiff_t difference_type;
  162. typedef std::forward_iterator_tag iterator_category;
  163. explicit SmallPtrSetIterator(const void *const *BP, const void *const *E)
  164. : SmallPtrSetIteratorImpl(BP, E) {}
  165. // Most methods provided by baseclass.
  166. const PtrTy operator*() const {
  167. assert(Bucket < End);
  168. return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
  169. }
  170. inline SmallPtrSetIterator& operator++() { // Preincrement
  171. ++Bucket;
  172. AdvanceIfNotValid();
  173. return *this;
  174. }
  175. SmallPtrSetIterator operator++(int) { // Postincrement
  176. SmallPtrSetIterator tmp = *this; ++*this; return tmp;
  177. }
  178. };
  179. /// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next
  180. /// power of two (which means N itself if N is already a power of two).
  181. template<unsigned N>
  182. struct RoundUpToPowerOfTwo;
  183. /// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a
  184. /// helper template used to implement RoundUpToPowerOfTwo.
  185. template<unsigned N, bool isPowerTwo>
  186. struct RoundUpToPowerOfTwoH {
  187. enum { Val = N };
  188. };
  189. template<unsigned N>
  190. struct RoundUpToPowerOfTwoH<N, false> {
  191. enum {
  192. // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets
  193. // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111.
  194. Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
  195. };
  196. };
  197. template<unsigned N>
  198. struct RoundUpToPowerOfTwo {
  199. enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
  200. };
  201. /// \brief A templated base class for \c SmallPtrSet which provides the
  202. /// typesafe interface that is common across all small sizes.
  203. ///
  204. /// This is particularly useful for passing around between interface boundaries
  205. /// to avoid encoding a particular small size in the interface boundary.
  206. template <typename PtrType>
  207. class SmallPtrSetImpl : public SmallPtrSetImplBase {
  208. typedef PointerLikeTypeTraits<PtrType> PtrTraits;
  209. SmallPtrSetImpl(const SmallPtrSetImpl&) = delete;
  210. protected:
  211. // Constructors that forward to the base.
  212. SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
  213. : SmallPtrSetImplBase(SmallStorage, that) {}
  214. SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize,
  215. SmallPtrSetImpl &&that)
  216. : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {}
  217. explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize)
  218. : SmallPtrSetImplBase(SmallStorage, SmallSize) {}
  219. public:
  220. typedef SmallPtrSetIterator<PtrType> iterator;
  221. typedef SmallPtrSetIterator<PtrType> const_iterator;
  222. /// Inserts Ptr if and only if there is no element in the container equal to
  223. /// Ptr. The bool component of the returned pair is true if and only if the
  224. /// insertion takes place, and the iterator component of the pair points to
  225. /// the element equal to Ptr.
  226. std::pair<iterator, bool> insert(PtrType Ptr) {
  227. auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
  228. return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second);
  229. }
  230. /// erase - If the set contains the specified pointer, remove it and return
  231. /// true, otherwise return false.
  232. bool erase(PtrType Ptr) {
  233. return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
  234. }
  235. /// count - Return 1 if the specified pointer is in the set, 0 otherwise.
  236. size_type count(PtrType Ptr) const {
  237. return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0;
  238. }
  239. template <typename IterT>
  240. void insert(IterT I, IterT E) {
  241. for (; I != E; ++I)
  242. insert(*I);
  243. }
  244. inline iterator begin() const {
  245. return iterator(CurArray, CurArray+CurArraySize);
  246. }
  247. inline iterator end() const {
  248. return iterator(CurArray+CurArraySize, CurArray+CurArraySize);
  249. }
  250. };
  251. /// SmallPtrSet - This class implements a set which is optimized for holding
  252. /// SmallSize or less elements. This internally rounds up SmallSize to the next
  253. /// power of two if it is not already a power of two. See the comments above
  254. /// SmallPtrSetImplBase for details of the algorithm.
  255. template<class PtrType, unsigned SmallSize>
  256. class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
  257. typedef SmallPtrSetImpl<PtrType> BaseT;
  258. // Make sure that SmallSize is a power of two, round up if not.
  259. enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
  260. /// SmallStorage - Fixed size storage used in 'small mode'.
  261. const void *SmallStorage[SmallSizePowTwo];
  262. public:
  263. SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {}
  264. SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {}
  265. SmallPtrSet(SmallPtrSet &&that)
  266. : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {}
  267. template<typename It>
  268. SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) {
  269. this->insert(I, E);
  270. }
  271. SmallPtrSet<PtrType, SmallSize> &
  272. operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
  273. if (&RHS != this)
  274. this->CopyFrom(RHS);
  275. return *this;
  276. }
  277. SmallPtrSet<PtrType, SmallSize>&
  278. operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) {
  279. if (&RHS != this)
  280. this->MoveFrom(SmallSizePowTwo, std::move(RHS));
  281. return *this;
  282. }
  283. /// swap - Swaps the elements of two sets.
  284. void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
  285. SmallPtrSetImplBase::swap(RHS);
  286. }
  287. };
  288. }
  289. namespace std {
  290. /// Implement std::swap in terms of SmallPtrSet swap.
  291. template<class T, unsigned N>
  292. inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
  293. LHS.swap(RHS);
  294. }
  295. }
  296. #endif