[llvm] r226899 - [ADT] Add move operations to SmallVector<T, N> from SmallVectorImpl<T>.
David Blaikie
dblaikie at gmail.com
Fri Jan 23 11:06:26 PST 2015
On Fri, Jan 23, 2015 at 10:57 AM, Lang Hames <lhames at gmail.com> wrote:
> Hi Dave,
>
> I didn't delve into the code to check, I just cribbed from the existing
> implementations. My inclination is that that check should be pushed down
> into SmallVectorImpl's methods though.
>
*frysquint* r40983.
Not clear whether the win is in avoiding the function call entirely, or
just in having the short-cut before the rest of the assignment
implementation.
(+Chris for history. +Chandler for inlining)
>
> - Lang.
>
> On Fri, Jan 23, 2015 at 12:02 AM, David Blaikie <dblaikie at gmail.com>
> wrote:
>
>>
>>
>> On Thu, Jan 22, 2015 at 10:25 PM, Lang Hames <lhames at gmail.com> wrote:
>>
>>> Author: lhames
>>> Date: Fri Jan 23 00:25:17 2015
>>> New Revision: 226899
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=226899&view=rev
>>> Log:
>>> [ADT] Add move operations to SmallVector<T,N> from SmallVectorImpl<T>.
>>>
>>> This makes it possible to move between SmallVectors of different sizes.
>>>
>>> Thanks to Dave Blaikie and Duncan Smith for patch feedback.
>>>
>>> Modified:
>>> llvm/trunk/include/llvm/ADT/SmallVector.h
>>> llvm/trunk/unittests/ADT/SmallVectorTest.cpp
>>>
>>> Modified: llvm/trunk/include/llvm/ADT/SmallVector.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=226899&r1=226898&r2=226899&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/ADT/SmallVector.h (original)
>>> +++ llvm/trunk/include/llvm/ADT/SmallVector.h Fri Jan 23 00:25:17 2015
>>> @@ -921,6 +921,17 @@ public:
>>> SmallVectorImpl<T>::operator=(::std::move(RHS));
>>> return *this;
>>> }
>>> +
>>> + SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
>>> + if (!RHS.empty())
>>>
>>
>> Is this ^ check necessary/useful for some reason? (why in the ctor, but
>> not in the assignment operator?)
>>
>>
>>> + SmallVectorImpl<T>::operator=(::std::move(RHS));
>>> + }
>>> +
>>> + const SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
>>> + SmallVectorImpl<T>::operator=(::std::move(RHS));
>>> + return *this;
>>> + }
>>> +
>>> };
>>>
>>> template<typename T, unsigned N>
>>>
>>> Modified: llvm/trunk/unittests/ADT/SmallVectorTest.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/SmallVectorTest.cpp?rev=226899&r1=226898&r2=226899&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/unittests/ADT/SmallVectorTest.cpp (original)
>>> +++ llvm/trunk/unittests/ADT/SmallVectorTest.cpp Fri Jan 23 00:25:17 2015
>>> @@ -153,17 +153,14 @@ LLVM_ATTRIBUTE_USED void CompileTest() {
>>> V.resize(42);
>>> }
>>>
>>> -// Test fixture class
>>> -template <typename VectorT>
>>> -class SmallVectorTest : public testing::Test {
>>> +class SmallVectorTestBase : public testing::Test {
>>> protected:
>>> - VectorT theVector;
>>> - VectorT otherVector;
>>>
>>> void SetUp() {
>>> Constructable::reset();
>>> }
>>>
>>> + template <typename VectorT>
>>> void assertEmpty(VectorT & v) {
>>> // Size tests
>>> EXPECT_EQ(0u, v.size());
>>> @@ -173,7 +170,8 @@ protected:
>>> EXPECT_TRUE(v.begin() == v.end());
>>> }
>>>
>>> - // Assert that theVector contains the specified values, in order.
>>> + // Assert that v contains the specified values, in order.
>>> + template <typename VectorT>
>>> void assertValuesInOrder(VectorT & v, size_t size, ...) {
>>> EXPECT_EQ(size, v.size());
>>>
>>> @@ -188,6 +186,7 @@ protected:
>>> }
>>>
>>> // Generate a sequence of values to initialize the vector.
>>> + template <typename VectorT>
>>> void makeSequence(VectorT & v, int start, int end) {
>>> for (int i = start; i <= end; ++i) {
>>> v.push_back(Constructable(i));
>>> @@ -195,6 +194,15 @@ protected:
>>> }
>>> };
>>>
>>> +// Test fixture class
>>> +template <typename VectorT>
>>> +class SmallVectorTest : public SmallVectorTestBase {
>>> +protected:
>>> + VectorT theVector;
>>> + VectorT otherVector;
>>> +};
>>> +
>>> +
>>> typedef ::testing::Types<SmallVector<Constructable, 0>,
>>> SmallVector<Constructable, 1>,
>>> SmallVector<Constructable, 2>,
>>> @@ -664,6 +672,67 @@ TYPED_TEST(SmallVectorTest, IteratorTest
>>> this->theVector.insert(this->theVector.end(), L.begin(), L.end());
>>> }
>>>
>>> +template <typename InvalidType> class DualSmallVectorsTest;
>>> +
>>> +template <typename VectorT1, typename VectorT2>
>>> +class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>> : public
>>> SmallVectorTestBase {
>>> +protected:
>>> + VectorT1 theVector;
>>> + VectorT2 otherVector;
>>> +
>>> + template <typename T, unsigned N>
>>> + static unsigned NumBuiltinElts(const SmallVector<T, N>&) { return N; }
>>> +};
>>> +
>>> +typedef ::testing::Types<
>>> + // Small mode -> Small mode.
>>> + std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable,
>>> 4>>,
>>> + // Small mode -> Big mode.
>>> + std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable,
>>> 2>>,
>>> + // Big mode -> Small mode.
>>> + std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable,
>>> 4>>,
>>> + // Big mode -> Big mode.
>>> + std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable,
>>> 2>>
>>> + > DualSmallVectorTestTypes;
>>> +
>>> +TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes);
>>> +
>>> +TYPED_TEST(DualSmallVectorsTest, MoveAssignment) {
>>> + SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
>>> +
>>> + // Set up our vector with four elements.
>>> + for (unsigned I = 0; I < 4; ++I)
>>> + this->otherVector.push_back(Constructable(I));
>>> +
>>> + const Constructable *OrigDataPtr = this->otherVector.data();
>>> +
>>> + // Move-assign from the other vector.
>>> + this->theVector =
>>> +
>>> std::move(static_cast<SmallVectorImpl<Constructable>&>(this->otherVector));
>>> +
>>> + // Make sure we have the right result.
>>> + this->assertValuesInOrder(this->theVector, 4u, 0, 1, 2, 3);
>>> +
>>> + // Make sure the # of constructor/destructor calls line up. There
>>> + // are two live objects after clearing the other vector.
>>> + this->otherVector.clear();
>>> + EXPECT_EQ(Constructable::getNumConstructorCalls()-4,
>>> + Constructable::getNumDestructorCalls());
>>> +
>>> + // If the source vector (otherVector) was in small-mode, assert that
>>> we just
>>> + // moved the data pointer over.
>>> + EXPECT_TRUE(this->NumBuiltinElts(this->otherVector) == 4 ||
>>> + this->theVector.data() == OrigDataPtr);
>>> +
>>> + // There shouldn't be any live objects any more.
>>> + this->theVector.clear();
>>> + EXPECT_EQ(Constructable::getNumConstructorCalls(),
>>> + Constructable::getNumDestructorCalls());
>>> +
>>> + // We shouldn't have copied anything in this whole process.
>>> + EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0);
>>> +}
>>> +
>>> struct notassignable {
>>> int &x;
>>> notassignable(int &x) : x(x) {}
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150123/380f5724/attachment.html>
More information about the llvm-commits
mailing list