diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -1281,11 +1281,18 @@ SmallVector, Size> to_vector(R &&Range) { return {std::begin(Range), std::end(Range)}; } + template -SmallVector, - CalculateSmallVectorDefaultInlinedElements< - ValueTypeFromRangeType>::value> -to_vector(R &&Range) { +SmallVector> to_vector(R &&Range) { + return {std::begin(Range), std::end(Range)}; +} + +template +SmallVector to_vector_of(R &&Range) { + return {std::begin(Range), std::end(Range)}; +} + +template SmallVector to_vector_of(R &&Range) { return {std::begin(Range), std::end(Range)}; } diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -1345,9 +1345,8 @@ StorageType Storage, bool ShouldCreate = true); TempMDTuple cloneImpl() const { - ArrayRef Operands = operands(); - return getTemporary(getContext(), SmallVector( - Operands.begin(), Operands.end())); + return getTemporary(getContext(), + llvm::to_vector_of(operands())); } public: diff --git a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp --- a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp +++ b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -811,8 +811,7 @@ return nullptr; // Otherwise, create TBAA with the new Len - ArrayRef MDOperands = MD->operands(); - SmallVector NextNodes(MDOperands.begin(), MDOperands.end()); + auto NextNodes = to_vector_of(MD->operands()); ConstantInt *PreviousSize = mdconst::extract(NextNodes[3]); // Don't create a new MDNode if it is the same length. diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1362,10 +1362,9 @@ "Expected MDTuple when appending module flags"); if (DstValue->isDistinct()) return dyn_cast(DstValue); - ArrayRef DstOperands = DstValue->operands(); MDTuple *New = MDTuple::getDistinct( DstM.getContext(), - SmallVector(DstOperands.begin(), DstOperands.end())); + llvm::to_vector_of(DstValue->operands())); Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New}; MDNode *Flag = MDTuple::getDistinct(DstM.getContext(), FlagOps); DstModFlags->setOperand(DstIndex, Flag); diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h --- a/llvm/tools/llvm-rc/ResourceScriptStmt.h +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -817,7 +817,7 @@ VersionInfoFixed() : IsTypePresent(FtNumTypes, false) {} void setValue(VersionInfoFixedType Type, ArrayRef Value) { - FixedInfo[Type] = SmallVector(Value.begin(), Value.end()); + FixedInfo[Type] = llvm::to_vector_of(Value); IsTypePresent[Type] = true; } diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -125,7 +125,7 @@ return {}; ArrayRef BuildID(reinterpret_cast(Bytes.data()), Bytes.size()); - return SmallVector(BuildID.begin(), BuildID.end()); + return llvm::to_vector_of(BuildID); } static bool parseCommand(StringRef BinaryName, bool IsAddr2Line, diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -862,14 +862,16 @@ template class DualSmallVectorsTest; +template +static unsigned NumBuiltinElts(const SmallVector &) { + return N; +} + template class DualSmallVectorsTest> : public SmallVectorTestBase { protected: VectorT1 theVector; VectorT2 otherVector; - - template - static unsigned NumBuiltinElts(const SmallVector&) { return N; } }; typedef ::testing::Types< @@ -909,7 +911,7 @@ // 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 || + EXPECT_TRUE(NumBuiltinElts(this->otherVector) == 4 || this->theVector.data() == OrigDataPtr); // There shouldn't be any live objects any more. @@ -1134,6 +1136,94 @@ EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2})); } +TEST(SmallVectorTest, ToVector) { + { + std::vector v = {'a', 'b', 'c'}; + auto Vector = to_vector<4>(v); + ASSERT_EQ(4u, NumBuiltinElts(Vector)); + ASSERT_EQ(3u, Vector.size()); + for (size_t I = 0; I < v.size(); ++I) { + EXPECT_EQ(v[I], Vector[I]); + } + } + { + std::vector v = {'a', 'b', 'c'}; + auto Vector = to_vector(v); + ASSERT_NE(4u, NumBuiltinElts(Vector)); + ASSERT_EQ(3u, Vector.size()); + for (size_t I = 0; I < v.size(); ++I) { + EXPECT_EQ(v[I], Vector[I]); + } + } +} + +TEST(SmallVectorTest, ToVectorOf) { + struct Metadata { + int content; + bool operator==(const Metadata &RHS) const { + return content == RHS.content; + } + }; + + class MDOperand { + public: + MDOperand() = default; + MDOperand(Metadata *M) { MD = M; } + operator Metadata *() const { return get(); } + Metadata &operator*() const { return *get(); } + + private: + Metadata *get() const { return MD; } + Metadata *MD = nullptr; + }; + + Metadata m1{1}, m2{2}, m3{3}; + std::vector Operands = {MDOperand(&m1), MDOperand(&m2), + MDOperand(&m3)}; + { + llvm::SmallVector Metadatas = + llvm::to_vector_of(Operands); + + ASSERT_EQ(Operands.size(), Metadatas.size()); + for (size_t I = 0; I < Operands.size(); ++I) { + EXPECT_EQ(&(*Operands[I]), Metadatas[I]); + EXPECT_EQ(*Operands[I], *Metadatas[I]); + } + } + { + ArrayRef ArrayOperands = Operands; + llvm::SmallVector Metadatas = + llvm::to_vector_of(ArrayOperands); + + ASSERT_EQ(ArrayOperands.size(), Metadatas.size()); + for (size_t I = 0; I < ArrayOperands.size(); ++I) { + EXPECT_EQ(ArrayOperands[I], Metadatas[I]); + EXPECT_EQ(*ArrayOperands[I], *Metadatas[I]); + } + } + { + auto Metadatas = llvm::to_vector_of(Operands); + + ASSERT_EQ(Operands.size(), Metadatas.size()); + ASSERT_EQ(4u, NumBuiltinElts(Metadatas)); + for (size_t I = 0; I < Operands.size(); ++I) { + EXPECT_EQ(&(*Operands[I]), Metadatas[I]); + EXPECT_EQ(*Operands[I], *Metadatas[I]); + } + } + { + ArrayRef ArrayOperands = Operands; + auto Metadatas = llvm::to_vector_of(ArrayOperands); + + ASSERT_EQ(ArrayOperands.size(), Metadatas.size()); + ASSERT_EQ(4u, NumBuiltinElts(Metadatas)); + for (size_t I = 0; I < ArrayOperands.size(); ++I) { + EXPECT_EQ(ArrayOperands[I], Metadatas[I]); + EXPECT_EQ(*ArrayOperands[I], *Metadatas[I]); + } + } +} + template class SmallVectorReferenceInvalidationTest : public SmallVectorTestBase { protected: @@ -1143,11 +1233,6 @@ VectorT V; - template - static unsigned NumBuiltinElts(const SmallVector &) { - return N; - } - template static bool isValueType() { return std::is_same::value; } @@ -1173,7 +1258,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBack) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.push_back(V.back()); @@ -1195,7 +1280,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBackMoved) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.push_back(std::move(V.back())); @@ -1224,7 +1309,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, Resize) { auto &V = this->V; (void)V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); V.resize(N + 1, V.back()); EXPECT_EQ(N, V.back()); @@ -1239,7 +1324,7 @@ auto &V = this->V; (void)V; V.append(1, V.back()); - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); EXPECT_EQ(N, V[N - 1]); // Append enough more elements that V will grow again. This tests growing @@ -1257,7 +1342,7 @@ #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST EXPECT_DEATH(V.append(V.begin(), V.begin() + 1), this->AssertionMessage); - ASSERT_EQ(3u, this->NumBuiltinElts(V)); + ASSERT_EQ(3u, NumBuiltinElts(V)); ASSERT_EQ(3u, V.size()); V.pop_back(); ASSERT_EQ(2u, V.size()); @@ -1272,7 +1357,7 @@ // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; (void)V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); ASSERT_EQ(unsigned(N), V.size()); ASSERT_EQ(unsigned(N), V.capacity()); @@ -1372,7 +1457,7 @@ // Cover NumToInsert <= this->end() - I. V.insert(V.begin() + 1, 1, V.back()); - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); EXPECT_EQ(N, V[1]); // Cover NumToInsert > this->end() - I, inserting enough elements that V will @@ -1392,7 +1477,7 @@ EXPECT_DEATH(V.insert(V.begin(), V.begin(), V.begin() + 1), this->AssertionMessage); - ASSERT_EQ(3u, this->NumBuiltinElts(V)); + ASSERT_EQ(3u, NumBuiltinElts(V)); ASSERT_EQ(3u, V.size()); V.pop_back(); ASSERT_EQ(2u, V.size()); @@ -1406,7 +1491,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, EmplaceBack) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.emplace_back(V.back()); @@ -1435,11 +1520,6 @@ VectorT V; - template - static unsigned NumBuiltinElts(const SmallVector &) { - return N; - } - void SetUp() override { SmallVectorTestBase::SetUp(); @@ -1460,7 +1540,7 @@ TYPED_TEST(SmallVectorInternalReferenceInvalidationTest, EmplaceBack) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.emplace_back(V.back().first, V.back().second); diff --git a/llvm/unittests/Analysis/VectorUtilsTest.cpp b/llvm/unittests/Analysis/VectorUtilsTest.cpp --- a/llvm/unittests/Analysis/VectorUtilsTest.cpp +++ b/llvm/unittests/Analysis/VectorUtilsTest.cpp @@ -507,8 +507,7 @@ } bool validParams(ArrayRef Parameters) { - Shape.Parameters = - SmallVector(Parameters.begin(), Parameters.end()); + Shape.Parameters = llvm::to_vector_of(Parameters); return Shape.hasValidParameterList(); } };