[llvm] r271669 - Adding reserve and capacity methods to FoldingSet
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 3 12:31:58 PDT 2016
ah, sure - no worries then. Thanks for the explanation!
On Fri, Jun 3, 2016 at 8:55 AM, Craig, Ben <ben.craig at codeaurora.org> wrote:
> The elements are never moved or copied, as FoldingSet doesn't own the
> elements (I think intrusive_hash_set would have been a better name). The
> elements are part of a singly linked list, with the FoldingSet's buckets as
> the heads of those lists.
>
> So the publicly visible way to write the test that you describe would be
> to force a hash-table collision, but not a full hash-value collision. The
> last element that collided would have a non-null NextInFoldingSetBucket
> member. When you rehash / reserve, if the unmasked parts of the hash-value
> start to differ, then you would get a null NextInFoldingSetBucket member
> after the rehash.
>
> Making a partial hash-value collision seems like a lot of trouble. It
> would be easier if the hashing algorithm could be chosen, but most of that
> is baked into the implementation of FoldingSetNodeID.
> On 6/3/2016 10:30 AM, David Blaikie wrote:
>
> Would it be worth adding a test that tests the functionality of reserve?
> (start with a default constructed container, add some number of elements
> and demonstrate that at some point a reallocation occurs and elements are
> moved (I assume they're moved, right? like move-semantic moved, or copied,
> not just buffers passed around) and then do the same thing but with a
> reserve call before adding any elements and demonstrate that elements are
> not moved around)
>
> On Fri, Jun 3, 2016 at 6:54 AM, Ben Craig via llvm-commits <
> <llvm-commits at lists.llvm.org>llvm-commits at lists.llvm.org> wrote:
>
>> Author: bcraig
>> Date: Fri Jun 3 08:54:48 2016
>> New Revision: 271669
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=271669&view=rev
>> Log:
>> Adding reserve and capacity methods to FoldingSet
>>
>> http://reviews.llvm.org/D20930
>>
>> Modified:
>> llvm/trunk/include/llvm/ADT/FoldingSet.h
>> llvm/trunk/lib/Support/FoldingSet.cpp
>> llvm/trunk/unittests/ADT/FoldingSet.cpp
>>
>> Modified: llvm/trunk/include/llvm/ADT/FoldingSet.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/FoldingSet.h?rev=271669&r1=271668&r2=271669&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/ADT/FoldingSet.h (original)
>> +++ llvm/trunk/include/llvm/ADT/FoldingSet.h Fri Jun 3 08:54:48 2016
>> @@ -180,11 +180,21 @@ public:
>> /// empty - Returns true if there are no nodes in the folding set.
>> bool empty() const { return NumNodes == 0; }
>>
>> + void reserve(unsigned EltCount);
>> + unsigned capacity() {
>> + // We allow a load factor of up to 2.0,
>> + // so that means our capacity is NumBuckets * 2
>> + return NumBuckets * 2;
>> + }
>> +
>> private:
>> /// GrowHashTable - Double the size of the hash table and rehash
>> everything.
>> - ///
>> void GrowHashTable();
>>
>> + /// GrowBucketCount - resize the hash table and rehash everything.
>> + /// NewBucketCount must be a power of two, and must be greater than
>> the old
>> + /// bucket count.
>> + void GrowBucketCount(unsigned NewBucketCount);
>> protected:
>> /// GetNodeProfile - Instantiations of the FoldingSet template
>> implement
>> /// this function to gather data bits for the given node.
>>
>> Modified: llvm/trunk/lib/Support/FoldingSet.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/FoldingSet.cpp?rev=271669&r1=271668&r2=271669&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Support/FoldingSet.cpp (original)
>> +++ llvm/trunk/lib/Support/FoldingSet.cpp Fri Jun 3 08:54:48 2016
>> @@ -266,12 +266,12 @@ void FoldingSetImpl::clear() {
>> NumNodes = 0;
>> }
>>
>> -/// GrowHashTable - Double the size of the hash table and rehash
>> everything.
>> -///
>> -void FoldingSetImpl::GrowHashTable() {
>> +void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) {
>> + assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set
>> with GrowBucketCount");
>> + assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!");
>> void **OldBuckets = Buckets;
>> unsigned OldNumBuckets = NumBuckets;
>> - NumBuckets <<= 1;
>> + NumBuckets = NewBucketCount;
>>
>> // Clear out new buckets.
>> Buckets = AllocateBuckets(NumBuckets);
>> @@ -298,6 +298,21 @@ void FoldingSetImpl::GrowHashTable() {
>> free(OldBuckets);
>> }
>>
>> +/// GrowHashTable - Double the size of the hash table and rehash
>> everything.
>> +///
>> +void FoldingSetImpl::GrowHashTable() {
>> + GrowBucketCount(NumBuckets * 2);
>> +}
>> +
>> +void FoldingSetImpl::reserve(unsigned EltCount) {
>> + // This will give us somewhere between EltCount / 2 and
>> + // EltCount buckets. This puts us in the load factor
>> + // range of 1.0 - 2.0.
>> + if(EltCount < capacity())
>> + return;
>> + GrowBucketCount(PowerOf2Floor(EltCount));
>> +}
>> +
>> /// FindNodeOrInsertPos - Look up the node specified by ID. If it
>> exists,
>> /// return it. If not, return the insertion token that will make
>> insertion
>> /// faster.
>> @@ -330,7 +345,7 @@ FoldingSetImpl::Node
>> void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
>> assert(!N->getNextInBucket());
>> // Do we need to grow the hashtable?
>> - if (NumNodes+1 > NumBuckets*2) {
>> + if (NumNodes+1 > capacity()) {
>> GrowHashTable();
>> FoldingSetNodeID TempID;
>> InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets,
>> NumBuckets);
>>
>> Modified: llvm/trunk/unittests/ADT/FoldingSet.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/FoldingSet.cpp?rev=271669&r1=271668&r2=271669&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/unittests/ADT/FoldingSet.cpp (original)
>> +++ llvm/trunk/unittests/ADT/FoldingSet.cpp Fri Jun 3 08:54:48 2016
>> @@ -35,5 +35,138 @@ TEST(FoldingSetTest, UnalignedStringTest
>> EXPECT_EQ(a.ComputeHash(), b.ComputeHash());
>> }
>>
>> +struct TrivialPair : public FoldingSetNode {
>> + unsigned Key = 0;
>> + unsigned Value = 0;
>> + TrivialPair(unsigned K, unsigned V) : FoldingSetNode(), Key(K),
>> Value(V) {}
>> +
>> + void Profile(FoldingSetNodeID &ID) const {
>> + ID.AddInteger(Key);
>> + ID.AddInteger(Value);
>> + }
>> +};
>> +
>> +TEST(FoldingSetTest, IDComparison) {
>> + FoldingSet<TrivialPair> Trivial;
>> +
>> + TrivialPair T(99, 42);
>> + Trivial.InsertNode(&T);
>> +
>> + void *InsertPos = nullptr;
>> + FoldingSetNodeID ID;
>> + T.Profile(ID);
>> + TrivialPair *N = Trivial.FindNodeOrInsertPos(ID, InsertPos);
>> + EXPECT_EQ(&T, N);
>> + EXPECT_EQ(nullptr, InsertPos);
>> +}
>> +
>> +TEST(FoldingSetTest, MissedIDComparison) {
>> + FoldingSet<TrivialPair> Trivial;
>> +
>> + TrivialPair S(100, 42);
>> + TrivialPair T(99, 42);
>> + Trivial.InsertNode(&T);
>> +
>> + void *InsertPos = nullptr;
>> + FoldingSetNodeID ID;
>> + S.Profile(ID);
>> + TrivialPair *N = Trivial.FindNodeOrInsertPos(ID, InsertPos);
>> + EXPECT_EQ(nullptr, N);
>> + EXPECT_NE(nullptr, InsertPos);
>> +}
>> +
>> +TEST(FoldingSetTest, RemoveNodeThatIsPresent) {
>> + FoldingSet<TrivialPair> Trivial;
>> +
>> + TrivialPair T(99, 42);
>> + Trivial.InsertNode(&T);
>> + EXPECT_EQ(Trivial.size(), 1U);
>> +
>> + bool WasThere = Trivial.RemoveNode(&T);
>> + EXPECT_TRUE(WasThere);
>> + EXPECT_EQ(0U, Trivial.size());
>> +}
>> +
>> +TEST(FoldingSetTest, RemoveNodeThatIsAbsent) {
>> + FoldingSet<TrivialPair> Trivial;
>> +
>> + TrivialPair T(99, 42);
>> + bool WasThere = Trivial.RemoveNode(&T);
>> + EXPECT_FALSE(WasThere);
>> + EXPECT_EQ(0U, Trivial.size());
>> +}
>> +
>> +TEST(FoldingSetTest, GetOrInsertInserting) {
>> + FoldingSet<TrivialPair> Trivial;
>> +
>> + TrivialPair T(99, 42);
>> + TrivialPair *N = Trivial.GetOrInsertNode(&T);
>> + EXPECT_EQ(&T, N);
>> +}
>> +
>> +TEST(FoldingSetTest, GetOrInsertGetting) {
>> + FoldingSet<TrivialPair> Trivial;
>> +
>> + TrivialPair T(99, 42);
>> + TrivialPair T2(99, 42);
>> + Trivial.InsertNode(&T);
>> + TrivialPair *N = Trivial.GetOrInsertNode(&T2);
>> + EXPECT_EQ(&T, N);
>> +}
>> +
>> +TEST(FoldingSetTest, InsertAtPos) {
>> + FoldingSet<TrivialPair> Trivial;
>> +
>> + void *InsertPos = nullptr;
>> + TrivialPair Finder(99, 42);
>> + FoldingSetNodeID ID;
>> + Finder.Profile(ID);
>> + Trivial.FindNodeOrInsertPos(ID, InsertPos);
>> +
>> + TrivialPair T(99, 42);
>> + Trivial.InsertNode(&T, InsertPos);
>> + EXPECT_EQ(1U, Trivial.size());
>> +}
>> +
>> +TEST(FoldingSetTest, EmptyIsTrue) {
>> + FoldingSet<TrivialPair> Trivial;
>> + EXPECT_TRUE(Trivial.empty());
>> +}
>> +
>> +TEST(FoldingSetTest, EmptyIsFalse) {
>> + FoldingSet<TrivialPair> Trivial;
>> + TrivialPair T(99, 42);
>> + Trivial.InsertNode(&T);
>> + EXPECT_FALSE(Trivial.empty());
>> +}
>> +
>> +TEST(FoldingSetTest, ClearOnEmpty) {
>> + FoldingSet<TrivialPair> Trivial;
>> + Trivial.clear();
>> + EXPECT_TRUE(Trivial.empty());
>> +}
>> +
>> +TEST(FoldingSetTest, ClearOnNonEmpty) {
>> + FoldingSet<TrivialPair> Trivial;
>> + TrivialPair T(99, 42);
>> + Trivial.InsertNode(&T);
>> + Trivial.clear();
>> + EXPECT_TRUE(Trivial.empty());
>> +}
>> +
>> +TEST(FoldingSetTest, CapacityLargerThanReserve) {
>> + FoldingSet<TrivialPair> Trivial;
>> + auto OldCapacity = Trivial.capacity();
>> + Trivial.reserve(OldCapacity + 1);
>> + EXPECT_GE(Trivial.capacity(), OldCapacity + 1);
>> +}
>> +
>> +TEST(FoldingSetTest, SmallReserveChangesNothing) {
>> + FoldingSet<TrivialPair> Trivial;
>> + auto OldCapacity = Trivial.capacity();
>> + Trivial.reserve(OldCapacity - 1);
>> + EXPECT_EQ(Trivial.capacity(), OldCapacity);
>> +}
>> +
>> }
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
>
> --
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160603/d65d1594/attachment.html>
More information about the llvm-commits
mailing list