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 @@ -978,6 +978,43 @@ return {std::begin(Range), std::end(Range)}; } +/// Parameter controlling the default number of inlined elements for SVec. +/// +/// We guarantee that `sizeof(SVec) <= kSVecMaxSizeof`. +constexpr size_t kSVecMaxSizeof = 64; +template constexpr size_t calculateSVecInlineElements() { + // Discount the size of the header itself when calculating the maximum inline + // bytes. + size_t MaxInlineBytes = kSVecMaxSizeof - sizeof(SmallVectorImpl); + return MaxInlineBytes / sizeof(ElementTy); +} + +/// SVec is a convenience wrapper around SmallVector with a default number of +/// inlined elements. +/// +/// One major reason to use SVec over SmallVector is convenience -- there is no +/// need to choose the number of inlined elements, or to write that number in +/// the type. Also, SVec is a shorter name than SmallVector which helps as well. +/// +/// SVec adjusts the number of inlined elements with a policy that bounds the +/// total `sizeof(SVec)` to never exceed a fixed size (currently 64 bytes). +/// This prevents a number of the most pathological cases of SmallVector usage. +/// For example, `SVec>>` works fine and doesn't result in an +/// excessive `sizeof`. +/// +/// For small types like `char`, the number of inlined elements will be larger. +/// For types like large structs, the number of inlined elements will be +/// smaller, including possibly having zero inlined elements in the extreme +/// case! +/// +/// Over time, we have found that most choices of the number of inlined elements +/// for SmallVector are chosen semi-arbitrarily or cargo-culted. It is expected +/// that by tuning SVec default sizes in aggregate by adjusting the policy here, +/// we can realize codebase-wide gains that would not be measurable if done +/// by tuning individual SmallVector sizes across the codebase. +template +using SVec = SmallVector()>; + } // end namespace llvm namespace std { 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 @@ -999,4 +999,15 @@ EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2})); } +struct BigElementType { + char Arr[10000] = {0}; +}; +template struct TestSVecSizeof { + static_assert(sizeof(SVec) <= kSVecMaxSizeof, ""); +}; +using instantiateTestSVecSizeof = + ::testing::Types, TestSVecSizeof, + TestSVecSizeof, TestSVecSizeof, + TestSVecSizeof, TestSVecSizeof>; + } // end namespace