2
0

SmallPtrSet.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. //===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
  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 implements the SmallPtrSet class. See SmallPtrSet.h for an
  11. // overview of the algorithm.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/ADT/SmallPtrSet.h"
  15. #include "llvm/ADT/DenseMapInfo.h"
  16. #include "llvm/Support/MathExtras.h"
  17. #include <algorithm>
  18. #include <cstdlib>
  19. using namespace llvm;
  20. void SmallPtrSetImplBase::shrink_and_clear() {
  21. assert(!isSmall() && "Can't shrink a small set!");
  22. delete[] CurArray; // HLSL Change: Use overridable operator delete
  23. // Reduce the number of buckets.
  24. CurArraySize = NumElements > 16 ? 1 << (Log2_32_Ceil(NumElements) + 1) : 32;
  25. NumElements = NumTombstones = 0;
  26. // Install the new array. Clear all the buckets to empty.
  27. CurArray = new const void*[CurArraySize]; // HLSL Change: Use overridable operator new
  28. assert(CurArray && "Failed to allocate memory?");
  29. memset(CurArray, -1, CurArraySize*sizeof(void*));
  30. }
  31. std::pair<const void *const *, bool>
  32. SmallPtrSetImplBase::insert_imp(const void *Ptr) {
  33. if (isSmall()) {
  34. // Check to see if it is already in the set.
  35. for (const void **APtr = SmallArray, **E = SmallArray+NumElements;
  36. APtr != E; ++APtr)
  37. if (*APtr == Ptr)
  38. return std::make_pair(APtr, false);
  39. // Nope, there isn't. If we stay small, just 'pushback' now.
  40. if (NumElements < CurArraySize) {
  41. SmallArray[NumElements++] = Ptr;
  42. return std::make_pair(SmallArray + (NumElements - 1), true);
  43. }
  44. // Otherwise, hit the big set case, which will call grow.
  45. }
  46. if (LLVM_UNLIKELY(NumElements * 4 >= CurArraySize * 3)) {
  47. // If more than 3/4 of the array is full, grow.
  48. Grow(CurArraySize < 64 ? 128 : CurArraySize*2);
  49. } else if (LLVM_UNLIKELY(CurArraySize - (NumElements + NumTombstones) <
  50. CurArraySize / 8)) {
  51. // If fewer of 1/8 of the array is empty (meaning that many are filled with
  52. // tombstones), rehash.
  53. Grow(CurArraySize);
  54. }
  55. // Okay, we know we have space. Find a hash bucket.
  56. const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr));
  57. if (*Bucket == Ptr)
  58. return std::make_pair(Bucket, false); // Already inserted, good.
  59. // Otherwise, insert it!
  60. if (*Bucket == getTombstoneMarker())
  61. --NumTombstones;
  62. *Bucket = Ptr;
  63. ++NumElements; // Track density.
  64. return std::make_pair(Bucket, true);
  65. }
  66. bool SmallPtrSetImplBase::erase_imp(const void * Ptr) {
  67. if (isSmall()) {
  68. // Check to see if it is in the set.
  69. for (const void **APtr = SmallArray, **E = SmallArray+NumElements;
  70. APtr != E; ++APtr)
  71. if (*APtr == Ptr) {
  72. // If it is in the set, replace this element.
  73. *APtr = E[-1];
  74. E[-1] = getEmptyMarker();
  75. --NumElements;
  76. return true;
  77. }
  78. return false;
  79. }
  80. // Okay, we know we have space. Find a hash bucket.
  81. void **Bucket = const_cast<void**>(FindBucketFor(Ptr));
  82. if (*Bucket != Ptr) return false; // Not in the set?
  83. // Set this as a tombstone.
  84. *Bucket = getTombstoneMarker();
  85. --NumElements;
  86. ++NumTombstones;
  87. return true;
  88. }
  89. const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
  90. unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1);
  91. unsigned ArraySize = CurArraySize;
  92. unsigned ProbeAmt = 1;
  93. const void *const *Array = CurArray;
  94. const void *const *Tombstone = nullptr;
  95. while (1) {
  96. // If we found an empty bucket, the pointer doesn't exist in the set.
  97. // Return a tombstone if we've seen one so far, or the empty bucket if
  98. // not.
  99. if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker()))
  100. return Tombstone ? Tombstone : Array+Bucket;
  101. // Found Ptr's bucket?
  102. if (LLVM_LIKELY(Array[Bucket] == Ptr))
  103. return Array+Bucket;
  104. // If this is a tombstone, remember it. If Ptr ends up not in the set, we
  105. // prefer to return it than something that would require more probing.
  106. if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
  107. Tombstone = Array+Bucket; // Remember the first tombstone found.
  108. // It's a hash collision or a tombstone. Reprobe.
  109. Bucket = (Bucket + ProbeAmt++) & (ArraySize-1);
  110. }
  111. }
  112. /// Grow - Allocate a larger backing store for the buckets and move it over.
  113. ///
  114. void SmallPtrSetImplBase::Grow(unsigned NewSize) {
  115. // Allocate at twice as many buckets, but at least 128.
  116. unsigned OldSize = CurArraySize;
  117. const void **OldBuckets = CurArray;
  118. bool WasSmall = isSmall();
  119. // Install the new array. Clear all the buckets to empty.
  120. CurArray = new const void*[NewSize]; // HLSL Change: Use overridable operator new
  121. assert(CurArray && "Failed to allocate memory?");
  122. CurArraySize = NewSize;
  123. memset(CurArray, -1, NewSize*sizeof(void*));
  124. // Copy over all the elements.
  125. if (WasSmall) {
  126. // Small sets store their elements in order.
  127. for (const void **BucketPtr = OldBuckets, **E = OldBuckets+NumElements;
  128. BucketPtr != E; ++BucketPtr) {
  129. const void *Elt = *BucketPtr;
  130. *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
  131. }
  132. } else {
  133. // Copy over all valid entries.
  134. for (const void **BucketPtr = OldBuckets, **E = OldBuckets+OldSize;
  135. BucketPtr != E; ++BucketPtr) {
  136. // Copy over the element if it is valid.
  137. const void *Elt = *BucketPtr;
  138. if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
  139. *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
  140. }
  141. delete[] OldBuckets; // HLSL Change: Use overridable operator delete
  142. NumTombstones = 0;
  143. }
  144. }
  145. SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
  146. const SmallPtrSetImplBase& that) {
  147. SmallArray = SmallStorage;
  148. // If we're becoming small, prepare to insert into our stack space
  149. if (that.isSmall()) {
  150. CurArray = SmallArray;
  151. // Otherwise, allocate new heap space (unless we were the same size)
  152. } else {
  153. CurArray = new const void*[that.CurArraySize]; // HLSL Change: Use overridable operator new
  154. assert(CurArray && "Failed to allocate memory?");
  155. }
  156. // Copy over the new array size
  157. CurArraySize = that.CurArraySize;
  158. // Copy over the contents from the other set
  159. memcpy(CurArray, that.CurArray, sizeof(void*)*CurArraySize);
  160. NumElements = that.NumElements;
  161. NumTombstones = that.NumTombstones;
  162. }
  163. SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
  164. unsigned SmallSize,
  165. SmallPtrSetImplBase &&that) {
  166. SmallArray = SmallStorage;
  167. // Copy over the basic members.
  168. CurArraySize = that.CurArraySize;
  169. NumElements = that.NumElements;
  170. NumTombstones = that.NumTombstones;
  171. // When small, just copy into our small buffer.
  172. if (that.isSmall()) {
  173. CurArray = SmallArray;
  174. memcpy(CurArray, that.CurArray, sizeof(void *) * CurArraySize);
  175. } else {
  176. // Otherwise, we steal the large memory allocation and no copy is needed.
  177. CurArray = that.CurArray;
  178. that.CurArray = that.SmallArray;
  179. }
  180. // Make the "that" object small and empty.
  181. that.CurArraySize = SmallSize;
  182. assert(that.CurArray == that.SmallArray);
  183. that.NumElements = 0;
  184. that.NumTombstones = 0;
  185. }
  186. /// CopyFrom - implement operator= from a smallptrset that has the same pointer
  187. /// type, but may have a different small size.
  188. void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) {
  189. assert(&RHS != this && "Self-copy should be handled by the caller.");
  190. if (isSmall() && RHS.isSmall())
  191. assert(CurArraySize == RHS.CurArraySize &&
  192. "Cannot assign sets with different small sizes");
  193. // If we're becoming small, prepare to insert into our stack space
  194. if (RHS.isSmall()) {
  195. if (!isSmall())
  196. delete[] CurArray; // HLSL Change: Use overridable operator delete
  197. CurArray = SmallArray;
  198. // Otherwise, allocate new heap space (unless we were the same size)
  199. } else if (CurArraySize != RHS.CurArraySize) {
  200. if (isSmall())
  201. CurArray = new const void*[RHS.CurArraySize]; // HLSL Change: Use overridable operator new
  202. else {
  203. // HLSL Change Begins: Use overridable operator new
  204. const void **T = new const void*[RHS.CurArraySize];
  205. std::memcpy(T, CurArray, std::min(CurArraySize, RHS.CurArraySize));
  206. delete[] CurArray;
  207. CurArray = T;
  208. // HLSL Change Ends
  209. }
  210. assert(CurArray && "Failed to allocate memory?");
  211. }
  212. // Copy over the new array size
  213. CurArraySize = RHS.CurArraySize;
  214. // Copy over the contents from the other set
  215. memcpy(CurArray, RHS.CurArray, sizeof(void*)*CurArraySize);
  216. NumElements = RHS.NumElements;
  217. NumTombstones = RHS.NumTombstones;
  218. }
  219. void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
  220. SmallPtrSetImplBase &&RHS) {
  221. assert(&RHS != this && "Self-move should be handled by the caller.");
  222. if (!isSmall())
  223. delete[] CurArray; // HLSL Change: Use overridable operator delete
  224. if (RHS.isSmall()) {
  225. // Copy a small RHS rather than moving.
  226. CurArray = SmallArray;
  227. memcpy(CurArray, RHS.CurArray, sizeof(void*)*RHS.CurArraySize);
  228. } else {
  229. CurArray = RHS.CurArray;
  230. RHS.CurArray = RHS.SmallArray;
  231. }
  232. // Copy the rest of the trivial members.
  233. CurArraySize = RHS.CurArraySize;
  234. NumElements = RHS.NumElements;
  235. NumTombstones = RHS.NumTombstones;
  236. // Make the RHS small and empty.
  237. RHS.CurArraySize = SmallSize;
  238. assert(RHS.CurArray == RHS.SmallArray);
  239. RHS.NumElements = 0;
  240. RHS.NumTombstones = 0;
  241. }
  242. void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) {
  243. if (this == &RHS) return;
  244. // We can only avoid copying elements if neither set is small.
  245. if (!this->isSmall() && !RHS.isSmall()) {
  246. std::swap(this->CurArray, RHS.CurArray);
  247. std::swap(this->CurArraySize, RHS.CurArraySize);
  248. std::swap(this->NumElements, RHS.NumElements);
  249. std::swap(this->NumTombstones, RHS.NumTombstones);
  250. return;
  251. }
  252. // FIXME: From here on we assume that both sets have the same small size.
  253. // If only RHS is small, copy the small elements into LHS and move the pointer
  254. // from LHS to RHS.
  255. if (!this->isSmall() && RHS.isSmall()) {
  256. std::copy(RHS.SmallArray, RHS.SmallArray+RHS.CurArraySize,
  257. this->SmallArray);
  258. std::swap(this->NumElements, RHS.NumElements);
  259. std::swap(this->CurArraySize, RHS.CurArraySize);
  260. RHS.CurArray = this->CurArray;
  261. RHS.NumTombstones = this->NumTombstones;
  262. this->CurArray = this->SmallArray;
  263. this->NumTombstones = 0;
  264. return;
  265. }
  266. // If only LHS is small, copy the small elements into RHS and move the pointer
  267. // from RHS to LHS.
  268. if (this->isSmall() && !RHS.isSmall()) {
  269. std::copy(this->SmallArray, this->SmallArray+this->CurArraySize,
  270. RHS.SmallArray);
  271. std::swap(RHS.NumElements, this->NumElements);
  272. std::swap(RHS.CurArraySize, this->CurArraySize);
  273. this->CurArray = RHS.CurArray;
  274. this->NumTombstones = RHS.NumTombstones;
  275. RHS.CurArray = RHS.SmallArray;
  276. RHS.NumTombstones = 0;
  277. return;
  278. }
  279. // Both a small, just swap the small elements.
  280. assert(this->isSmall() && RHS.isSmall());
  281. assert(this->CurArraySize == RHS.CurArraySize);
  282. std::swap_ranges(this->SmallArray, this->SmallArray+this->CurArraySize,
  283. RHS.SmallArray);
  284. std::swap(this->NumElements, RHS.NumElements);
  285. }
  286. SmallPtrSetImplBase::~SmallPtrSetImplBase() {
  287. if (!isSmall())
  288. delete[] CurArray; // HLSL Change: Use overridable operator delete
  289. }