[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