llvm.org GIT mirror llvm / 531b69a
Adding reserve and capacity methods to FoldingSet http://reviews.llvm.org/D20930 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271669 91177308-0d34-0410-b5e6-96231b3b80d8 Ben Craig 3 years ago
3 changed file(s) with 164 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
179179 /// empty - Returns true if there are no nodes in the folding set.
180180 bool empty() const { return NumNodes == 0; }
181181
182 void reserve(unsigned EltCount);
183 unsigned capacity() {
184 // We allow a load factor of up to 2.0,
185 // so that means our capacity is NumBuckets * 2
186 return NumBuckets * 2;
187 }
188
182189 private:
183190 /// GrowHashTable - Double the size of the hash table and rehash everything.
184 ///
185191 void GrowHashTable();
186192
193 /// GrowBucketCount - resize the hash table and rehash everything.
194 /// NewBucketCount must be a power of two, and must be greater than the old
195 /// bucket count.
196 void GrowBucketCount(unsigned NewBucketCount);
187197 protected:
188198 /// GetNodeProfile - Instantiations of the FoldingSet template implement
189199 /// this function to gather data bits for the given node.
265265 NumNodes = 0;
266266 }
267267
268 /// GrowHashTable - Double the size of the hash table and rehash everything.
269 ///
270 void FoldingSetImpl::GrowHashTable() {
268 void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) {
269 assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount");
270 assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!");
271271 void **OldBuckets = Buckets;
272272 unsigned OldNumBuckets = NumBuckets;
273 NumBuckets <<= 1;
273 NumBuckets = NewBucketCount;
274274
275275 // Clear out new buckets.
276276 Buckets = AllocateBuckets(NumBuckets);
297297 free(OldBuckets);
298298 }
299299
300 /// GrowHashTable - Double the size of the hash table and rehash everything.
301 ///
302 void FoldingSetImpl::GrowHashTable() {
303 GrowBucketCount(NumBuckets * 2);
304 }
305
306 void FoldingSetImpl::reserve(unsigned EltCount) {
307 // This will give us somewhere between EltCount / 2 and
308 // EltCount buckets. This puts us in the load factor
309 // range of 1.0 - 2.0.
310 if(EltCount < capacity())
311 return;
312 GrowBucketCount(PowerOf2Floor(EltCount));
313 }
314
300315 /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
301316 /// return it. If not, return the insertion token that will make insertion
302317 /// faster.
329344 void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
330345 assert(!N->getNextInBucket());
331346 // Do we need to grow the hashtable?
332 if (NumNodes+1 > NumBuckets*2) {
347 if (NumNodes+1 > capacity()) {
333348 GrowHashTable();
334349 FoldingSetNodeID TempID;
335350 InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets);
3434 EXPECT_EQ(a.ComputeHash(), b.ComputeHash());
3535 }
3636
37 struct TrivialPair : public FoldingSetNode {
38 unsigned Key = 0;
39 unsigned Value = 0;
40 TrivialPair(unsigned K, unsigned V) : FoldingSetNode(), Key(K), Value(V) {}
41
42 void Profile(FoldingSetNodeID &ID) const {
43 ID.AddInteger(Key);
44 ID.AddInteger(Value);
45 }
46 };
47
48 TEST(FoldingSetTest, IDComparison) {
49 FoldingSet Trivial;
50
51 TrivialPair T(99, 42);
52 Trivial.InsertNode(&T);
53
54 void *InsertPos = nullptr;
55 FoldingSetNodeID ID;
56 T.Profile(ID);
57 TrivialPair *N = Trivial.FindNodeOrInsertPos(ID, InsertPos);
58 EXPECT_EQ(&T, N);
59 EXPECT_EQ(nullptr, InsertPos);
3760 }
3861
62 TEST(FoldingSetTest, MissedIDComparison) {
63 FoldingSet Trivial;
64
65 TrivialPair S(100, 42);
66 TrivialPair T(99, 42);
67 Trivial.InsertNode(&T);
68
69 void *InsertPos = nullptr;
70 FoldingSetNodeID ID;
71 S.Profile(ID);
72 TrivialPair *N = Trivial.FindNodeOrInsertPos(ID, InsertPos);
73 EXPECT_EQ(nullptr, N);
74 EXPECT_NE(nullptr, InsertPos);
75 }
76
77 TEST(FoldingSetTest, RemoveNodeThatIsPresent) {
78 FoldingSet Trivial;
79
80 TrivialPair T(99, 42);
81 Trivial.InsertNode(&T);
82 EXPECT_EQ(Trivial.size(), 1U);
83
84 bool WasThere = Trivial.RemoveNode(&T);
85 EXPECT_TRUE(WasThere);
86 EXPECT_EQ(0U, Trivial.size());
87 }
88
89 TEST(FoldingSetTest, RemoveNodeThatIsAbsent) {
90 FoldingSet Trivial;
91
92 TrivialPair T(99, 42);
93 bool WasThere = Trivial.RemoveNode(&T);
94 EXPECT_FALSE(WasThere);
95 EXPECT_EQ(0U, Trivial.size());
96 }
97
98 TEST(FoldingSetTest, GetOrInsertInserting) {
99 FoldingSet Trivial;
100
101 TrivialPair T(99, 42);
102 TrivialPair *N = Trivial.GetOrInsertNode(&T);
103 EXPECT_EQ(&T, N);
104 }
105
106 TEST(FoldingSetTest, GetOrInsertGetting) {
107 FoldingSet Trivial;
108
109 TrivialPair T(99, 42);
110 TrivialPair T2(99, 42);
111 Trivial.InsertNode(&T);
112 TrivialPair *N = Trivial.GetOrInsertNode(&T2);
113 EXPECT_EQ(&T, N);
114 }
115
116 TEST(FoldingSetTest, InsertAtPos) {
117 FoldingSet Trivial;
118
119 void *InsertPos = nullptr;
120 TrivialPair Finder(99, 42);
121 FoldingSetNodeID ID;
122 Finder.Profile(ID);
123 Trivial.FindNodeOrInsertPos(ID, InsertPos);
124
125 TrivialPair T(99, 42);
126 Trivial.InsertNode(&T, InsertPos);
127 EXPECT_EQ(1U, Trivial.size());
128 }
129
130 TEST(FoldingSetTest, EmptyIsTrue) {
131 FoldingSet Trivial;
132 EXPECT_TRUE(Trivial.empty());
133 }
134
135 TEST(FoldingSetTest, EmptyIsFalse) {
136 FoldingSet Trivial;
137 TrivialPair T(99, 42);
138 Trivial.InsertNode(&T);
139 EXPECT_FALSE(Trivial.empty());
140 }
141
142 TEST(FoldingSetTest, ClearOnEmpty) {
143 FoldingSet Trivial;
144 Trivial.clear();
145 EXPECT_TRUE(Trivial.empty());
146 }
147
148 TEST(FoldingSetTest, ClearOnNonEmpty) {
149 FoldingSet Trivial;
150 TrivialPair T(99, 42);
151 Trivial.InsertNode(&T);
152 Trivial.clear();
153 EXPECT_TRUE(Trivial.empty());
154 }
155
156 TEST(FoldingSetTest, CapacityLargerThanReserve) {
157 FoldingSet Trivial;
158 auto OldCapacity = Trivial.capacity();
159 Trivial.reserve(OldCapacity + 1);
160 EXPECT_GE(Trivial.capacity(), OldCapacity + 1);
161 }
162
163 TEST(FoldingSetTest, SmallReserveChangesNothing) {
164 FoldingSet Trivial;
165 auto OldCapacity = Trivial.capacity();
166 Trivial.reserve(OldCapacity - 1);
167 EXPECT_EQ(Trivial.capacity(), OldCapacity);
168 }
169
170 }
171