[libcxx-commits] [libcxx] [libc++][PSTL] Add backend for forwaring to mem functions (PR #102448)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 8 03:40:29 PDT 2024


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/102448

None

>From 1213be216567cbc61f3fb3e86787abc70ff2e0e5 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 8 Aug 2024 12:39:35 +0200
Subject: [PATCH] [libc++][PSTL] Add backend for forwaring to mem functions

---
 libcxx/include/CMakeLists.txt                 |  1 +
 libcxx/include/__algorithm/equal.h            | 10 +-
 libcxx/include/__pstl/backend.h               |  1 +
 libcxx/include/__pstl/backend_fwd.h           |  3 +-
 .../__pstl/backends/forward_to_mem_funcs.h    | 94 +++++++++++++++++++
 libcxx/include/__pstl/dispatch.h              | 23 ++++-
 6 files changed, 125 insertions(+), 7 deletions(-)
 create mode 100644 libcxx/include/__pstl/backends/forward_to_mem_funcs.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 32579272858a8..68e4d30e71414 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -582,6 +582,7 @@ set(files
   __pstl/backend.h
   __pstl/backend_fwd.h
   __pstl/backends/default.h
+  __pstl/backends/forward_to_mem_funcs.h
   __pstl/backends/libdispatch.h
   __pstl/backends/serial.h
   __pstl/backends/std_thread.h
diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index bfc8f72f6eb19..f1b234cca1d42 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -81,15 +81,17 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
   return __first1 == __last1 && __first2 == __last2;
 }
 
+template <class _Tp, class _Up, class _Pred, class _Proj1, class _Proj2>
+inline constexpr bool __can_lower_to_memcmp_equal =
+    __desugars_to_v<__equal_tag, _Pred, _Tp, _Up> && __is_identity<_Proj1>::value && __is_identity<_Proj2>::value &&
+    !is_volatile<_Tp>::value && !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value;
+
 template <class _Tp,
           class _Up,
           class _Pred,
           class _Proj1,
           class _Proj2,
-          __enable_if_t<__desugars_to_v<__equal_tag, _Pred, _Tp, _Up> && __is_identity<_Proj1>::value &&
-                            __is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value &&
-                            __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
-                        int> = 0>
+          __enable_if_t<__can_lower_to_memcmp_equal<_Tp, _Up, _Pred, _Proj1, _Proj2>, int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
   return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
diff --git a/libcxx/include/__pstl/backend.h b/libcxx/include/__pstl/backend.h
index 86d9f28c77fa8..88b252720d11d 100644
--- a/libcxx/include/__pstl/backend.h
+++ b/libcxx/include/__pstl/backend.h
@@ -24,6 +24,7 @@ _LIBCPP_PUSH_MACROS
 #  include <__pstl/backends/serial.h>
 #elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD)
 #  include <__pstl/backends/default.h>
+#  include <__pstl/backends/forward_to_mem_funcs.h>
 #  include <__pstl/backends/std_thread.h>
 #elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH)
 #  include <__pstl/backends/default.h>
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index 32c5da576fb3c..803780086e88d 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -49,11 +49,12 @@ struct __default_backend_tag;
 struct __libdispatch_backend_tag;
 struct __serial_backend_tag;
 struct __std_thread_backend_tag;
+struct __forward_to_mem_funcs_backend_tag;
 
 #if defined(_LIBCPP_PSTL_BACKEND_SERIAL)
 using __current_configuration = __backend_configuration<__serial_backend_tag, __default_backend_tag>;
 #elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD)
-using __current_configuration = __backend_configuration<__std_thread_backend_tag, __default_backend_tag>;
+using __current_configuration = __backend_configuration<__forward_to_mem_funcs_backend_tag, __std_thread_backend_tag, __default_backend_tag>;
 #elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH)
 using __current_configuration = __backend_configuration<__libdispatch_backend_tag, __default_backend_tag>;
 #else
diff --git a/libcxx/include/__pstl/backends/forward_to_mem_funcs.h b/libcxx/include/__pstl/backends/forward_to_mem_funcs.h
new file mode 100644
index 0000000000000..7267a067f00be
--- /dev/null
+++ b/libcxx/include/__pstl/backends/forward_to_mem_funcs.h
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___PSTL_BACKENDS_FORWARD_TO_MEM_FUNCS_H
+#define _LIBCPP___PSTL_BACKENDS_FORWARD_TO_MEM_FUNCS_H
+
+#include <__algorithm/copy_move_common.h>
+#include <__algorithm/equal.h>
+#include <__config>
+#include <__pstl/backend_fwd.h>
+#include <__pstl/dispatch.h>
+#include <optional>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace __pstl {
+
+template <class _ExecutionPolicy>
+struct __copy<__forward_to_mem_funcs_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _In,
+            class _Out,
+            enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Out*>
+  operator()(_Policy&&, _In* __first, _In* __last, _Out* __result) const noexcept {
+    return std::__constexpr_memmove(__result, __first, __element_count(__last - __first));
+  }
+};
+
+template <class _ExecutionPolicy>
+struct __copy_n<__forward_to_mem_funcs_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _In,
+            class _Size,
+            class _Out,
+            enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Out*>
+  operator()(_Policy&&, _In* __first, _Size __n, _Out* __result) const noexcept {
+    return std::__constexpr_memmove(__result, __first, __element_count(__n));
+  }
+};
+
+template <class _ExecutionPolicy>
+struct __move<__forward_to_mem_funcs_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _In,
+            class _Out,
+            enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Out*>
+  operator()(_Policy&&, _In* __first, _In* __last, _Out* __result) const noexcept {
+    return std::__constexpr_memmove(__result, __first, __element_count(__last - __first));
+  }
+};
+
+template <class _ExecutionPolicy>
+struct __equal<__forward_to_mem_funcs_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _Tp,
+            class _Up,
+            class _Pred,
+            enable_if_t<__can_lower_to_memcmp_equal<_Tp, _Up, _Pred, __identity, __identity>, int> = 0>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
+  operator()(_Policy&&, _Tp* __first1, _Tp* __last1, _Up* __first2, _Up* __last2) const noexcept {
+    if (__last2 - __first2 != __last1 - __first2)
+      return false;
+    return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
+  }
+};
+
+template <class _ExecutionPolicy>
+struct __equal_3leg<__forward_to_mem_funcs_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _Tp,
+            class _Up,
+            class _Pred,
+            enable_if_t<__can_lower_to_memcmp_equal<_Tp, _Up, _Pred, __identity, __identity>, int> = 0>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
+  operator()(_Policy&&, _Tp* __first1, _Tp* __last1, _Up* __first2) const noexcept {
+    return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first2));
+  }
+};
+
+} // namespace __pstl
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___PSTL_BACKENDS_FORWARD_TO_MEM_FUNCS_H
diff --git a/libcxx/include/__pstl/dispatch.h b/libcxx/include/__pstl/dispatch.h
index 5e903f7524fe9..3a771339c312a 100644
--- a/libcxx/include/__pstl/dispatch.h
+++ b/libcxx/include/__pstl/dispatch.h
@@ -14,7 +14,9 @@
 #include <__type_traits/conditional.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/integral_constant.h>
+#include <__type_traits/is_callable.h>
 #include <__type_traits/type_identity.h>
+#include <__utility/forward.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -49,14 +51,31 @@ struct __find_first_implemented<_Algorithm, __backend_configuration<>, _Executio
                 "Could not find a PSTL backend for the given algorithm and execution policy");
 };
 
+template <class _Backend, class _RemainingBackends>
+struct __backend_info {
+  using __backend            = _Backend;
+  using __remaining_backends = _RemainingBackends;
+};
+
 template <template <class, class> class _Algorithm, class _B1, class... _Bn, class _ExecutionPolicy>
 struct __find_first_implemented<_Algorithm, __backend_configuration<_B1, _Bn...>, _ExecutionPolicy>
     : _If<__is_implemented_v<_Algorithm, _B1, _ExecutionPolicy>,
-          __type_identity<_Algorithm<_B1, _ExecutionPolicy>>,
+          __backend_info<_Algorithm<_B1, _ExecutionPolicy>, __backend_configuration<_Bn...>>,
           __find_first_implemented<_Algorithm, __backend_configuration<_Bn...>, _ExecutionPolicy> > {};
 
 template <template <class, class> class _Algorithm, class _BackendConfiguration, class _ExecutionPolicy>
-using __dispatch = typename __find_first_implemented<_Algorithm, _BackendConfiguration, _ExecutionPolicy>::type;
+struct __dispatch {
+  template <class... _Args>
+  [[nodiscard]] auto operator()(_Args&&... __args) {
+    using _NextBackend = __find_first_implemented<_Algorithm, _BackendConfiguration, _ExecutionPolicy>;
+    if constexpr (__is_callable<typename _NextBackend::__backend, _Args...>::value) {
+      return typename _NextBackend::__backend()(std::forward<_Args>(__args)...);
+    } else {
+      return __dispatch<_Algorithm, typename _NextBackend::__remaining_backends, _ExecutionPolicy>()(
+          std::forward<_Args>(__args)...);
+    }
+  }
+};
 
 } // namespace __pstl
 _LIBCPP_END_NAMESPACE_STD



More information about the libcxx-commits mailing list