2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
11 #define _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
13 #include <__type_traits/is_arithmetic.h>
14 #include <__type_traits/is_const.h>
15 #include <__type_traits/is_constant_evaluated.h>
16 #include <__type_traits/is_convertible.h>
17 #include <__type_traits/is_same.h>
18 #include <__type_traits/is_unsigned.h>
19 #include <__type_traits/is_volatile.h>
20 #include <__type_traits/void_t.h>
21 #include <__utility/declval.h>
22 #include <__utility/integer_sequence.h>
27 #include <__undef_macros>
29 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
31 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
32 inline namespace parallelism_v2
{
34 inline constexpr bool __is_vectorizable_v
=
35 is_arithmetic_v
<_Tp
> && !is_const_v
<_Tp
> && !is_volatile_v
<_Tp
> && !is_same_v
<_Tp
, bool>;
38 _LIBCPP_HIDE_FROM_ABI
auto __choose_mask_type() {
39 if constexpr (sizeof(_Tp
) == 1) {
41 } else if constexpr (sizeof(_Tp
) == 2) {
43 } else if constexpr (sizeof(_Tp
) == 4) {
45 } else if constexpr (sizeof(_Tp
) == 8) {
48 # ifndef _LIBCPP_HAS_NO_INT128
49 else if constexpr (sizeof(_Tp
) == 16) {
54 static_assert(sizeof(_Tp
) == 0, "Unexpected size");
58 _LIBCPP_HIDE_FROM_ABI
auto constexpr __set_all_bits(bool __v
) {
59 return __v
? (numeric_limits
<decltype(__choose_mask_type
<_Tp
>())>::max()) : 0;
62 template <class _From
, class _To
, class = void>
63 inline constexpr bool __is_non_narrowing_convertible_v
= false;
65 template <class _From
, class _To
>
66 inline constexpr bool __is_non_narrowing_convertible_v
<_From
, _To
, std::void_t
<decltype(_To
{std::declval
<_From
>()})>> =
69 template <class _Tp
, class _Up
>
70 inline constexpr bool __can_broadcast_v
=
71 (__is_vectorizable_v
<_Up
> && __is_non_narrowing_convertible_v
<_Up
, _Tp
>) ||
72 (!__is_vectorizable_v
<_Up
> && is_convertible_v
<_Up
, _Tp
>) || is_same_v
<_Up
, int> ||
73 (is_same_v
<_Up
, unsigned int> && is_unsigned_v
<_Tp
>);
75 template <class _Tp
, class _Generator
, std::size_t _Idx
, class = void>
76 inline constexpr bool __is_well_formed
= false;
78 template <class _Tp
, class _Generator
, std::size_t _Idx
>
83 std::void_t
<decltype(std::declval
<_Generator
>()(integral_constant
<size_t, _Idx
>()))>> =
84 __can_broadcast_v
<_Tp
, decltype(std::declval
<_Generator
>()(integral_constant
<size_t, _Idx
>()))>;
86 template <class _Tp
, class _Generator
, std::size_t... _Idxes
>
87 _LIBCPP_HIDE_FROM_ABI
constexpr bool __can_generate(index_sequence
<_Idxes
...>) {
88 return (true && ... && __is_well_formed
<_Tp
, _Generator
, _Idxes
>);
91 template <class _Tp
, class _Generator
, std::size_t _Size
>
92 inline constexpr bool __can_generate_v
= experimental::__can_generate
<_Tp
, _Generator
>(make_index_sequence
<_Size
>());
94 } // namespace parallelism_v2
95 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
97 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
101 #endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H