public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libstdc++: Simplify std::valarray initialization helpers
@ 2024-06-20 15:32 Jonathan Wakely
  2024-06-25 23:26 ` Jonathan Wakely
  0 siblings, 1 reply; 2+ messages in thread
From: Jonathan Wakely @ 2024-06-20 15:32 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Tested x86_64-linux.

-- >8 --

Dispatching to partial specializations doesn't really seem to offer much
benefit here. The __is_trivial(T) condition is a compile-time constant
so the untaken branches are dead code and don't cost us anything.

libstdc++-v3/ChangeLog:

	* include/bits/valarray_array.h (_Array_default_ctor): Remove.
	(__valarray_default_construct): Inline it into here.
	(_Array_init_ctor): Remove.
	(__valarray_fill_construct): Inline it into here.
	(_Array_copy_ctor): Remove.
	(__valarray_copy_construct(const T*, const T*, T*)): Inline it
	into here.
	(__valarray_copy_construct(const T*, size_t, size_t, T*)):
	Use _GLIBCXX17_CONSTEXPR for constant condition.
---
 libstdc++-v3/include/bits/valarray_array.h | 97 ++++------------------
 1 file changed, 18 insertions(+), 79 deletions(-)

diff --git a/libstdc++-v3/include/bits/valarray_array.h b/libstdc++-v3/include/bits/valarray_array.h
index 07c49ce1057..0dc28333f33 100644
--- a/libstdc++-v3/include/bits/valarray_array.h
+++ b/libstdc++-v3/include/bits/valarray_array.h
@@ -62,105 +62,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __valarray_release_memory(void* __p)
   { operator delete(__p); }
 
-  // Turn a raw-memory into an array of _Tp filled with _Tp()
-  // This is required in 'valarray<T> v(n);'
-  template<typename _Tp, bool>
-    struct _Array_default_ctor
-    {
-      // Please note that this isn't exception safe.  But
-      // valarrays aren't required to be exception safe.
-      inline static void
-      _S_do_it(_Tp* __b, _Tp* __e)
-      {
-	while (__b != __e)
-	  new(__b++) _Tp();
-      }
-    };
-
-  template<typename _Tp>
-    struct _Array_default_ctor<_Tp, true>
-    {
-      // For trivial types, it suffices to say 'memset()'
-      inline static void
-      _S_do_it(_Tp* __b, _Tp* __e)
-      { __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp)); }
-    };
-
+  // Turn raw-memory into an array of _Tp filled with _Tp().
+  // This is used in `valarray<T> v(n);` and in `valarray<T>::shift(n)`.
   template<typename _Tp>
     inline void
     __valarray_default_construct(_Tp* __b, _Tp* __e)
     {
-      _Array_default_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e);
+      if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
+	__builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp));
+      else
+	while (__b != __e)
+	  ::new(static_cast<void*>(__b++)) _Tp();
     }
 
   // Turn a raw-memory into an array of _Tp filled with __t
   // This is the required in valarray<T> v(n, t).  Also
   // used in valarray<>::resize().
-  template<typename _Tp, bool>
-    struct _Array_init_ctor
-    {
-      // Please note that this isn't exception safe.  But
-      // valarrays aren't required to be exception safe.
-      inline static void
-      _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t)
-      {
-	while (__b != __e)
-	  new(__b++) _Tp(__t);
-      }
-    };
-
-  template<typename _Tp>
-    struct _Array_init_ctor<_Tp, true>
-    {
-      inline static void
-      _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t)
-      {
-	while (__b != __e)
-	  *__b++ = __t;
-      }
-    };
-
   template<typename _Tp>
     inline void
     __valarray_fill_construct(_Tp* __b, _Tp* __e, const _Tp __t)
     {
-      _Array_init_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __t);
+      while (__b != __e)
+	::new(static_cast<void*>(__b++)) _Tp(__t);
     }
 
-  //
   // copy-construct raw array [__o, *) from plain array [__b, __e)
-  // We can't just say 'memcpy()'
-  //
-  template<typename _Tp, bool>
-    struct _Array_copy_ctor
-    {
-      // Please note that this isn't exception safe.  But
-      // valarrays aren't required to be exception safe.
-      inline static void
-      _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o)
-      {
-	while (__b != __e)
-	  new(__o++) _Tp(*__b++);
-      }
-    };
-
-  template<typename _Tp>
-    struct _Array_copy_ctor<_Tp, true>
-    {
-      inline static void
-      _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o)
-      {
-	if (__b)
-	  __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp));
-      }
-    };
-
   template<typename _Tp>
     inline void
     __valarray_copy_construct(const _Tp* __b, const _Tp* __e,
 			      _Tp* __restrict__ __o)
     {
-      _Array_copy_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __o);
+      if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
+	{
+	  if (__b)
+	    __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp));
+	}
+      else
+	while (__b != __e)
+	  ::new(static_cast<void*>(__o++)) _Tp(*__b++);
     }
 
   // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
@@ -169,7 +108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
 			       size_t __s, _Tp* __restrict__ __o)
     {
-      if (__is_trivial(_Tp))
+      if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
 	while (__n--)
 	  {
 	    *__o++ = *__a;
-- 
2.45.2


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

* Re: [PATCH] libstdc++: Simplify std::valarray initialization helpers
  2024-06-20 15:32 [PATCH] libstdc++: Simplify std::valarray initialization helpers Jonathan Wakely
@ 2024-06-25 23:26 ` Jonathan Wakely
  0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Wakely @ 2024-06-25 23:26 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Pushed to trunk.

On Thu, 20 Jun 2024 at 16:34, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> Tested x86_64-linux.
>
> -- >8 --
>
> Dispatching to partial specializations doesn't really seem to offer much
> benefit here. The __is_trivial(T) condition is a compile-time constant
> so the untaken branches are dead code and don't cost us anything.
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/valarray_array.h (_Array_default_ctor): Remove.
>         (__valarray_default_construct): Inline it into here.
>         (_Array_init_ctor): Remove.
>         (__valarray_fill_construct): Inline it into here.
>         (_Array_copy_ctor): Remove.
>         (__valarray_copy_construct(const T*, const T*, T*)): Inline it
>         into here.
>         (__valarray_copy_construct(const T*, size_t, size_t, T*)):
>         Use _GLIBCXX17_CONSTEXPR for constant condition.
> ---
>  libstdc++-v3/include/bits/valarray_array.h | 97 ++++------------------
>  1 file changed, 18 insertions(+), 79 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/valarray_array.h b/libstdc++-v3/include/bits/valarray_array.h
> index 07c49ce1057..0dc28333f33 100644
> --- a/libstdc++-v3/include/bits/valarray_array.h
> +++ b/libstdc++-v3/include/bits/valarray_array.h
> @@ -62,105 +62,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    __valarray_release_memory(void* __p)
>    { operator delete(__p); }
>
> -  // Turn a raw-memory into an array of _Tp filled with _Tp()
> -  // This is required in 'valarray<T> v(n);'
> -  template<typename _Tp, bool>
> -    struct _Array_default_ctor
> -    {
> -      // Please note that this isn't exception safe.  But
> -      // valarrays aren't required to be exception safe.
> -      inline static void
> -      _S_do_it(_Tp* __b, _Tp* __e)
> -      {
> -       while (__b != __e)
> -         new(__b++) _Tp();
> -      }
> -    };
> -
> -  template<typename _Tp>
> -    struct _Array_default_ctor<_Tp, true>
> -    {
> -      // For trivial types, it suffices to say 'memset()'
> -      inline static void
> -      _S_do_it(_Tp* __b, _Tp* __e)
> -      { __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp)); }
> -    };
> -
> +  // Turn raw-memory into an array of _Tp filled with _Tp().
> +  // This is used in `valarray<T> v(n);` and in `valarray<T>::shift(n)`.
>    template<typename _Tp>
>      inline void
>      __valarray_default_construct(_Tp* __b, _Tp* __e)
>      {
> -      _Array_default_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e);
> +      if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
> +       __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp));
> +      else
> +       while (__b != __e)
> +         ::new(static_cast<void*>(__b++)) _Tp();
>      }
>
>    // Turn a raw-memory into an array of _Tp filled with __t
>    // This is the required in valarray<T> v(n, t).  Also
>    // used in valarray<>::resize().
> -  template<typename _Tp, bool>
> -    struct _Array_init_ctor
> -    {
> -      // Please note that this isn't exception safe.  But
> -      // valarrays aren't required to be exception safe.
> -      inline static void
> -      _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t)
> -      {
> -       while (__b != __e)
> -         new(__b++) _Tp(__t);
> -      }
> -    };
> -
> -  template<typename _Tp>
> -    struct _Array_init_ctor<_Tp, true>
> -    {
> -      inline static void
> -      _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t)
> -      {
> -       while (__b != __e)
> -         *__b++ = __t;
> -      }
> -    };
> -
>    template<typename _Tp>
>      inline void
>      __valarray_fill_construct(_Tp* __b, _Tp* __e, const _Tp __t)
>      {
> -      _Array_init_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __t);
> +      while (__b != __e)
> +       ::new(static_cast<void*>(__b++)) _Tp(__t);
>      }
>
> -  //
>    // copy-construct raw array [__o, *) from plain array [__b, __e)
> -  // We can't just say 'memcpy()'
> -  //
> -  template<typename _Tp, bool>
> -    struct _Array_copy_ctor
> -    {
> -      // Please note that this isn't exception safe.  But
> -      // valarrays aren't required to be exception safe.
> -      inline static void
> -      _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o)
> -      {
> -       while (__b != __e)
> -         new(__o++) _Tp(*__b++);
> -      }
> -    };
> -
> -  template<typename _Tp>
> -    struct _Array_copy_ctor<_Tp, true>
> -    {
> -      inline static void
> -      _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o)
> -      {
> -       if (__b)
> -         __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp));
> -      }
> -    };
> -
>    template<typename _Tp>
>      inline void
>      __valarray_copy_construct(const _Tp* __b, const _Tp* __e,
>                               _Tp* __restrict__ __o)
>      {
> -      _Array_copy_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __o);
> +      if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
> +       {
> +         if (__b)
> +           __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp));
> +       }
> +      else
> +       while (__b != __e)
> +         ::new(static_cast<void*>(__o++)) _Tp(*__b++);
>      }
>
>    // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
> @@ -169,7 +108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
>                                size_t __s, _Tp* __restrict__ __o)
>      {
> -      if (__is_trivial(_Tp))
> +      if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
>         while (__n--)
>           {
>             *__o++ = *__a;
> --
> 2.45.2
>


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

end of thread, other threads:[~2024-06-25 23:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-20 15:32 [PATCH] libstdc++: Simplify std::valarray initialization helpers Jonathan Wakely
2024-06-25 23:26 ` 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).