[SmallVector] Weaken the predicate for the memcpy optimization

We don't require the type to be trivially assignable. While the standard
says that only is_trivially_copyable types may be memcpy'd, this seems
overly strict. We never assign the type, so there's no way for the type
to observe that the copy/move construction got elided. This is important
for std::pair<POD, POD>, which is not trivially assignable and probably
never will be because changing that would break ABI.

As a side-effect this no longer allows types with deleted copy/move
constructors in SmallVector. That's an unintended side-effect of
is_trivially_copyable anyways.

Shrinks Release+Asserts clang by 20k.
This commit is contained in:
Benjamin Kramer 2020-05-02 19:22:15 +02:00
parent c0f210d636
commit f7bf28b2c0
1 changed files with 14 additions and 4 deletions

View File

@ -200,9 +200,17 @@ public:
}
};
/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put method
/// implementations that are designed to work with non-POD-like T's.
template <typename T, bool = is_trivially_copyable<T>::value>
/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put
/// method implementations that are designed to work with non-trivial T's.
///
/// We approximate is_trivially_copyable with trivial move/copy construction and
/// trivial destruction. While the standard doesn't specify that you're allowed
/// copy these types with memcpy, there is no way for the type to observe this.
/// This catches the important case of std::pair<POD, POD>, which is not
/// trivially assignable.
template <typename T, bool = (is_trivially_copy_constructible<T>::value) &&
(is_trivially_move_constructible<T>::value) &&
std::is_trivially_destructible<T>::value>
class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
protected:
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
@ -290,7 +298,9 @@ void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
}
/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
/// method implementations that are designed to work with POD-like T's.
/// method implementations that are designed to work with trivially copyable
/// T's. This allows using memcpy in place of copy/move construction and
/// skipping destruction.
template <typename T>
class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
protected: