[libc-commits] [compiler-rt] [libcxx] [clang] [libc] [flang] [llvm] [clang-tools-extra] [libcxx] Unifying __is_trivial_equality_predicate and __is_trivial_plus_operation into __desugars_to (PR #68642)

Anton Rydahl via libc-commits libc-commits at lists.llvm.org
Sun Nov 5 13:02:08 PST 2023


https://github.com/AntonRydahl updated https://github.com/llvm/llvm-project/pull/68642

>From f0d93cc6a5cd485c654ab38221691db038bacc7d Mon Sep 17 00:00:00 2001
From: AntonRydahl <rydahl2610 at gmail.com>
Date: Mon, 9 Oct 2023 15:13:22 -0700
Subject: [PATCH 1/5] Merged __is_trivial_equality_predicate and
 __is_trivial_plus_operation into __desugars_to

---
 libcxx/include/CMakeLists.txt                 |  1 -
 libcxx/include/__algorithm/comp.h             |  7 ++---
 libcxx/include/__algorithm/equal.h            | 22 ++++++++--------
 .../cpu_backends/transform_reduce.h           | 23 ++++++++--------
 libcxx/include/__functional/operations.h      | 15 +++++------
 .../include/__functional/ranges_operations.h  |  7 ++---
 .../include/__numeric/pstl_transform_reduce.h |  2 +-
 .../include/__type_traits/operation_traits.h  |  4 +--
 .../include/__type_traits/predicate_traits.h  | 26 -------------------
 libcxx/include/module.modulemap.in            |  1 -
 10 files changed, 40 insertions(+), 68 deletions(-)
 delete mode 100644 libcxx/include/__type_traits/predicate_traits.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 340353f8ebb41c4..7eb09a06ccd482e 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -813,7 +813,6 @@ set(files
   __type_traits/negation.h
   __type_traits/noexcept_move_assign_container.h
   __type_traits/operation_traits.h
-  __type_traits/predicate_traits.h
   __type_traits/promote.h
   __type_traits/rank.h
   __type_traits/remove_all_extents.h
diff --git a/libcxx/include/__algorithm/comp.h b/libcxx/include/__algorithm/comp.h
index 9474536615ffb67..0993c37cce36a6b 100644
--- a/libcxx/include/__algorithm/comp.h
+++ b/libcxx/include/__algorithm/comp.h
@@ -10,8 +10,9 @@
 #define _LIBCPP___ALGORITHM_COMP_H
 
 #include <__config>
+#include <__functional/operations.h>
 #include <__type_traits/integral_constant.h>
-#include <__type_traits/predicate_traits.h>
+#include <__type_traits/operation_traits.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -26,8 +27,8 @@ struct __equal_to {
   }
 };
 
-template <class _Lhs, class _Rhs>
-struct __is_trivial_equality_predicate<__equal_to, _Lhs, _Rhs> : true_type {};
+template <>
+struct __desugars_to<__equal_to, std::equal_to<>> : true_type {};
 
 // The definition is required because __less is part of the ABI, but it's empty
 // because all comparisons should be transparent.
diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index b69aeff92bb9289..35e82da15e4d058 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -15,6 +15,7 @@
 #include <__config>
 #include <__functional/identity.h>
 #include <__functional/invoke.h>
+#include <__functional/operations.h>
 #include <__iterator/distance.h>
 #include <__iterator/iterator_traits.h>
 #include <__string/constexpr_c_functions.h>
@@ -23,7 +24,7 @@
 #include <__type_traits/is_constant_evaluated.h>
 #include <__type_traits/is_equality_comparable.h>
 #include <__type_traits/is_volatile.h>
-#include <__type_traits/predicate_traits.h>
+#include <__type_traits/operation_traits.h>
 #include <__utility/move.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -41,13 +42,12 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
   return true;
 }
 
-template <
-    class _Tp,
-    class _Up,
-    class _BinaryPredicate,
-    __enable_if_t<__is_trivial_equality_predicate<_BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value &&
-                      !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
-                  int> = 0>
+template < class _Tp,
+           class _Up,
+           class _BinaryPredicate,
+           __enable_if_t<__desugars_to<_BinaryPredicate, std::equal_to<>>::value && !is_volatile<_Tp>::value &&
+                             !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
+                         int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) {
   return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
@@ -94,12 +94,12 @@ template <class _Tp,
           class _Pred,
           class _Proj1,
           class _Proj2,
-          __enable_if_t<__is_trivial_equality_predicate<_Pred, _Tp, _Up>::value && __is_identity<_Proj1>::value &&
+          __enable_if_t<__desugars_to<_Pred, std::equal_to<>>::value && __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>
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
-    _Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
+_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/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
index a5ca9c89d1ab23b..3f4bc31632956b3 100644
--- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
+++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
@@ -11,6 +11,7 @@
 
 #include <__algorithm/pstl_backends/cpu_backends/backend.h>
 #include <__config>
+#include <__functional/operations.h>
 #include <__iterator/concepts.h>
 #include <__iterator/iterator_traits.h>
 #include <__numeric/transform_reduce.h>
@@ -29,12 +30,11 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <
-    typename _DifferenceType,
-    typename _Tp,
-    typename _BinaryOperation,
-    typename _UnaryOperation,
-    __enable_if_t<__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>, int> = 0>
+template < typename _DifferenceType,
+           typename _Tp,
+           typename _BinaryOperation,
+           typename _UnaryOperation,
+           __enable_if_t<__desugars_to<_BinaryOperation, std::plus<>>::value && is_arithmetic_v<_Tp>, int> = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept {
   _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init)
@@ -43,12 +43,11 @@ __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _Unar
   return __init;
 }
 
-template <
-    typename _Size,
-    typename _Tp,
-    typename _BinaryOperation,
-    typename _UnaryOperation,
-    __enable_if_t<!(__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>), int> = 0>
+template < typename _Size,
+           typename _Tp,
+           typename _BinaryOperation,
+           typename _UnaryOperation,
+           __enable_if_t<!(__desugars_to<_BinaryOperation, std::plus<>>::value && is_arithmetic_v<_Tp>), int> = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept {
   const _Size __block_size = __lane_size / sizeof(_Tp);
diff --git a/libcxx/include/__functional/operations.h b/libcxx/include/__functional/operations.h
index 6cdb89d6b449bcd..d6c8ff547cfbdcd 100644
--- a/libcxx/include/__functional/operations.h
+++ b/libcxx/include/__functional/operations.h
@@ -15,7 +15,6 @@
 #include <__functional/unary_function.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/operation_traits.h>
-#include <__type_traits/predicate_traits.h>
 #include <__utility/forward.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -41,12 +40,12 @@ struct _LIBCPP_TEMPLATE_VIS plus
 };
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus);
 
-template <class _Tp>
-struct __is_trivial_plus_operation<plus<_Tp>, _Tp, _Tp> : true_type {};
+template <class _Pred>
+struct __desugars_to<plus<_Pred>, plus<_Pred>> : true_type {};
 
 #if _LIBCPP_STD_VER >= 14
-template <class _Tp, class _Up>
-struct __is_trivial_plus_operation<plus<>, _Tp, _Up> : true_type {};
+template <>
+struct __desugars_to<plus<>, plus<>> : true_type {};
 #endif
 
 #if _LIBCPP_STD_VER >= 14
@@ -353,11 +352,11 @@ struct _LIBCPP_TEMPLATE_VIS equal_to<void>
 #endif
 
 template <class _Tp>
-struct __is_trivial_equality_predicate<equal_to<_Tp>, _Tp, _Tp> : true_type {};
+struct __desugars_to<equal_to<_Tp>, std::equal_to<_Tp>> : true_type {};
 
 #if _LIBCPP_STD_VER >= 14
-template <class _Tp>
-struct __is_trivial_equality_predicate<equal_to<>, _Tp, _Tp> : true_type {};
+template <>
+struct __desugars_to<equal_to<>, std::equal_to<>> : true_type {};
 #endif
 
 #if _LIBCPP_STD_VER >= 14
diff --git a/libcxx/include/__functional/ranges_operations.h b/libcxx/include/__functional/ranges_operations.h
index c344fc38f98ddd9..22d6f7fef3b3da5 100644
--- a/libcxx/include/__functional/ranges_operations.h
+++ b/libcxx/include/__functional/ranges_operations.h
@@ -13,8 +13,9 @@
 #include <__concepts/equality_comparable.h>
 #include <__concepts/totally_ordered.h>
 #include <__config>
+#include <__functional/operations.h>
 #include <__type_traits/integral_constant.h>
-#include <__type_traits/predicate_traits.h>
+#include <__type_traits/operation_traits.h>
 #include <__utility/forward.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -95,8 +96,8 @@ struct greater_equal {
 
 } // namespace ranges
 
-template <class _Lhs, class _Rhs>
-struct __is_trivial_equality_predicate<ranges::equal_to, _Lhs, _Rhs> : true_type {};
+template <>
+struct __desugars_to<ranges::equal_to, std::equal_to<>> : true_type {};
 
 #endif // _LIBCPP_STD_VER >= 20
 
diff --git a/libcxx/include/__numeric/pstl_transform_reduce.h b/libcxx/include/__numeric/pstl_transform_reduce.h
index 4127ee21e3045c8..1127726046665c0 100644
--- a/libcxx/include/__numeric/pstl_transform_reduce.h
+++ b/libcxx/include/__numeric/pstl_transform_reduce.h
@@ -84,7 +84,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
 }
 
 // This overload doesn't get a customization point because it's trivial to detect (through e.g.
-// __is_trivial_plus_operation) when specializing the more general variant, which should always be preferred
+// __desugars_to) when specializing the more general variant, which should always be preferred
 template <class _ExecutionPolicy,
           class _ForwardIterator1,
           class _ForwardIterator2,
diff --git a/libcxx/include/__type_traits/operation_traits.h b/libcxx/include/__type_traits/operation_traits.h
index 7dda93e9083a404..d03bf6209a6cc77 100644
--- a/libcxx/include/__type_traits/operation_traits.h
+++ b/libcxx/include/__type_traits/operation_traits.h
@@ -18,8 +18,8 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Pred, class _Lhs, class _Rhs>
-struct __is_trivial_plus_operation : false_type {};
+template <class _Pred, class _Reference>
+struct __desugars_to : false_type {};
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/__type_traits/predicate_traits.h b/libcxx/include/__type_traits/predicate_traits.h
deleted file mode 100644
index 872608e6ac3be3f..000000000000000
--- a/libcxx/include/__type_traits/predicate_traits.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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___TYPE_TRAITS_PREDICATE_TRAITS
-#define _LIBCPP___TYPE_TRAITS_PREDICATE_TRAITS
-
-#include <__config>
-#include <__type_traits/integral_constant.h>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-template <class _Pred, class _Lhs, class _Rhs>
-struct __is_trivial_equality_predicate : false_type {};
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___TYPE_TRAITS_PREDICATE_TRAITS
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 26657b78b8440c6..3c08c2fb52ce65f 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2015,7 +2015,6 @@ module std_private_type_traits_nat                                       [system
 module std_private_type_traits_negation                                  [system] { header "__type_traits/negation.h" }
 module std_private_type_traits_noexcept_move_assign_container            [system] { header "__type_traits/noexcept_move_assign_container.h" }
 module std_private_type_traits_operation_traits                          [system] { header "__type_traits/operation_traits.h" }
-module std_private_type_traits_predicate_traits                          [system] { header "__type_traits/predicate_traits.h" }
 module std_private_type_traits_promote                                   [system] { header "__type_traits/promote.h" }
 module std_private_type_traits_rank                                      [system] { header "__type_traits/rank.h" }
 module std_private_type_traits_remove_all_extents                        [system] { header "__type_traits/remove_all_extents.h" }

>From 299ab77b90fbfc8f63076a3b897ce3217c5d9bb4 Mon Sep 17 00:00:00 2001
From: AntonRydahl <rydahl2610 at gmail.com>
Date: Fri, 13 Oct 2023 12:05:49 -0700
Subject: [PATCH 2/5] Resolving suggested changes

---
 libcxx/include/__algorithm/comp.h                |  2 +-
 libcxx/include/__algorithm/equal.h               |  4 ++--
 .../cpu_backends/transform_reduce.h              |  4 ++--
 libcxx/include/__functional/operations.h         | 16 +++-------------
 libcxx/include/__type_traits/operation_traits.h  |  5 ++++-
 5 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/libcxx/include/__algorithm/comp.h b/libcxx/include/__algorithm/comp.h
index 0993c37cce36a6b..3624a26a7d6d771 100644
--- a/libcxx/include/__algorithm/comp.h
+++ b/libcxx/include/__algorithm/comp.h
@@ -28,7 +28,7 @@ struct __equal_to {
 };
 
 template <>
-struct __desugars_to<__equal_to, std::equal_to<>> : true_type {};
+struct __desugars_to<__equal_to, equal_to<void>> : true_type {};
 
 // The definition is required because __less is part of the ABI, but it's empty
 // because all comparisons should be transparent.
diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index 35e82da15e4d058..116d1a903e50716 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -45,7 +45,7 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
 template < class _Tp,
            class _Up,
            class _BinaryPredicate,
-           __enable_if_t<__desugars_to<_BinaryPredicate, std::equal_to<>>::value && !is_volatile<_Tp>::value &&
+           __enable_if_t<__desugars_to<_BinaryPredicate, equal_to<_Tp>>::value && !is_volatile<_Tp>::value &&
                              !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
                          int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
@@ -94,7 +94,7 @@ template <class _Tp,
           class _Pred,
           class _Proj1,
           class _Proj2,
-          __enable_if_t<__desugars_to<_Pred, std::equal_to<>>::value && __is_identity<_Proj1>::value &&
+          __enable_if_t<__desugars_to<_Pred, equal_to<_Tp>>::value && __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>
diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
index 3f4bc31632956b3..c238d1475aec9db 100644
--- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
+++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
@@ -34,7 +34,7 @@ template < typename _DifferenceType,
            typename _Tp,
            typename _BinaryOperation,
            typename _UnaryOperation,
-           __enable_if_t<__desugars_to<_BinaryOperation, std::plus<>>::value && is_arithmetic_v<_Tp>, int> = 0>
+           __enable_if_t<__desugars_to<_BinaryOperation, plus<_Tp>>::value && is_arithmetic_v<_Tp>, int> = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept {
   _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init)
@@ -47,7 +47,7 @@ template < typename _Size,
            typename _Tp,
            typename _BinaryOperation,
            typename _UnaryOperation,
-           __enable_if_t<!(__desugars_to<_BinaryOperation, std::plus<>>::value && is_arithmetic_v<_Tp>), int> = 0>
+           __enable_if_t<!(__desugars_to<_BinaryOperation, plus<_Tp>>::value && is_arithmetic_v<_Tp>), int> = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept {
   const _Size __block_size = __lane_size / sizeof(_Tp);
diff --git a/libcxx/include/__functional/operations.h b/libcxx/include/__functional/operations.h
index d6c8ff547cfbdcd..19ea9ab46ff7270 100644
--- a/libcxx/include/__functional/operations.h
+++ b/libcxx/include/__functional/operations.h
@@ -40,13 +40,8 @@ struct _LIBCPP_TEMPLATE_VIS plus
 };
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus);
 
-template <class _Pred>
-struct __desugars_to<plus<_Pred>, plus<_Pred>> : true_type {};
-
-#if _LIBCPP_STD_VER >= 14
-template <>
-struct __desugars_to<plus<>, plus<>> : true_type {};
-#endif
+template <class _Tp>
+struct __desugars_to<plus<_Tp>, plus<void>> : true_type {};
 
 #if _LIBCPP_STD_VER >= 14
 template <>
@@ -352,12 +347,7 @@ struct _LIBCPP_TEMPLATE_VIS equal_to<void>
 #endif
 
 template <class _Tp>
-struct __desugars_to<equal_to<_Tp>, std::equal_to<_Tp>> : true_type {};
-
-#if _LIBCPP_STD_VER >= 14
-template <>
-struct __desugars_to<equal_to<>, std::equal_to<>> : true_type {};
-#endif
+struct __desugars_to<equal_to<_Tp>, equal_to<void>> : true_type {};
 
 #if _LIBCPP_STD_VER >= 14
 template <class _Tp = void>
diff --git a/libcxx/include/__type_traits/operation_traits.h b/libcxx/include/__type_traits/operation_traits.h
index d03bf6209a6cc77..7dd7ef7c9d23d39 100644
--- a/libcxx/include/__type_traits/operation_traits.h
+++ b/libcxx/include/__type_traits/operation_traits.h
@@ -18,9 +18,12 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Pred, class _Reference>
+template <class _Operation, class _Canonical>
 struct __desugars_to : false_type {};
 
+template <class _Operation>
+struct __desugars_to<_Operation, _Operation> : true_type {};
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___TYPE_TRAITS_OPERATION_TRAITS_H

>From f59a38b4ec854fdbcba24b318c6cd746c2fb136c Mon Sep 17 00:00:00 2001
From: AntonRydahl <rydahl2610 at gmail.com>
Date: Fri, 13 Oct 2023 15:25:44 -0700
Subject: [PATCH 3/5] Attempt to fix -std=gnu++03 related errors

---
 libcxx/include/__algorithm/comp.h                             | 2 +-
 libcxx/include/__algorithm/equal.h                            | 4 ++--
 .../__algorithm/pstl_backends/cpu_backends/transform_reduce.h | 4 ++--
 libcxx/include/__functional/operations.h                      | 4 ++--
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libcxx/include/__algorithm/comp.h b/libcxx/include/__algorithm/comp.h
index 3624a26a7d6d771..38fd28427430002 100644
--- a/libcxx/include/__algorithm/comp.h
+++ b/libcxx/include/__algorithm/comp.h
@@ -28,7 +28,7 @@ struct __equal_to {
 };
 
 template <>
-struct __desugars_to<__equal_to, equal_to<void>> : true_type {};
+struct __desugars_to<__equal_to, equal_to<void> > : true_type {};
 
 // The definition is required because __less is part of the ABI, but it's empty
 // because all comparisons should be transparent.
diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index 116d1a903e50716..320c84df3641e3d 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -45,7 +45,7 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
 template < class _Tp,
            class _Up,
            class _BinaryPredicate,
-           __enable_if_t<__desugars_to<_BinaryPredicate, equal_to<_Tp>>::value && !is_volatile<_Tp>::value &&
+           __enable_if_t<__desugars_to<_BinaryPredicate, equal_to<_Tp> >::value && !is_volatile<_Tp>::value &&
                              !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
                          int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
@@ -94,7 +94,7 @@ template <class _Tp,
           class _Pred,
           class _Proj1,
           class _Proj2,
-          __enable_if_t<__desugars_to<_Pred, equal_to<_Tp>>::value && __is_identity<_Proj1>::value &&
+          __enable_if_t<__desugars_to<_Pred, equal_to<_Tp> >::value && __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>
diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
index c238d1475aec9db..245eda5388622d5 100644
--- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
+++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
@@ -34,7 +34,7 @@ template < typename _DifferenceType,
            typename _Tp,
            typename _BinaryOperation,
            typename _UnaryOperation,
-           __enable_if_t<__desugars_to<_BinaryOperation, plus<_Tp>>::value && is_arithmetic_v<_Tp>, int> = 0>
+           __enable_if_t<__desugars_to<_BinaryOperation, plus<_Tp> >::value && is_arithmetic_v<_Tp>, int> = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept {
   _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init)
@@ -47,7 +47,7 @@ template < typename _Size,
            typename _Tp,
            typename _BinaryOperation,
            typename _UnaryOperation,
-           __enable_if_t<!(__desugars_to<_BinaryOperation, plus<_Tp>>::value && is_arithmetic_v<_Tp>), int> = 0>
+           __enable_if_t<!(__desugars_to<_BinaryOperation, plus<_Tp> >::value && is_arithmetic_v<_Tp>), int> = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept {
   const _Size __block_size = __lane_size / sizeof(_Tp);
diff --git a/libcxx/include/__functional/operations.h b/libcxx/include/__functional/operations.h
index 19ea9ab46ff7270..4f734cac7c6772a 100644
--- a/libcxx/include/__functional/operations.h
+++ b/libcxx/include/__functional/operations.h
@@ -41,7 +41,7 @@ struct _LIBCPP_TEMPLATE_VIS plus
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus);
 
 template <class _Tp>
-struct __desugars_to<plus<_Tp>, plus<void>> : true_type {};
+struct __desugars_to<plus<_Tp>, plus<void> > : true_type {};
 
 #if _LIBCPP_STD_VER >= 14
 template <>
@@ -347,7 +347,7 @@ struct _LIBCPP_TEMPLATE_VIS equal_to<void>
 #endif
 
 template <class _Tp>
-struct __desugars_to<equal_to<_Tp>, equal_to<void>> : true_type {};
+struct __desugars_to<equal_to<_Tp>, equal_to<void> > : true_type {};
 
 #if _LIBCPP_STD_VER >= 14
 template <class _Tp = void>

>From 7c35b004090c90320db3e4165f288ba146173aa9 Mon Sep 17 00:00:00 2001
From: AntonRydahl <rydahl2610 at gmail.com>
Date: Sun, 15 Oct 2023 20:45:16 -0700
Subject: [PATCH 4/5] Only optimizing __equal_impl for is_equal<void>

---
 libcxx/include/__algorithm/equal.h       | 4 ++--
 libcxx/include/__functional/operations.h | 6 ------
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index 320c84df3641e3d..188c40f482c90b1 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -45,7 +45,7 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
 template < class _Tp,
            class _Up,
            class _BinaryPredicate,
-           __enable_if_t<__desugars_to<_BinaryPredicate, equal_to<_Tp> >::value && !is_volatile<_Tp>::value &&
+           __enable_if_t<__desugars_to<_BinaryPredicate, equal_to<void> >::value && !is_volatile<_Tp>::value &&
                              !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
                          int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
@@ -94,7 +94,7 @@ template <class _Tp,
           class _Pred,
           class _Proj1,
           class _Proj2,
-          __enable_if_t<__desugars_to<_Pred, equal_to<_Tp> >::value && __is_identity<_Proj1>::value &&
+          __enable_if_t<__desugars_to<_Pred, equal_to<void> >::value && __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>
diff --git a/libcxx/include/__functional/operations.h b/libcxx/include/__functional/operations.h
index 4f734cac7c6772a..6b489a0fb439c8a 100644
--- a/libcxx/include/__functional/operations.h
+++ b/libcxx/include/__functional/operations.h
@@ -40,9 +40,6 @@ struct _LIBCPP_TEMPLATE_VIS plus
 };
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus);
 
-template <class _Tp>
-struct __desugars_to<plus<_Tp>, plus<void> > : true_type {};
-
 #if _LIBCPP_STD_VER >= 14
 template <>
 struct _LIBCPP_TEMPLATE_VIS plus<void>
@@ -346,9 +343,6 @@ struct _LIBCPP_TEMPLATE_VIS equal_to<void>
 };
 #endif
 
-template <class _Tp>
-struct __desugars_to<equal_to<_Tp>, equal_to<void> > : true_type {};
-
 #if _LIBCPP_STD_VER >= 14
 template <class _Tp = void>
 #else

>From 3d33a69ffa250c12e129dd8bcfd799b4604590f7 Mon Sep 17 00:00:00 2001
From: AntonRydahl <rydahl2610 at gmail.com>
Date: Sun, 5 Nov 2023 12:55:06 -0800
Subject: [PATCH 5/5] Update __desugars_to to compare againts tags rather than
 transparent predicates

---
 libcxx/include/__algorithm/equal.h            |  4 +-
 .../cpu_backends/transform_reduce.h           | 17 ++++++---
 libcxx/include/__functional/operations.h      | 22 +++++++++++
 .../include/__functional/ranges_operations.h  |  6 ++-
 .../include/__type_traits/operation_traits.h  | 11 ++++--
 .../pstl.transform_reduce.string.pass.cpp     | 38 +++++++++++++++++++
 6 files changed, 84 insertions(+), 14 deletions(-)
 create mode 100644 libcxx/test/libcxx/algorithms/pstl.transform_reduce.string.pass.cpp

diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index 188c40f482c90b1..7979628b7446bf9 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -45,7 +45,7 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
 template < class _Tp,
            class _Up,
            class _BinaryPredicate,
-           __enable_if_t<__desugars_to<_BinaryPredicate, equal_to<void> >::value && !is_volatile<_Tp>::value &&
+           __enable_if_t<__desugars_to<__equal_tag, _BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value &&
                              !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
                          int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
@@ -94,7 +94,7 @@ template <class _Tp,
           class _Pred,
           class _Proj1,
           class _Proj2,
-          __enable_if_t<__desugars_to<_Pred, equal_to<void> >::value && __is_identity<_Proj1>::value &&
+          __enable_if_t<__desugars_to<__equal_tag, _Pred, _Tp, _Up>::value && __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>
diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
index 245eda5388622d5..0786d3f24cf85ab 100644
--- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
+++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
@@ -34,7 +34,9 @@ template < typename _DifferenceType,
            typename _Tp,
            typename _BinaryOperation,
            typename _UnaryOperation,
-           __enable_if_t<__desugars_to<_BinaryOperation, plus<_Tp> >::value && is_arithmetic_v<_Tp>, int> = 0>
+           typename _UnaryResult = invoke_result_t<_UnaryOperation, _DifferenceType>,
+           __enable_if_t<__desugars_to<__plus_tag, _BinaryOperation, _Tp, _UnaryResult>::value && is_arithmetic_v<_Tp>,
+                         int>    = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept {
   _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init)
@@ -43,11 +45,14 @@ __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _Unar
   return __init;
 }
 
-template < typename _Size,
-           typename _Tp,
-           typename _BinaryOperation,
-           typename _UnaryOperation,
-           __enable_if_t<!(__desugars_to<_BinaryOperation, plus<_Tp> >::value && is_arithmetic_v<_Tp>), int> = 0>
+template <
+    typename _Size,
+    typename _Tp,
+    typename _BinaryOperation,
+    typename _UnaryOperation,
+    typename _UnaryResult = invoke_result_t<_UnaryOperation, _Size>,
+    __enable_if_t<!(__desugars_to<__plus_tag, _BinaryOperation, _Tp, _UnaryResult>::value && is_arithmetic_v<_Tp>),
+                  int>    = 0>
 _LIBCPP_HIDE_FROM_ABI _Tp
 __simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept {
   const _Size __block_size = __lane_size / sizeof(_Tp);
diff --git a/libcxx/include/__functional/operations.h b/libcxx/include/__functional/operations.h
index 6b489a0fb439c8a..30554d97ab238ff 100644
--- a/libcxx/include/__functional/operations.h
+++ b/libcxx/include/__functional/operations.h
@@ -40,6 +40,17 @@ struct _LIBCPP_TEMPLATE_VIS plus
 };
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus);
 
+// For the typed version of plus, we require that the left- and right-hand
+// side of the plus operator matches
+template <class _Tp>
+struct __desugars_to<__plus_tag, plus<_Tp>, _Tp, _Tp> : true_type {};
+
+#if _LIBCPP_STD_VER >= 14
+// In the transparent case, we do not enforce that
+template <class _Tp, class _Up>
+struct __desugars_to<__plus_tag, plus<void>, _Tp, _Up> : true_type {};
+#endif
+
 #if _LIBCPP_STD_VER >= 14
 template <>
 struct _LIBCPP_TEMPLATE_VIS plus<void>
@@ -343,6 +354,17 @@ struct _LIBCPP_TEMPLATE_VIS equal_to<void>
 };
 #endif
 
+// For the typed version of equal_to, we require that the left- and right-hand
+// side of the equality operator matches
+template <class _Tp>
+struct __desugars_to<__equal_tag, equal_to<_Tp>, _Tp, _Tp> : true_type {};
+
+#if _LIBCPP_STD_VER >= 14
+// In the transparent case, we do not enforce that
+template <class _Tp, class _Up>
+struct __desugars_to<__equal_tag, equal_to<void>, _Tp, _Up> : true_type {};
+#endif
+
 #if _LIBCPP_STD_VER >= 14
 template <class _Tp = void>
 #else
diff --git a/libcxx/include/__functional/ranges_operations.h b/libcxx/include/__functional/ranges_operations.h
index 22d6f7fef3b3da5..eee3442a3ef0e8f 100644
--- a/libcxx/include/__functional/ranges_operations.h
+++ b/libcxx/include/__functional/ranges_operations.h
@@ -96,8 +96,10 @@ struct greater_equal {
 
 } // namespace ranges
 
-template <>
-struct __desugars_to<ranges::equal_to, std::equal_to<>> : true_type {};
+// For ranges we do not require that the types on each side of the equality
+// operator are of the same type
+template <class _Tp, class _Up>
+struct __desugars_to<__equal_tag, ranges::equal_to, _Tp, _Up> : true_type {};
 
 #endif // _LIBCPP_STD_VER >= 20
 
diff --git a/libcxx/include/__type_traits/operation_traits.h b/libcxx/include/__type_traits/operation_traits.h
index 7dd7ef7c9d23d39..5774e14ab091200 100644
--- a/libcxx/include/__type_traits/operation_traits.h
+++ b/libcxx/include/__type_traits/operation_traits.h
@@ -18,11 +18,14 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Operation, class _Canonical>
-struct __desugars_to : false_type {};
+// Tags to represent the canonical operations
+struct __equal_tag {};
+struct __plus_tag {};
+
+// In the general case, __desugars_to is false
 
-template <class _Operation>
-struct __desugars_to<_Operation, _Operation> : true_type {};
+template <class _CanonicalTag, class _Operation, class... _Args>
+struct __desugars_to : false_type {};
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/test/libcxx/algorithms/pstl.transform_reduce.string.pass.cpp b/libcxx/test/libcxx/algorithms/pstl.transform_reduce.string.pass.cpp
new file mode 100644
index 000000000000000..ced0e6a23da77ac
--- /dev/null
+++ b/libcxx/test/libcxx/algorithms/pstl.transform_reduce.string.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// This test verifies that you can make string reductions with parallel
+// algorithms
+
+#include <algorithm>
+#include <cassert>
+#include <execution>
+#include <vector>
+
+int main(int, char**) {
+  int length = 10000;
+  std::vector<std::string> vec(length);
+  for (int i = 0; i < length; i++) {
+    std::string str = "";
+    char a;
+    for (int j = 0; j < 5; j++) {
+      a = 56 + (((int)i * 5 + 3 * j) % 200);
+      str += a;
+    }
+    vec[i] = str;
+  }
+
+  std::string result = std::transform_reduce(
+      std::execution::par_unseq, vec.begin(), vec.end(), (std::string) "", std::plus{}, [](std::string& str) {
+        return str;
+      });
+  for (auto v : vec) {
+    assert(result.find(v) != std::string::npos && "Substring not found in deruced string.");
+  }
+  return 0;
+}
\ No newline at end of file



More information about the libc-commits mailing list