1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 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 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H 11 #define _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H 12 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> 23 #include <cstddef> 24 #include <cstdint> 25 #include <experimental/__config> 26 #include <limits> 27 28 _LIBCPP_PUSH_MACROS 29 #include <__undef_macros> 30 31 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 32 33 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL 34 inline namespace parallelism_v2 { 35 template <class _Tp> 36 inline constexpr bool __is_vectorizable_v = 37 is_arithmetic_v<_Tp> && !is_const_v<_Tp> && !is_volatile_v<_Tp> && !is_same_v<_Tp, bool>; 38 39 template <class _Tp> 40 _LIBCPP_HIDE_FROM_ABI auto __choose_mask_type() { 41 if constexpr (sizeof(_Tp) == 1) { 42 return uint8_t{}; 43 } else if constexpr (sizeof(_Tp) == 2) { 44 return uint16_t{}; 45 } else if constexpr (sizeof(_Tp) == 4) { 46 return uint32_t{}; 47 } else if constexpr (sizeof(_Tp) == 8) { 48 return uint64_t{}; 49 } 50 # ifndef _LIBCPP_HAS_NO_INT128 51 else if constexpr (sizeof(_Tp) == 16) { 52 return __uint128_t{}; 53 } 54 # endif 55 else 56 static_assert(sizeof(_Tp) == 0, "Unexpected size"); 57 } 58 59 template <class _Tp> 60 _LIBCPP_HIDE_FROM_ABI auto constexpr __set_all_bits(bool __v) { 61 return __v ? (numeric_limits<decltype(__choose_mask_type<_Tp>())>::max()) : 0; 62 } 63 64 template <class _From, class _To, class = void> 65 inline constexpr bool __is_non_narrowing_convertible_v = false; 66 67 template <class _From, class _To> 68 inline constexpr bool __is_non_narrowing_convertible_v<_From, _To, std::void_t<decltype(_To{std::declval<_From>()})>> = 69 true; 70 71 template <class _Tp, class _Up> 72 inline constexpr bool __can_broadcast_v = 73 (__is_vectorizable_v<_Up> && __is_non_narrowing_convertible_v<_Up, _Tp>) || 74 (!__is_vectorizable_v<_Up> && is_convertible_v<_Up, _Tp>) || is_same_v<_Up, int> || 75 (is_same_v<_Up, unsigned int> && is_unsigned_v<_Tp>); 76 77 template <class _Tp, class _Generator, std::size_t _Idx, class = void> 78 inline constexpr bool __is_well_formed = false; 79 80 template <class _Tp, class _Generator, std::size_t _Idx> 81 inline constexpr bool 82 __is_well_formed<_Tp, 83 _Generator, 84 _Idx, 85 std::void_t<decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>> = 86 __can_broadcast_v<_Tp, decltype(std::declval<_Generator>()(integral_constant<size_t, _Idx>()))>; 87 88 template <class _Tp, class _Generator, std::size_t... _Idxes> 89 _LIBCPP_HIDE_FROM_ABI constexpr bool __can_generate(index_sequence<_Idxes...>) { 90 return (true && ... && __is_well_formed<_Tp, _Generator, _Idxes>); 91 } 92 93 template <class _Tp, class _Generator, std::size_t _Size> 94 inline constexpr bool __can_generate_v = experimental::__can_generate<_Tp, _Generator>(make_index_sequence<_Size>()); 95 96 } // namespace parallelism_v2 97 _LIBCPP_END_NAMESPACE_EXPERIMENTAL 98 99 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 100 101 _LIBCPP_POP_MACROS 102 103 #endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H 104