Relocation (= move+destroy)
Marc Glisse
marc.glisse@inria.fr
Sat Sep 1 15:00:00 GMT 2018
Hello,
this patch passed bootstrap+regtest on powerpc64le-unknown-linux-gnu.
The main idea is manually performing loop fusion when we see 2 consecutive
loops where the first moves data from A to B, and the second destroys the
same elements in A.
This is beneficial because there is one loop fewer (as usual with loop
fusion), but also because the move constructor and the destructor can
combine relatively well for several types. I performed some simple tests
on std::vector<std::string>, and for a loop that just emplace_back many
empty strings, I see a performance gain close to 20%. With not-small
strings, I am still seeing a noticable gain (maybe 10%? The noise makes it
hard to be precise).
I had to add a special case for trivial types, using memmove, to avoid
perf regressions, since relocation takes precedence over the old path that
is specialized to call memmove.
_GLIBCXX_ASAN_ANNOTATE_REINIT: I am not familiar with those annotations.
It was convenient in one function to move this annotation after _Destroy,
to reduce code duplication. For consistency, I did the same in the whole
file. As far as I understand, the macro makes it ok to access memory
between _M_finish and _M_end_of_storage, and at the end of the block marks
again the region after the new _M_finish as protected. Since _Destroy
should stop at _M_finish, moving the macro looks safe. But maybe the
position of the macro was chosen to reduce needless checking in ASAN?
It might be possible to introduce some helpers that do relocate if
noexcept and copy otherwise, but it is much less convenient than for
move_if_noexcept, because they don't want to execute the destructors at
the same point, so we might also want a destroy_if_no_relocate to go with
it...
The exact form of the relocate functions is whatever I had when things
started working, it is probably not that important as long as we don't
document them. I had a _n version taking a size, but I ended up not using
it, so I removed it.
The change is limited to C++17+, because I felt like using if constexpr.
Actually, I think g++ accepts if constexpr in C++11 with a warning (ok in
a system header), I don't remember if I ended up using any other recent
features...
Possible future stuff:
* use relocation in more places: there should be 1 or 2 places left in
vector, deque may also be a good candidate, I didn't look elsewhere.
* specialize relocation for some types (maybe deque?) where it can be
noexcept, possibly even trivial, whereas the move constructor cannot. If
we do that, we may want to specialize for pair/tuple/array as well, in
case one of the members is specialized.
2018-09-01 Marc Glisse <marc.glisse@inria.fr>
PR libstdc++/87106
* include/bits/alloc_traits.h (_S_construct, _S_destroy, construct,
destroy): Add noexcept specification.
* include/bits/allocator.h (construct, destroy): Likewise.
* include/ext/alloc_traits.h (construct, destroy): Likewise.
* include/ext/malloc_allocator.h (construct, destroy): Likewise.
* include/ext/new_allocator.h (construct, destroy): Likewise.
* include/bits/stl_uninitialized.h (__relocate, __relocate_a,
__relocate_a_1): New functions.
(__is_trivially_relocatable): New class.
* include/bits/stl_vector.h (__use_relocate): New static member.
* include/bits/vector.tcc (reserve, _M_realloc_insert,
_M_default_append): Use __relocate_a.
(reserve, _M_assign_aux, _M_realloc_insert, _M_fill_insert,
_M_default_append, _M_range_insert): Move _GLIBCXX_ASAN_ANNOTATE_REINIT
after _Destroy.
--
Marc Glisse
-------------- next part --------------
A non-text attachment was scrubbed...
Name: reloc.patch
Type: text/x-diff
Size: 23955 bytes
Desc:
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20180901/c3c29f22/attachment.bin>
More information about the Libstdc++
mailing list