[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