public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view
@ 2020-09-28  4:48 Patrick Palka
  2020-09-28  4:48 ` [PATCH 2/4] libstdc++: Reduce the size of a subrange with empty sentinel type Patrick Palka
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Patrick Palka @ 2020-09-28  4:48 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Patrick Palka

libstdc++-v3/ChangeLog:

	* include/std/ranges (iota_view::_M_bound): Give it
	[[no_unique_address]].
	* testsuite/std/ranges/iota/iota_view.cc: Check that an
	unbounded iota_view has minimal size.
---
 libstdc++-v3/include/std/ranges                     | 2 +-
 libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index ed04fa0001d..964a2b616a6 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -511,7 +511,7 @@ namespace ranges
       };
 
       _Winc _M_value = _Winc();
-      _Bound _M_bound = _Bound();
+      [[no_unique_address]] _Bound _M_bound = _Bound();
 
     public:
       iota_view() = default;
diff --git a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
index 65d166fbd3b..8a33e10a093 100644
--- a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
+++ b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
@@ -77,6 +77,9 @@ test04()
   VERIFY( it == v.end() );
 }
 
+// Verify we optimize away the 'bound' data member of an unbounded iota_view.
+static_assert(sizeof(std::ranges::iota_view<char>) == 1);
+
 int
 main()
 {
-- 
2.28.0.618.g9bc233ae1c


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/4] libstdc++: Reduce the size of a subrange with empty sentinel type
  2020-09-28  4:48 [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Patrick Palka
@ 2020-09-28  4:48 ` Patrick Palka
  2020-09-28  9:32   ` Jonathan Wakely
  2020-09-28  4:48 ` [PATCH 3/4] libstdc++: Add test that tracks range adaptors' sizes Patrick Palka
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Patrick Palka @ 2020-09-28  4:48 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Patrick Palka

libstdc++-v3/ChangeLog:

	* include/bits/ranges_util.h (subrange::_M_end): Give it
	[[no_unique_adcress]].
	* testsuite/std/ranges/subrange/sizeof.cc: New test.
---
 libstdc++-v3/include/bits/ranges_util.h       |  2 +-
 .../testsuite/std/ranges/subrange/sizeof.cc   | 28 +++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc

diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
index 694ae796399..a98658ff5c8 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -208,7 +208,7 @@ namespace ranges
 	= _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
 
       _It _M_begin = _It();
-      _Sent _M_end = _Sent();
+      [[no_unique_address]] _Sent _M_end = _Sent();
 
       template<typename, bool = _S_store_size>
 	struct _Size
diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc
new file mode 100644
index 00000000000..7e95e196c6c
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc
@@ -0,0 +1,28 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <iterator>
+#include <ranges>
+
+// Verify we optimize away the 'end' data member of a subrange with an empty
+// sentinel type.
+static_assert(sizeof(std::ranges::subrange<std::counted_iterator<int*>,
+					   std::default_sentinel_t>)
+	      == sizeof(std::counted_iterator<int*>));
-- 
2.28.0.618.g9bc233ae1c


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/4] libstdc++: Add test that tracks range adaptors' sizes
  2020-09-28  4:48 [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Patrick Palka
  2020-09-28  4:48 ` [PATCH 2/4] libstdc++: Reduce the size of a subrange with empty sentinel type Patrick Palka
@ 2020-09-28  4:48 ` Patrick Palka
  2020-09-28  9:32   ` Jonathan Wakely
  2020-09-28  4:48 ` [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members Patrick Palka
  2020-09-28  9:31 ` [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Jonathan Wakely
  3 siblings, 1 reply; 10+ messages in thread
From: Patrick Palka @ 2020-09-28  4:48 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Patrick Palka

libstdc++-v3/ChangeLog:

	* testsuite/std/ranges/adaptors/sizeof.cc: New test.
---
 .../testsuite/std/ranges/adaptors/sizeof.cc   | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc

diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
new file mode 100644
index 00000000000..5fb1ab7e4da
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ranges>
+#include <string_view>
+
+namespace ranges = std::ranges;
+
+auto pred_f(int x) { return x%2 == 0; };
+auto pred_l = [] (int x) { return x%2 == 0; };
+
+auto func_f(int x) { return x*x; }
+auto func_l = [] (int x) { return x*x; };
+
+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::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_l)>) == 4*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::transform_view<V, decltype(func_l)>) == 3*ptr);
+
+static_assert(sizeof(ranges::split_view<V, std::string_view>) == 5*ptr);
-- 
2.28.0.618.g9bc233ae1c


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members
  2020-09-28  4:48 [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Patrick Palka
  2020-09-28  4:48 ` [PATCH 2/4] libstdc++: Reduce the size of a subrange with empty sentinel type Patrick Palka
  2020-09-28  4:48 ` [PATCH 3/4] libstdc++: Add test that tracks range adaptors' sizes Patrick Palka
@ 2020-09-28  4:48 ` Patrick Palka
  2020-09-28  9:34   ` Jonathan Wakely
  2020-09-28  9:31 ` [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Jonathan Wakely
  3 siblings, 1 reply; 10+ messages in thread
From: Patrick Palka @ 2020-09-28  4:48 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Patrick Palka

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();
 
     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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view
  2020-09-28  4:48 [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Patrick Palka
                   ` (2 preceding siblings ...)
  2020-09-28  4:48 ` [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members Patrick Palka
@ 2020-09-28  9:31 ` Jonathan Wakely
  3 siblings, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2020-09-28  9:31 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On 28/09/20 00:48 -0400, Patrick Palka via Libstdc++ wrote:
>libstdc++-v3/ChangeLog:
>
>	* include/std/ranges (iota_view::_M_bound): Give it
>	[[no_unique_address]].
>	* testsuite/std/ranges/iota/iota_view.cc: Check that an
>	unbounded iota_view has minimal size.

OK.

> libstdc++-v3/include/std/ranges                     | 2 +-
> libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc | 3 +++
> 2 files changed, 4 insertions(+), 1 deletion(-)
>
>diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
>index ed04fa0001d..964a2b616a6 100644
>--- a/libstdc++-v3/include/std/ranges
>+++ b/libstdc++-v3/include/std/ranges
>@@ -511,7 +511,7 @@ namespace ranges
>       };
>
>       _Winc _M_value = _Winc();
>-      _Bound _M_bound = _Bound();
>+      [[no_unique_address]] _Bound _M_bound = _Bound();
>
>     public:
>       iota_view() = default;
>diff --git a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
>index 65d166fbd3b..8a33e10a093 100644
>--- a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
>+++ b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
>@@ -77,6 +77,9 @@ test04()
>   VERIFY( it == v.end() );
> }
>
>+// Verify we optimize away the 'bound' data member of an unbounded iota_view.
>+static_assert(sizeof(std::ranges::iota_view<char>) == 1);
>+
> int
> main()
> {
>-- 
>2.28.0.618.g9bc233ae1c
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] libstdc++: Reduce the size of a subrange with empty sentinel type
  2020-09-28  4:48 ` [PATCH 2/4] libstdc++: Reduce the size of a subrange with empty sentinel type Patrick Palka
@ 2020-09-28  9:32   ` Jonathan Wakely
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2020-09-28  9:32 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On 28/09/20 00:48 -0400, Patrick Palka via Libstdc++ wrote:
>libstdc++-v3/ChangeLog:
>
>	* include/bits/ranges_util.h (subrange::_M_end): Give it
>	[[no_unique_adcress]].
>	* testsuite/std/ranges/subrange/sizeof.cc: New test.

OK.

> libstdc++-v3/include/bits/ranges_util.h       |  2 +-
> .../testsuite/std/ranges/subrange/sizeof.cc   | 28 +++++++++++++++++++
> 2 files changed, 29 insertions(+), 1 deletion(-)
> create mode 100644 libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc
>
>diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
>index 694ae796399..a98658ff5c8 100644
>--- a/libstdc++-v3/include/bits/ranges_util.h
>+++ b/libstdc++-v3/include/bits/ranges_util.h
>@@ -208,7 +208,7 @@ namespace ranges
> 	= _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
>
>       _It _M_begin = _It();
>-      _Sent _M_end = _Sent();
>+      [[no_unique_address]] _Sent _M_end = _Sent();
>
>       template<typename, bool = _S_store_size>
> 	struct _Size
>diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc
>new file mode 100644
>index 00000000000..7e95e196c6c
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/std/ranges/subrange/sizeof.cc
>@@ -0,0 +1,28 @@
>+// Copyright (C) 2020 Free Software Foundation, Inc.
>+//
>+// This file is part of the GNU ISO C++ Library.  This library is free
>+// software; you can redistribute it and/or modify it under the
>+// terms of the GNU General Public License as published by the
>+// Free Software Foundation; either version 3, or (at your option)
>+// any later version.
>+
>+// This library is distributed in the hope that it will be useful,
>+// but WITHOUT ANY WARRANTY; without even the implied warranty of
>+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+// GNU General Public License for more details.
>+
>+// You should have received a copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+// <http://www.gnu.org/licenses/>.
>+
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do compile { target c++2a } }
>+
>+#include <iterator>
>+#include <ranges>
>+
>+// Verify we optimize away the 'end' data member of a subrange with an empty
>+// sentinel type.
>+static_assert(sizeof(std::ranges::subrange<std::counted_iterator<int*>,
>+					   std::default_sentinel_t>)
>+	      == sizeof(std::counted_iterator<int*>));
>-- 
>2.28.0.618.g9bc233ae1c
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] libstdc++: Add test that tracks range adaptors' sizes
  2020-09-28  4:48 ` [PATCH 3/4] libstdc++: Add test that tracks range adaptors' sizes Patrick Palka
@ 2020-09-28  9:32   ` Jonathan Wakely
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2020-09-28  9:32 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On 28/09/20 00:48 -0400, Patrick Palka via Libstdc++ wrote:
>libstdc++-v3/ChangeLog:
>
>	* testsuite/std/ranges/adaptors/sizeof.cc: New test.

OK.

> .../testsuite/std/ranges/adaptors/sizeof.cc   | 49 +++++++++++++++++++
> 1 file changed, 49 insertions(+)
> create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
>
>diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
>new file mode 100644
>index 00000000000..5fb1ab7e4da
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
>@@ -0,0 +1,49 @@
>+// Copyright (C) 2020 Free Software Foundation, Inc.
>+//
>+// This file is part of the GNU ISO C++ Library.  This library is free
>+// software; you can redistribute it and/or modify it under the
>+// terms of the GNU General Public License as published by the
>+// Free Software Foundation; either version 3, or (at your option)
>+// any later version.
>+
>+// This library is distributed in the hope that it will be useful,
>+// but WITHOUT ANY WARRANTY; without even the implied warranty of
>+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+// GNU General Public License for more details.
>+
>+// You should have received a copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+// <http://www.gnu.org/licenses/>.
>+
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do compile { target c++2a } }
>+
>+#include <ranges>
>+#include <string_view>
>+
>+namespace ranges = std::ranges;
>+
>+auto pred_f(int x) { return x%2 == 0; };
>+auto pred_l = [] (int x) { return x%2 == 0; };
>+
>+auto func_f(int x) { return x*x; }
>+auto func_l = [] (int x) { return x*x; };
>+
>+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::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_l)>) == 4*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::transform_view<V, decltype(func_l)>) == 3*ptr);
>+
>+static_assert(sizeof(ranges::split_view<V, std::string_view>) == 5*ptr);
>-- 
>2.28.0.618.g9bc233ae1c
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members
  2020-09-28  4:48 ` [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members Patrick Palka
@ 2020-09-28  9:34   ` Jonathan Wakely
  2020-09-28 13:11     ` Patrick Palka
  0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2020-09-28  9:34 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

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
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members
  2020-09-28  9:34   ` Jonathan Wakely
@ 2020-09-28 13:11     ` Patrick Palka
  2020-09-28 15:38       ` Jonathan Wakely
  0 siblings, 1 reply; 10+ messages in thread
From: Patrick Palka @ 2020-09-28 13:11 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Patrick Palka, gcc-patches, libstdc++

On Mon, 28 Sep 2020, Jonathan Wakely wrote:

> 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.

Oops, fixed thusly.  I noticed meanwhile that I forgot to move
reverse_view's _M_base member, so the below patch adds that as well.

Tested on x86_64-pc-linux-gnu, and also verified that there are no new
-Wsystem-headers warnings.

-- >8 --

libstdc++-v3/ChangeLog:

	* include/std/ranges (filter_view): Declare data member _M_base
	last instead of first, and adjust constructors' member
	initializer lists accordingly.
	(transform_view): Likewise.
	(take_view): Likewise.
	(take_while_view): Likewise.
	(drop_view): Likewise.
	(drop_while_view): Likewise.
	(join_view): Likewise.
	(split_view): Likewise (and tweak formatting of the declaration
	of _M_current).
	(reverse_view): Likewise.
	* testsuite/std/ranges/adaptors/sizeof.cc: Update expected
	sizes.
---
 libstdc++-v3/include/std/ranges               | 47 +++++++++----------
 .../testsuite/std/ranges/adaptors/sizeof.cc   | 20 ++++----
 2 files changed, 32 insertions(+), 35 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 964a2b616a6..7fd5d5110ed 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1250,16 +1250,16 @@ 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();
 
     public:
       filter_view() = default;
 
       constexpr
       filter_view(_Vp __base, _Pred __pred)
-	: _M_base(std::move(__base)), _M_pred(std::move(__pred))
+	: _M_pred(std::move(__pred)), _M_base(std::move(__base))
       { }
 
       constexpr _Vp
@@ -1588,15 +1588,15 @@ 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;
 
       constexpr
       transform_view(_Vp __base, _Fp __fun)
-	: _M_base(std::move(__base)), _M_fun(std::move(__fun))
+	: _M_fun(std::move(__fun)), _M_base(std::move(__base))
       { }
 
       constexpr _Vp
@@ -1695,15 +1695,15 @@ namespace views
 	  friend _Sentinel<!_Const>;
 	};
 
-      _Vp _M_base = _Vp();
       range_difference_t<_Vp> _M_count = 0;
+      _Vp _M_base = _Vp();
 
     public:
       take_view() = default;
 
       constexpr
       take_view(_Vp base, range_difference_t<_Vp> __count)
-	: _M_base(std::move(base)), _M_count(std::move(__count))
+	: _M_count(std::move(__count)), _M_base(std::move(base))
       { }
 
       constexpr _Vp
@@ -1842,17 +1842,16 @@ 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;
 
       constexpr
       take_while_view(_Vp base, _Pred __pred)
-	: _M_base(std::move(base)), _M_pred(std::move(__pred))
-      {
-      }
+	: _M_pred(std::move(__pred)), _M_base(std::move(base))
+      { }
 
       constexpr _Vp
       base() const& requires copy_constructible<_Vp>
@@ -1902,8 +1901,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.
@@ -1919,7 +1918,7 @@ namespace views
 
       constexpr
       drop_view(_Vp __base, range_difference_t<_Vp> __count)
-	: _M_base(std::move(__base)), _M_count(__count)
+	: _M_count(__count), _M_base(std::move(__base))
       { __glibcxx_assert(__count >= 0); }
 
       constexpr _Vp
@@ -2002,16 +2001,16 @@ 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;
 
       constexpr
       drop_while_view(_Vp __base, _Pred __pred)
-	: _M_base(std::move(__base)), _M_pred(std::move(__pred))
+	: _M_pred(std::move(__pred)), _M_base(std::move(__base))
       { }
 
       constexpr _Vp
@@ -2300,12 +2299,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,13 +2678,12 @@ namespace views
 	  { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); }
 	};
 
-      _Vp _M_base = _Vp();
       _Pattern _M_pattern = _Pattern();
-
       // XXX: _M_current is "present only if !forward_range<V>"
       [[no_unique_address]]
-	__detail::__maybe_present_t<!forward_range<_Vp>, iterator_t<_Vp>>
-	  _M_current;
+	__detail::__maybe_present_t<!forward_range<_Vp>,
+				    iterator_t<_Vp>> _M_current;
+      _Vp _M_base = _Vp();
 
 
     public:
@@ -2694,7 +2691,7 @@ namespace views
 
       constexpr
       split_view(_Vp __base, _Pattern __pattern)
-	: _M_base(std::move(__base)), _M_pattern(std::move(__pattern))
+	: _M_pattern(std::move(__pattern)), _M_base(std::move(__base))
       { }
 
       template<input_range _Range>
@@ -2702,8 +2699,8 @@ namespace views
 	  && constructible_from<_Pattern, single_view<range_value_t<_Range>>>
 	constexpr
 	split_view(_Range&& __r, range_value_t<_Range> __e)
-	  : _M_base(views::all(std::forward<_Range>(__r))),
-	    _M_pattern(std::move(__e))
+	  : _M_pattern(std::move(__e)),
+	    _M_base(views::all(std::forward<_Range>(__r)))
 	{ }
 
       constexpr _Vp
@@ -2892,14 +2889,14 @@ namespace views
     class reverse_view : public view_interface<reverse_view<_Vp>>
     {
     private:
-      _Vp _M_base = _Vp();
-
       static constexpr bool _S_needs_cached_begin
 	= !common_range<_Vp> && !random_access_range<_Vp>;
+
       [[no_unique_address]]
 	__detail::__maybe_present_t<_S_needs_cached_begin,
 				    __detail::_CachedPosition<_Vp>>
 				      _M_cached_begin;
+      _Vp _M_base = _Vp();
 
     public:
       reverse_view() = default;
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
index 2182981b7a2..4d6f78b36b1 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc
@@ -33,20 +33,20 @@ 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);
 
 static_assert
- (sizeof(ranges::reverse_view<ranges::filter_view<V, decltype(pred_l)>>) == 5*ptr);
+ (sizeof(ranges::reverse_view<ranges::filter_view<V, decltype(pred_l)>>) == 4*ptr);
-- 
2.28.0.618.g9bc233ae1c


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members
  2020-09-28 13:11     ` Patrick Palka
@ 2020-09-28 15:38       ` Jonathan Wakely
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2020-09-28 15:38 UTC (permalink / raw)
  To: Patrick Palka; +Cc: libstdc++, gcc-patches

On 28/09/20 09:11 -0400, Patrick Palka via Libstdc++ wrote:
>On Mon, 28 Sep 2020, Jonathan Wakely wrote:
>
>> 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.
>
>Oops, fixed thusly.  I noticed meanwhile that I forgot to move
>reverse_view's _M_base member, so the below patch adds that as well.

Nice to see testsuite/std/ranges/adaptors/sizeof.cc already proving
useful by demonstrating the reduced sizes.

>Tested on x86_64-pc-linux-gnu, and also verified that there are no new
>-Wsystem-headers warnings.

OK, thanks.


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-09-28 15:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-28  4:48 [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Patrick Palka
2020-09-28  4:48 ` [PATCH 2/4] libstdc++: Reduce the size of a subrange with empty sentinel type Patrick Palka
2020-09-28  9:32   ` Jonathan Wakely
2020-09-28  4:48 ` [PATCH 3/4] libstdc++: Add test that tracks range adaptors' sizes Patrick Palka
2020-09-28  9:32   ` Jonathan Wakely
2020-09-28  4:48 ` [PATCH 4/4] libstdc++: Rearrange some range adaptors' data members Patrick Palka
2020-09-28  9:34   ` Jonathan Wakely
2020-09-28 13:11     ` Patrick Palka
2020-09-28 15:38       ` Jonathan Wakely
2020-09-28  9:31 ` [PATCH 1/4] libstdc++: Reduce the size of an unbounded iota_view Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).