xref: /freebsd-src/contrib/llvm-project/libcxx/include/experimental/__simd/utility.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1*5f757f3fSDimitry Andric // -*- C++ -*-
2*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
3*5f757f3fSDimitry Andric //
4*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*5f757f3fSDimitry Andric //
8*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
9*5f757f3fSDimitry Andric 
10*5f757f3fSDimitry Andric #ifndef _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
11*5f757f3fSDimitry Andric #define _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
12*5f757f3fSDimitry Andric 
13*5f757f3fSDimitry Andric #include <__type_traits/is_arithmetic.h>
14*5f757f3fSDimitry Andric #include <__type_traits/is_const.h>
15*5f757f3fSDimitry Andric #include <__type_traits/is_constant_evaluated.h>
16*5f757f3fSDimitry Andric #include <__type_traits/is_convertible.h>
17*5f757f3fSDimitry Andric #include <__type_traits/is_same.h>
18*5f757f3fSDimitry Andric #include <__type_traits/is_unsigned.h>
19*5f757f3fSDimitry Andric #include <__type_traits/is_volatile.h>
20*5f757f3fSDimitry Andric #include <__type_traits/void_t.h>
21*5f757f3fSDimitry Andric #include <__utility/declval.h>
22*5f757f3fSDimitry Andric #include <__utility/integer_sequence.h>
23*5f757f3fSDimitry Andric #include <cstddef>
24*5f757f3fSDimitry Andric #include <cstdint>
25*5f757f3fSDimitry Andric #include <experimental/__config>
26*5f757f3fSDimitry Andric #include <limits>
27*5f757f3fSDimitry Andric 
28*5f757f3fSDimitry Andric _LIBCPP_PUSH_MACROS
29*5f757f3fSDimitry Andric #include <__undef_macros>
30*5f757f3fSDimitry Andric 
31*5f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
32*5f757f3fSDimitry Andric 
33*5f757f3fSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
34*5f757f3fSDimitry Andric inline namespace parallelism_v2 {
35*5f757f3fSDimitry Andric template <class _Tp>
36*5f757f3fSDimitry Andric inline constexpr bool __is_vectorizable_v =
37*5f757f3fSDimitry Andric     is_arithmetic_v<_Tp> && !is_const_v<_Tp> && !is_volatile_v<_Tp> && !is_same_v<_Tp, bool>;
38*5f757f3fSDimitry Andric 
39*5f757f3fSDimitry Andric template <class _Tp>
__choose_mask_type()40*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI auto __choose_mask_type() {
41*5f757f3fSDimitry Andric   if constexpr (sizeof(_Tp) == 1) {
42*5f757f3fSDimitry Andric     return uint8_t{};
43*5f757f3fSDimitry Andric   } else if constexpr (sizeof(_Tp) == 2) {
44*5f757f3fSDimitry Andric     return uint16_t{};
45*5f757f3fSDimitry Andric   } else if constexpr (sizeof(_Tp) == 4) {
46*5f757f3fSDimitry Andric     return uint32_t{};
47*5f757f3fSDimitry Andric   } else if constexpr (sizeof(_Tp) == 8) {
48*5f757f3fSDimitry Andric     return uint64_t{};
49*5f757f3fSDimitry Andric   }
50*5f757f3fSDimitry Andric #  ifndef _LIBCPP_HAS_NO_INT128
51*5f757f3fSDimitry Andric   else if constexpr (sizeof(_Tp) == 16) {
52*5f757f3fSDimitry Andric     return __uint128_t{};
53*5f757f3fSDimitry Andric   }
54*5f757f3fSDimitry Andric #  endif
55*5f757f3fSDimitry Andric   else
56*5f757f3fSDimitry Andric     static_assert(sizeof(_Tp) == 0, "Unexpected size");
57*5f757f3fSDimitry Andric }
58*5f757f3fSDimitry Andric 
59*5f757f3fSDimitry Andric template <class _Tp>
__set_all_bits(bool __v)60*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI auto constexpr __set_all_bits(bool __v) {
61*5f757f3fSDimitry Andric   return __v ? (numeric_limits<decltype(__choose_mask_type<_Tp>())>::max()) : 0;
62*5f757f3fSDimitry Andric }
63*5f757f3fSDimitry Andric 
64*5f757f3fSDimitry Andric template <class _From, class _To, class = void>
65*5f757f3fSDimitry Andric inline constexpr bool __is_non_narrowing_convertible_v = false;
66*5f757f3fSDimitry Andric 
67*5f757f3fSDimitry Andric template <class _From, class _To>
68*5f757f3fSDimitry Andric inline constexpr bool __is_non_narrowing_convertible_v<_From, _To, std::void_t<decltype(_To{std::declval<_From>()})>> =
69*5f757f3fSDimitry Andric     true;
70*5f757f3fSDimitry Andric 
71*5f757f3fSDimitry Andric template <class _Tp, class _Up>
72*5f757f3fSDimitry Andric inline constexpr bool __can_broadcast_v =
73*5f757f3fSDimitry Andric     (__is_vectorizable_v<_Up> && __is_non_narrowing_convertible_v<_Up, _Tp>) ||
74*5f757f3fSDimitry Andric     (!__is_vectorizable_v<_Up> && is_convertible_v<_Up, _Tp>) || is_same_v<_Up, int> ||
75*5f757f3fSDimitry Andric     (is_same_v<_Up, unsigned int> && is_unsigned_v<_Tp>);
76*5f757f3fSDimitry Andric 
77*5f757f3fSDimitry Andric template <class _Tp, class _Generator, std::size_t _Idx, class = void>
78*5f757f3fSDimitry Andric inline constexpr bool __is_well_formed = false;
79*5f757f3fSDimitry Andric 
80*5f757f3fSDimitry Andric template <class _Tp, class _Generator, std::size_t _Idx>
81*5f757f3fSDimitry Andric inline constexpr bool
82*5f757f3fSDimitry Andric     __is_well_formed<_Tp,
83*5f757f3fSDimitry Andric                      _Generator,
84*5f757f3fSDimitry Andric                      _Idx,
85*5f757f3fSDimitry Andric                      std::void_t<decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>> =
86*5f757f3fSDimitry Andric         __can_broadcast_v<_Tp, decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>;
87*5f757f3fSDimitry Andric 
88*5f757f3fSDimitry Andric template <class _Tp, class _Generator, std::size_t... _Idxes>
__can_generate(index_sequence<_Idxes...>)89*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool __can_generate(index_sequence<_Idxes...>) {
90*5f757f3fSDimitry Andric   return (true && ... && __is_well_formed<_Tp, _Generator, _Idxes>);
91*5f757f3fSDimitry Andric }
92*5f757f3fSDimitry Andric 
93*5f757f3fSDimitry Andric template <class _Tp, class _Generator, std::size_t _Size>
94*5f757f3fSDimitry Andric inline constexpr bool __can_generate_v = experimental::__can_generate<_Tp, _Generator>(make_index_sequence<_Size>());
95*5f757f3fSDimitry Andric 
96*5f757f3fSDimitry Andric } // namespace parallelism_v2
97*5f757f3fSDimitry Andric _LIBCPP_END_NAMESPACE_EXPERIMENTAL
98*5f757f3fSDimitry Andric 
99*5f757f3fSDimitry Andric #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
100*5f757f3fSDimitry Andric 
101*5f757f3fSDimitry Andric _LIBCPP_POP_MACROS
102*5f757f3fSDimitry Andric 
103*5f757f3fSDimitry Andric #endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
104