LLVM  4.0.0
SmallPtrSet.cpp
Go to the documentation of this file.
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 
15 #include "llvm/ADT/SmallPtrSet.h"
16 #include "llvm/ADT/DenseMapInfo.h"
18 #include <algorithm>
19 #include <cassert>
20 #include <cstdlib>
21 
22 using namespace llvm;
23 
24 void SmallPtrSetImplBase::shrink_and_clear() {
25  assert(!isSmall() && "Can't shrink a small set!");
26  free(CurArray);
27 
28  // Reduce the number of buckets.
29  unsigned Size = size();
30  CurArraySize = Size > 16 ? 1 << (Log2_32_Ceil(Size) + 1) : 32;
32 
33  // Install the new array. Clear all the buckets to empty.
34  CurArray = (const void**)malloc(sizeof(void*) * CurArraySize);
35  assert(CurArray && "Failed to allocate memory?");
36  memset(CurArray, -1, CurArraySize*sizeof(void*));
37 }
38 
39 std::pair<const void *const *, bool>
40 SmallPtrSetImplBase::insert_imp_big(const void *Ptr) {
41  if (LLVM_UNLIKELY(size() * 4 >= CurArraySize * 3)) {
42  // If more than 3/4 of the array is full, grow.
43  Grow(CurArraySize < 64 ? 128 : CurArraySize * 2);
44  } else if (LLVM_UNLIKELY(CurArraySize - NumNonEmpty < CurArraySize / 8)) {
45  // If fewer of 1/8 of the array is empty (meaning that many are filled with
46  // tombstones), rehash.
47  Grow(CurArraySize);
48  }
49 
50  // Okay, we know we have space. Find a hash bucket.
51  const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr));
52  if (*Bucket == Ptr)
53  return std::make_pair(Bucket, false); // Already inserted, good.
54 
55  // Otherwise, insert it!
56  if (*Bucket == getTombstoneMarker())
57  --NumTombstones;
58  else
59  ++NumNonEmpty; // Track density.
60  *Bucket = Ptr;
61  return std::make_pair(Bucket, true);
62 }
63 
64 const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
65  unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1);
66  unsigned ArraySize = CurArraySize;
67  unsigned ProbeAmt = 1;
68  const void *const *Array = CurArray;
69  const void *const *Tombstone = nullptr;
70  while (true) {
71  // If we found an empty bucket, the pointer doesn't exist in the set.
72  // Return a tombstone if we've seen one so far, or the empty bucket if
73  // not.
74  if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker()))
75  return Tombstone ? Tombstone : Array+Bucket;
76 
77  // Found Ptr's bucket?
78  if (LLVM_LIKELY(Array[Bucket] == Ptr))
79  return Array+Bucket;
80 
81  // If this is a tombstone, remember it. If Ptr ends up not in the set, we
82  // prefer to return it than something that would require more probing.
83  if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
84  Tombstone = Array+Bucket; // Remember the first tombstone found.
85 
86  // It's a hash collision or a tombstone. Reprobe.
87  Bucket = (Bucket + ProbeAmt++) & (ArraySize-1);
88  }
89 }
90 
91 /// Grow - Allocate a larger backing store for the buckets and move it over.
92 ///
93 void SmallPtrSetImplBase::Grow(unsigned NewSize) {
94  const void **OldBuckets = CurArray;
95  const void **OldEnd = EndPointer();
96  bool WasSmall = isSmall();
97 
98  // Install the new array. Clear all the buckets to empty.
99  CurArray = (const void**)malloc(sizeof(void*) * NewSize);
100  assert(CurArray && "Failed to allocate memory?");
101  CurArraySize = NewSize;
102  memset(CurArray, -1, NewSize*sizeof(void*));
103 
104  // Copy over all valid entries.
105  for (const void **BucketPtr = OldBuckets; BucketPtr != OldEnd; ++BucketPtr) {
106  // Copy over the element if it is valid.
107  const void *Elt = *BucketPtr;
108  if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
109  *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
110  }
111 
112  if (!WasSmall)
113  free(OldBuckets);
114  NumNonEmpty -= NumTombstones;
115  NumTombstones = 0;
116 }
117 
119  const SmallPtrSetImplBase &that) {
120  SmallArray = SmallStorage;
121 
122  // If we're becoming small, prepare to insert into our stack space
123  if (that.isSmall()) {
125  // Otherwise, allocate new heap space (unless we were the same size)
126  } else {
127  CurArray = (const void**)malloc(sizeof(void*) * that.CurArraySize);
128  assert(CurArray && "Failed to allocate memory?");
129  }
130 
131  // Copy over the that array.
132  CopyHelper(that);
133 }
134 
136  unsigned SmallSize,
137  SmallPtrSetImplBase &&that) {
138  SmallArray = SmallStorage;
139  MoveHelper(SmallSize, std::move(that));
140 }
141 
143  assert(&RHS != this && "Self-copy should be handled by the caller.");
144 
145  if (isSmall() && RHS.isSmall())
147  "Cannot assign sets with different small sizes");
148 
149  // If we're becoming small, prepare to insert into our stack space
150  if (RHS.isSmall()) {
151  if (!isSmall())
152  free(CurArray);
154  // Otherwise, allocate new heap space (unless we were the same size)
155  } else if (CurArraySize != RHS.CurArraySize) {
156  if (isSmall())
157  CurArray = (const void**)malloc(sizeof(void*) * RHS.CurArraySize);
158  else {
159  const void **T = (const void**)realloc(CurArray,
160  sizeof(void*) * RHS.CurArraySize);
161  if (!T)
162  free(CurArray);
163  CurArray = T;
164  }
165  assert(CurArray && "Failed to allocate memory?");
166  }
167 
168  CopyHelper(RHS);
169 }
170 
171 void SmallPtrSetImplBase::CopyHelper(const SmallPtrSetImplBase &RHS) {
172  // Copy over the new array size
174 
175  // Copy over the contents from the other set
176  std::copy(RHS.CurArray, RHS.EndPointer(), CurArray);
177 
178  NumNonEmpty = RHS.NumNonEmpty;
180 }
181 
182 void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
183  SmallPtrSetImplBase &&RHS) {
184  if (!isSmall())
185  free(CurArray);
186  MoveHelper(SmallSize, std::move(RHS));
187 }
188 
189 void SmallPtrSetImplBase::MoveHelper(unsigned SmallSize,
190  SmallPtrSetImplBase &&RHS) {
191  assert(&RHS != this && "Self-move should be handled by the caller.");
192 
193  if (RHS.isSmall()) {
194  // Copy a small RHS rather than moving.
196  std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, CurArray);
197  } else {
198  CurArray = RHS.CurArray;
199  RHS.CurArray = RHS.SmallArray;
200  }
201 
202  // Copy the rest of the trivial members.
204  NumNonEmpty = RHS.NumNonEmpty;
206 
207  // Make the RHS small and empty.
208  RHS.CurArraySize = SmallSize;
209  assert(RHS.CurArray == RHS.SmallArray);
210  RHS.NumNonEmpty = 0;
211  RHS.NumTombstones = 0;
212 }
213 
215  if (this == &RHS) return;
216 
217  // We can only avoid copying elements if neither set is small.
218  if (!this->isSmall() && !RHS.isSmall()) {
219  std::swap(this->CurArray, RHS.CurArray);
220  std::swap(this->CurArraySize, RHS.CurArraySize);
221  std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
223  return;
224  }
225 
226  // FIXME: From here on we assume that both sets have the same small size.
227 
228  // If only RHS is small, copy the small elements into LHS and move the pointer
229  // from LHS to RHS.
230  if (!this->isSmall() && RHS.isSmall()) {
231  assert(RHS.CurArray == RHS.SmallArray);
232  std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, this->SmallArray);
233  std::swap(RHS.CurArraySize, this->CurArraySize);
234  std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
236  RHS.CurArray = this->CurArray;
237  this->CurArray = this->SmallArray;
238  return;
239  }
240 
241  // If only LHS is small, copy the small elements into RHS and move the pointer
242  // from RHS to LHS.
243  if (this->isSmall() && !RHS.isSmall()) {
244  assert(this->CurArray == this->SmallArray);
245  std::copy(this->CurArray, this->CurArray + this->NumNonEmpty,
246  RHS.SmallArray);
247  std::swap(RHS.CurArraySize, this->CurArraySize);
248  std::swap(RHS.NumNonEmpty, this->NumNonEmpty);
249  std::swap(RHS.NumTombstones, this->NumTombstones);
250  this->CurArray = RHS.CurArray;
251  RHS.CurArray = RHS.SmallArray;
252  return;
253  }
254 
255  // Both a small, just swap the small elements.
256  assert(this->isSmall() && RHS.isSmall());
257  unsigned MinNonEmpty = std::min(this->NumNonEmpty, RHS.NumNonEmpty);
258  std::swap_ranges(this->SmallArray, this->SmallArray + MinNonEmpty,
259  RHS.SmallArray);
260  if (this->NumNonEmpty > MinNonEmpty) {
261  std::copy(this->SmallArray + MinNonEmpty,
262  this->SmallArray + this->NumNonEmpty,
263  RHS.SmallArray + MinNonEmpty);
264  } else {
265  std::copy(RHS.SmallArray + MinNonEmpty, RHS.SmallArray + RHS.NumNonEmpty,
266  this->SmallArray + MinNonEmpty);
267  }
268  assert(this->CurArraySize == RHS.CurArraySize);
269  std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
271 }
static void * getTombstoneMarker()
Definition: SmallPtrSet.h:116
unsigned Log2_32_Ceil(uint32_t Value)
Log2_32_Ceil - This function returns the ceil log base 2 of the specified value, 32 if the value is z...
Definition: MathExtras.h:526
#define LLVM_UNLIKELY(EXPR)
Definition: Compiler.h:182
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:181
void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS)
unsigned NumNonEmpty
Number of elements in CurArray that contain a value or are a tombstone.
Definition: SmallPtrSet.h:71
void swap(SmallPtrSetImplBase &RHS)
swap - Swaps the elements of two sets.
unsigned CurArraySize
CurArraySize - The allocated size of CurArray, always a power of two.
Definition: SmallPtrSet.h:66
const void ** CurArray
CurArray - This is the current set of buckets.
Definition: SmallPtrSet.h:64
static void * getEmptyMarker()
Definition: SmallPtrSet.h:118
#define T
const void ** EndPointer() const
Definition: SmallPtrSet.h:124
void CopyFrom(const SmallPtrSetImplBase &RHS)
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
size_type size() const
Definition: SmallPtrSet.h:99
const void ** SmallArray
SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
Definition: SmallPtrSet.h:61
SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:586
SmallPtrSetImplBase - This is the common code shared among all the SmallPtrSet<>'s, which is almost everything.
Definition: SmallPtrSet.h:56
unsigned NumTombstones
Number of tombstones in CurArray.
Definition: SmallPtrSet.h:73
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
int * Ptr