Mehdi AMINI via llvm-dev
2020-Dec-01 22:39 UTC
[llvm-dev] RFC: [SmallVector] Adding SVec<T> and Vec<T> convenience wrappers.
On Tue, Dec 1, 2020 at 2:19 PM Chris Lattner via llvm-dev < llvm-dev at lists.llvm.org> wrote:> On Nov 17, 2020, at 1:42 PM, David Blaikie <dblaikie at gmail.com> wrote: >> >> Thoughts/suggestions: >> - Adding the default seems very reasonable to me, and I think that 64 >> bytes is a good default. I think you should change the behavior so that >> SmallVector<LargeThing> defaults to a single inline element instead of zero >> though. Perhaps generate a static_assert when it is crazy large. >> >> >> Out of curiosity: Why a single rather than zero? >> >> >> My rationale for this is basically that SmallVector is typically used for >> the case when you want to avoid an out-of-line allocation for a small >> number of elements, this was the reason it was created. While there is >> some performance benefits of SmallVector<T,0> over std::vector<> they are >> almost trivial. >> >> >> The performance benefits aren't trivial. >> >> std::vector grow operations will refuse to use std::move for some T, a >> pessimization required by its exception guarantees, even if you're building >> with `-fno-exceptions`. We had a massive compile-time problem in 2016 >> related to this that I fixed with 3c406c2da52302eb5cced431373f240b9c037841 >> by switching to SmallVector<T,0>. You can see the history in r338071 / >> 0f81faed05c3c7c1fbaf6af402411c99d715cf56. >> > > That issue, at least, is fixable without switching from std::vector just > by adding noexcept to the appropriate user-defined move constructors. > > > Sure, once we’ve added noexcept to all types in LLVM/Clang/etc. That’s a > pretty long tail though; a lot of work for relatively little gain given > that we don’t care about exceptions anyway and we have an optimized vector > implementation in tree. > > > Can you spell this out for me? Why do we need noexcept if we’re building > with -fno-exceptions? What is going on here? >It isn't clear to me that -fno-exceptions can get the same benefit as noexcept for code that is written with exceptions in mind (I think https://stackoverflow.com/questions/61417534/can-stdvectort-use-ts-move-constructor-if-exceptions-are-disabled explains some of it). While it is possible to write a library that optimizes for -fno-exceptions, I am not sure it would be standard-compliant for the STL to do so (and it'd be anyway another code path that the one written in term of `std::move_if_noexcept`). Does it make sense or did you see it differently with your question? -- Mehdi -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201201/ebcfc472/attachment.html>
Mehdi AMINI via llvm-dev
2020-Dec-01 22:52 UTC
[llvm-dev] RFC: [SmallVector] Adding SVec<T> and Vec<T> convenience wrappers.
On Tue, Dec 1, 2020 at 2:39 PM Mehdi AMINI <joker.eph at gmail.com> wrote:> > > On Tue, Dec 1, 2020 at 2:19 PM Chris Lattner via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > >> On Nov 17, 2020, at 1:42 PM, David Blaikie <dblaikie at gmail.com> wrote: >>> >>> Thoughts/suggestions: >>> - Adding the default seems very reasonable to me, and I think that 64 >>> bytes is a good default. I think you should change the behavior so that >>> SmallVector<LargeThing> defaults to a single inline element instead of zero >>> though. Perhaps generate a static_assert when it is crazy large. >>> >>> >>> Out of curiosity: Why a single rather than zero? >>> >>> >>> My rationale for this is basically that SmallVector is typically used >>> for the case when you want to avoid an out-of-line allocation for a small >>> number of elements, this was the reason it was created. While there is >>> some performance benefits of SmallVector<T,0> over std::vector<> they are >>> almost trivial. >>> >>> >>> The performance benefits aren't trivial. >>> >>> std::vector grow operations will refuse to use std::move for some T, a >>> pessimization required by its exception guarantees, even if you're building >>> with `-fno-exceptions`. We had a massive compile-time problem in 2016 >>> related to this that I fixed with 3c406c2da52302eb5cced431373f240b9c037841 >>> by switching to SmallVector<T,0>. You can see the history in r338071 / >>> 0f81faed05c3c7c1fbaf6af402411c99d715cf56. >>> >> >> That issue, at least, is fixable without switching from std::vector just >> by adding noexcept to the appropriate user-defined move constructors. >> >> >> Sure, once we’ve added noexcept to all types in LLVM/Clang/etc. That’s a >> pretty long tail though; a lot of work for relatively little gain given >> that we don’t care about exceptions anyway and we have an optimized vector >> implementation in tree. >> >> >> Can you spell this out for me? Why do we need noexcept if we’re building >> with -fno-exceptions? What is going on here? >> > > It isn't clear to me that -fno-exceptions can get the same benefit as > noexcept for code that is written with exceptions in mind (I think > https://stackoverflow.com/questions/61417534/can-stdvectort-use-ts-move-constructor-if-exceptions-are-disabled > explains some of it). > > While it is possible to write a library that optimizes > for -fno-exceptions, I am not sure it would be standard-compliant for the > STL to do so (and it'd be anyway another code path that the one written in > term of `std::move_if_noexcept`). > > Does it make sense or did you see it differently with your question? > >After digging a bit, I found that libcxx was changed last year to optimize with moving in std::vector when -fno-exceptions is present : https://reviews.llvm.org/D62228 That means that a copy-only class can't be used in vector anymore in clang-10 but it was possible in clang-9 (but only with -fno-exceptions): https://godbolt.org/z/M54bqn -- Mehdi -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201201/1a68a836/attachment.html>