Skip to content

Commit aea7929

Browse files
AntonRydahlldionne
andauthored
[libc++] Unify __is_trivial_equality_predicate and __is_trivial_plus_operation into __desugars_to (#68642)
When working on an OpenMP offloading backend for standard parallel algorithms (#66968) we noticed the need of a generalization of `__is_trivial_plus_operation`. This patch merges `__is_trivial_equality_predicate` and `__is_trivial_plus_operation` into `__desugars_to`, and in the future we might extend the latter to support other binary operations as well. Co-authored-by: Louis Dionne <[email protected]>
1 parent 07d799f commit aea7929

File tree

10 files changed

+61
-70
lines changed

10 files changed

+61
-70
lines changed

libcxx/include/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,6 @@ set(files
816816
__type_traits/negation.h
817817
__type_traits/noexcept_move_assign_container.h
818818
__type_traits/operation_traits.h
819-
__type_traits/predicate_traits.h
820819
__type_traits/promote.h
821820
__type_traits/rank.h
822821
__type_traits/remove_all_extents.h

libcxx/include/__algorithm/comp.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#include <__config>
1313
#include <__type_traits/integral_constant.h>
14-
#include <__type_traits/predicate_traits.h>
14+
#include <__type_traits/operation_traits.h>
1515

1616
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1717
# pragma GCC system_header
@@ -26,8 +26,8 @@ struct __equal_to {
2626
}
2727
};
2828

29-
template <class _Lhs, class _Rhs>
30-
struct __is_trivial_equality_predicate<__equal_to, _Lhs, _Rhs> : true_type {};
29+
template <class _Tp, class _Up>
30+
struct __desugars_to<__equal_tag, __equal_to, _Tp, _Up> : true_type {};
3131

3232
// The definition is required because __less is part of the ABI, but it's empty
3333
// because all comparisons should be transparent.

libcxx/include/__algorithm/equal.h

+10-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <__type_traits/is_constant_evaluated.h>
2424
#include <__type_traits/is_equality_comparable.h>
2525
#include <__type_traits/is_volatile.h>
26-
#include <__type_traits/predicate_traits.h>
26+
#include <__type_traits/operation_traits.h>
2727
#include <__utility/move.h>
2828

2929
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -41,13 +41,12 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
4141
return true;
4242
}
4343

44-
template <
45-
class _Tp,
46-
class _Up,
47-
class _BinaryPredicate,
48-
__enable_if_t<__is_trivial_equality_predicate<_BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value &&
49-
!is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
50-
int> = 0>
44+
template <class _Tp,
45+
class _Up,
46+
class _BinaryPredicate,
47+
__enable_if_t<__desugars_to<__equal_tag, _BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value &&
48+
!is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
49+
int> = 0>
5150
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
5251
__equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) {
5352
return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
@@ -94,12 +93,12 @@ template <class _Tp,
9493
class _Pred,
9594
class _Proj1,
9695
class _Proj2,
97-
__enable_if_t<__is_trivial_equality_predicate<_Pred, _Tp, _Up>::value && __is_identity<_Proj1>::value &&
96+
__enable_if_t<__desugars_to<__equal_tag, _Pred, _Tp, _Up>::value && __is_identity<_Proj1>::value &&
9897
__is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value &&
9998
__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
10099
int> = 0>
101-
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
102-
_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
100+
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
101+
__equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
103102
return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
104103
}
105104

libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h

+16-12
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@
2929

3030
_LIBCPP_BEGIN_NAMESPACE_STD
3131

32-
template <
33-
typename _DifferenceType,
34-
typename _Tp,
35-
typename _BinaryOperation,
36-
typename _UnaryOperation,
37-
__enable_if_t<__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>, int> = 0>
32+
template <typename _DifferenceType,
33+
typename _Tp,
34+
typename _BinaryOperation,
35+
typename _UnaryOperation,
36+
typename _UnaryResult = invoke_result_t<_UnaryOperation, _DifferenceType>,
37+
__enable_if_t<__desugars_to<__plus_tag, _BinaryOperation, _Tp, _UnaryResult>::value && is_arithmetic_v<_Tp> &&
38+
is_arithmetic_v<_UnaryResult>,
39+
int> = 0>
3840
_LIBCPP_HIDE_FROM_ABI _Tp
3941
__simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept {
4042
_PSTL_PRAGMA_SIMD_REDUCTION(+ : __init)
@@ -43,12 +45,14 @@ __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _Unar
4345
return __init;
4446
}
4547

46-
template <
47-
typename _Size,
48-
typename _Tp,
49-
typename _BinaryOperation,
50-
typename _UnaryOperation,
51-
__enable_if_t<!(__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>), int> = 0>
48+
template <typename _Size,
49+
typename _Tp,
50+
typename _BinaryOperation,
51+
typename _UnaryOperation,
52+
typename _UnaryResult = invoke_result_t<_UnaryOperation, _Size>,
53+
__enable_if_t<!(__desugars_to<__plus_tag, _BinaryOperation, _Tp, _UnaryResult>::value &&
54+
is_arithmetic_v<_Tp> && is_arithmetic_v<_UnaryResult>),
55+
int> = 0>
5256
_LIBCPP_HIDE_FROM_ABI _Tp
5357
__simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept {
5458
const _Size __block_size = __lane_size / sizeof(_Tp);

libcxx/include/__functional/operations.h

+10-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <__functional/unary_function.h>
1616
#include <__type_traits/integral_constant.h>
1717
#include <__type_traits/operation_traits.h>
18-
#include <__type_traits/predicate_traits.h>
1918
#include <__utility/forward.h>
2019

2120
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -41,13 +40,13 @@ struct _LIBCPP_TEMPLATE_VIS plus
4140
};
4241
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus);
4342

43+
// The non-transparent std::plus specialization is only equivalent to a raw plus
44+
// operator when we don't perform an implicit conversion when calling it.
4445
template <class _Tp>
45-
struct __is_trivial_plus_operation<plus<_Tp>, _Tp, _Tp> : true_type {};
46+
struct __desugars_to<__plus_tag, plus<_Tp>, _Tp, _Tp> : true_type {};
4647

47-
#if _LIBCPP_STD_VER >= 14
4848
template <class _Tp, class _Up>
49-
struct __is_trivial_plus_operation<plus<>, _Tp, _Up> : true_type {};
50-
#endif
49+
struct __desugars_to<__plus_tag, plus<void>, _Tp, _Up> : true_type {};
5150

5251
#if _LIBCPP_STD_VER >= 14
5352
template <>
@@ -352,13 +351,14 @@ struct _LIBCPP_TEMPLATE_VIS equal_to<void>
352351
};
353352
#endif
354353

354+
// The non-transparent std::equal_to specialization is only equivalent to a raw equality
355+
// comparison when we don't perform an implicit conversion when calling it.
355356
template <class _Tp>
356-
struct __is_trivial_equality_predicate<equal_to<_Tp>, _Tp, _Tp> : true_type {};
357+
struct __desugars_to<__equal_tag, equal_to<_Tp>, _Tp, _Tp> : true_type {};
357358

358-
#if _LIBCPP_STD_VER >= 14
359-
template <class _Tp>
360-
struct __is_trivial_equality_predicate<equal_to<>, _Tp, _Tp> : true_type {};
361-
#endif
359+
// In the transparent case, we do not enforce that
360+
template <class _Tp, class _Up>
361+
struct __desugars_to<__equal_tag, equal_to<void>, _Tp, _Up> : true_type {};
362362

363363
#if _LIBCPP_STD_VER >= 14
364364
template <class _Tp = void>

libcxx/include/__functional/ranges_operations.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <__concepts/totally_ordered.h>
1515
#include <__config>
1616
#include <__type_traits/integral_constant.h>
17-
#include <__type_traits/predicate_traits.h>
17+
#include <__type_traits/operation_traits.h>
1818
#include <__utility/forward.h>
1919

2020
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -95,8 +95,10 @@ struct greater_equal {
9595

9696
} // namespace ranges
9797

98-
template <class _Lhs, class _Rhs>
99-
struct __is_trivial_equality_predicate<ranges::equal_to, _Lhs, _Rhs> : true_type {};
98+
// For ranges we do not require that the types on each side of the equality
99+
// operator are of the same type
100+
template <class _Tp, class _Up>
101+
struct __desugars_to<__equal_tag, ranges::equal_to, _Tp, _Up> : true_type {};
100102

101103
#endif // _LIBCPP_STD_VER >= 20
102104

libcxx/include/__numeric/pstl_transform_reduce.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
8484
}
8585

8686
// This overload doesn't get a customization point because it's trivial to detect (through e.g.
87-
// __is_trivial_plus_operation) when specializing the more general variant, which should always be preferred
87+
// __desugars_to) when specializing the more general variant, which should always be preferred
8888
template <class _ExecutionPolicy,
8989
class _ForwardIterator1,
9090
class _ForwardIterator2,

libcxx/include/__type_traits/operation_traits.h

+16-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,22 @@
1818

1919
_LIBCPP_BEGIN_NAMESPACE_STD
2020

21-
template <class _Pred, class _Lhs, class _Rhs>
22-
struct __is_trivial_plus_operation : false_type {};
21+
// Tags to represent the canonical operations
22+
struct __equal_tag {};
23+
struct __plus_tag {};
24+
25+
// This class template is used to determine whether an operation "desugars"
26+
// (or boils down) to a given canonical operation.
27+
//
28+
// For example, `std::equal_to<>`, our internal `std::__equal_to` helper and
29+
// `ranges::equal_to` are all just fancy ways of representing a transparent
30+
// equality operation, so they all desugar to `__equal_tag`.
31+
//
32+
// This is useful to optimize some functions in cases where we know e.g. the
33+
// predicate being passed is actually going to call a builtin operator, or has
34+
// some specific semantics.
35+
template <class _CanonicalTag, class _Operation, class... _Args>
36+
struct __desugars_to : false_type {};
2337

2438
_LIBCPP_END_NAMESPACE_STD
2539

libcxx/include/__type_traits/predicate_traits.h

-26
This file was deleted.

libcxx/include/module.modulemap.in

-1
Original file line numberDiff line numberDiff line change
@@ -2013,7 +2013,6 @@ module std_private_type_traits_nat [system
20132013
module std_private_type_traits_negation [system] { header "__type_traits/negation.h" }
20142014
module std_private_type_traits_noexcept_move_assign_container [system] { header "__type_traits/noexcept_move_assign_container.h" }
20152015
module std_private_type_traits_operation_traits [system] { header "__type_traits/operation_traits.h" }
2016-
module std_private_type_traits_predicate_traits [system] { header "__type_traits/predicate_traits.h" }
20172016
module std_private_type_traits_promote [system] { header "__type_traits/promote.h" }
20182017
module std_private_type_traits_rank [system] { header "__type_traits/rank.h" }
20192018
module std_private_type_traits_remove_all_extents [system] { header "__type_traits/remove_all_extents.h" }

0 commit comments

Comments
 (0)