[PATCH 4/4] libstdc++: Rearrange some range adaptors' data members
Jonathan Wakely
jwakely@redhat.com
Mon Sep 28 09:34:30 GMT 2020
On 28/09/20 00:48 -0400, Patrick Palka via Libstdc++ wrote:
>Since the standard range adaptors are specified to derive from the empty
>class view_base, making their first data member store the underlying
>view is suboptimal, for if the underlying view also derives from
>view_base then the two view_base subobjects will be adjacent, thus
>preventing the compiler from applying the empty base optimization to
>elide away the storage for these two empty bases.
>
>This patch improves the situation by declaring the _M_base data member
>last instead of first in each range adaptor that has more than one data
>member, so that the empty base optimization can apply more often.
>
>Tested on x86_64-pc-linux-gnu with and wihout -m32.
>
>libstdc++-v3/ChangeLog:
>
> * include/std/ranges (filter_view::_M_base): Declare this data
> member last.
> (transform_view::_M_base): Likewise.
> (take_view::_M_base): Likewise.
> (take_while_view::_M_base): Likewise.
> (drop_view::_M_base): Likewise.
> (drop_while_view::_M_base): Likewise.
> (join_view::_M_base): Likewise.
> (split_view::_M_base): Likewise.
> * testsuite/std/ranges/adaptors/sizeof.cc: Adjust expected
> sizes.
>---
> libstdc++-v3/include/std/ranges | 17 ++++++++---------
> .../testsuite/std/ranges/adaptors/sizeof.cc | 18 +++++++++---------
> 2 files changed, 17 insertions(+), 18 deletions(-)
>
>diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
>index 964a2b616a6..6fd8a85c2bf 100644
>--- a/libstdc++-v3/include/std/ranges
>+++ b/libstdc++-v3/include/std/ranges
>@@ -1250,9 +1250,9 @@ namespace views
> { return __y.__equal(__x); }
> };
>
>- _Vp _M_base = _Vp();
> [[no_unique_address]] __detail::__box<_Pred> _M_pred;
> [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
>+ _Vp _M_base = _Vp();
The constructor's mem-initializer-list needs to be reordered, to avoid
warnings with -Wsystem-headers.
>
> public:
> filter_view() = default;
>@@ -1588,8 +1588,8 @@ namespace views
> friend _Sentinel<!_Const>;
> };
>
>- _Vp _M_base = _Vp();
> [[no_unique_address]] __detail::__box<_Fp> _M_fun;
>+ _Vp _M_base = _Vp();
>
> public:
> transform_view() = default;
>@@ -1695,8 +1695,8 @@ namespace views
> friend _Sentinel<!_Const>;
> };
>
>- _Vp _M_base = _Vp();
> range_difference_t<_Vp> _M_count = 0;
>+ _Vp _M_base = _Vp();
>
> public:
> take_view() = default;
>@@ -1842,8 +1842,8 @@ namespace views
> friend _Sentinel<!_Const>;
> };
>
>- _Vp _M_base = _Vp();
> [[no_unique_address]] __detail::__box<_Pred> _M_pred;
>+ _Vp _M_base = _Vp();
>
> public:
> take_while_view() = default;
>@@ -1902,8 +1902,8 @@ namespace views
> class drop_view : public view_interface<drop_view<_Vp>>
> {
> private:
>- _Vp _M_base = _Vp();
> range_difference_t<_Vp> _M_count = 0;
>+ _Vp _M_base = _Vp();
>
> // ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies
> // both random_access_range and sized_range. Otherwise, cache its result.
>@@ -2002,9 +2002,9 @@ namespace views
> class drop_while_view : public view_interface<drop_while_view<_Vp, _Pred>>
> {
> private:
>- _Vp _M_base = _Vp();
> [[no_unique_address]] __detail::__box<_Pred> _M_pred;
> [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
>+ _Vp _M_base = _Vp();
>
> public:
> drop_while_view() = default;
>@@ -2300,12 +2300,11 @@ namespace views
> friend _Sentinel<!_Const>;
> };
>
>- _Vp _M_base = _Vp();
>-
> // XXX: _M_inner is "present only when !is_reference_v<_InnerRange>"
> [[no_unique_address]]
> __detail::__maybe_present_t<!is_reference_v<_InnerRange>,
> views::all_t<_InnerRange>> _M_inner;
>+ _Vp _M_base = _Vp();
>
> public:
> join_view() = default;
>@@ -2680,8 +2679,8 @@ namespace views
> { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); }
> };
>
>- _Vp _M_base = _Vp();
> _Pattern _M_pattern = _Pattern();
>+ _Vp _M_base = _Vp();
>
> // XXX: _M_current is "present only if !forward_range<V>"
> [[no_unique_address]]
>diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
>index 5fb1ab7e4da..a7f622bb725 100644
>--- a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
>+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
>@@ -33,17 +33,17 @@ using V = ranges::subrange<int*, int*>;
> constexpr auto ptr = sizeof(int*);
> static_assert(sizeof(V) == 2*ptr);
>
>-static_assert(sizeof(ranges::take_view<V>) == 4*ptr);
>-static_assert(sizeof(ranges::drop_view<V>) == 4*ptr);
>+static_assert(sizeof(ranges::take_view<V>) == 3*ptr);
>+static_assert(sizeof(ranges::drop_view<V>) == 3*ptr);
>
>-static_assert(sizeof(ranges::filter_view<V, decltype(&pred_f)>) == 5*ptr);
>-static_assert(sizeof(ranges::take_while_view<V, decltype(&pred_f)>) == 4*ptr);
>-static_assert(sizeof(ranges::drop_while_view<V, decltype(&pred_f)>) == 5*ptr);
>-static_assert(sizeof(ranges::transform_view<V, decltype(&func_f)>) == 4*ptr);
>+static_assert(sizeof(ranges::filter_view<V, decltype(&pred_f)>) == 4*ptr);
>+static_assert(sizeof(ranges::take_while_view<V, decltype(&pred_f)>) == 3*ptr);
>+static_assert(sizeof(ranges::drop_while_view<V, decltype(&pred_f)>) == 4*ptr);
>+static_assert(sizeof(ranges::transform_view<V, decltype(&func_f)>) == 3*ptr);
>
>-static_assert(sizeof(ranges::filter_view<V, decltype(pred_l)>) == 4*ptr);
>+static_assert(sizeof(ranges::filter_view<V, decltype(pred_l)>) == 3*ptr);
> static_assert(sizeof(ranges::take_while_view<V, decltype(pred_l)>) == 3*ptr);
>-static_assert(sizeof(ranges::drop_while_view<V, decltype(pred_l)>) == 4*ptr);
>+static_assert(sizeof(ranges::drop_while_view<V, decltype(pred_l)>) == 3*ptr);
> static_assert(sizeof(ranges::transform_view<V, decltype(func_l)>) == 3*ptr);
>
>-static_assert(sizeof(ranges::split_view<V, std::string_view>) == 5*ptr);
>+static_assert(sizeof(ranges::split_view<V, std::string_view>) == 4*ptr);
>--
>2.28.0.618.g9bc233ae1c
>
More information about the Libstdc++
mailing list