xref: /llvm-project/libcxx/test/std/experimental/simd/test_utils.h (revision e99c4906e44ae3f921fa05356909d006cda8d954)
10e30dd44SZhangyin //===----------------------------------------------------------------------===//
20e30dd44SZhangyin //
30e30dd44SZhangyin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40e30dd44SZhangyin // See https://llvm.org/LICENSE.txt for license information.
50e30dd44SZhangyin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60e30dd44SZhangyin //
70e30dd44SZhangyin //===----------------------------------------------------------------------===//
80e30dd44SZhangyin 
9b034da7dSLouis Dionne #ifndef LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
10b034da7dSLouis Dionne #define LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
110e30dd44SZhangyin 
12ed29f275SZhangyin #include <array>
13ed29f275SZhangyin #include <cassert>
14*e99c4906SNikolas Klauser #include <cstddef>
15*e99c4906SNikolas Klauser #include <experimental/simd>
16ed29f275SZhangyin #include <type_traits>
170e30dd44SZhangyin #include <utility>
18*e99c4906SNikolas Klauser 
190e30dd44SZhangyin #include "type_algorithms.h"
200e30dd44SZhangyin 
210e30dd44SZhangyin namespace ex = std::experimental::parallelism_v2;
220e30dd44SZhangyin 
230e30dd44SZhangyin constexpr std::size_t max_simd_size = 32;
240e30dd44SZhangyin 
250e30dd44SZhangyin template <template <class T, std::size_t N> class F>
260e30dd44SZhangyin struct TestAllSimdAbiFunctor {
270e30dd44SZhangyin   template <class T, std::size_t N>
280e30dd44SZhangyin   using sized_abis = types::type_list<ex::simd_abi::fixed_size<N>, ex::simd_abi::deduce_t<T, N>>;
290e30dd44SZhangyin 
300e30dd44SZhangyin   template <class T, std::size_t... Ns>
310e30dd44SZhangyin   void instantiate_with_n(std::index_sequence<Ns...>) {
325cd24759SLouis Dionne     (types::for_each(sized_abis<T, Ns>{}, F<T, Ns>{}), ...);
330e30dd44SZhangyin   }
340e30dd44SZhangyin 
350e30dd44SZhangyin   template <class T>
360e30dd44SZhangyin   void operator()() {
370e30dd44SZhangyin     using abis = types::type_list<ex::simd_abi::scalar, ex::simd_abi::native<T>, ex::simd_abi::compatible<T>>;
380e30dd44SZhangyin     types::for_each(abis{}, F<T, 1>());
390e30dd44SZhangyin 
405cd24759SLouis Dionne     instantiate_with_n<T>(
415cd24759SLouis Dionne         std::index_sequence<1, 2, 3, 4, 8, 16, max_simd_size - 2, max_simd_size - 1, max_simd_size>{});
420e30dd44SZhangyin   }
430e30dd44SZhangyin };
440e30dd44SZhangyin 
4581a3828dSZhangyin // TODO: Support long double (12 bytes) for 32-bits x86
4681a3828dSZhangyin #ifdef __i386__
47e7a45c6dSZhangyin using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::type_list<float, double>>;
48e7a45c6dSZhangyin #else
49ce5652c7SZhangyin using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::floating_point_types>;
50e7a45c6dSZhangyin #endif
51ce5652c7SZhangyin 
525c663aa9SZhangYin // For interfaces with vectorizable type template parameters, we only use some common or boundary types
535c663aa9SZhangYin // as template parameters for testing to ensure that the compilation time of a single test does not exceed.
54899055f2SZhangYin using simd_test_integer_types =
555c663aa9SZhangYin     types::type_list<char,
565c663aa9SZhangYin                      unsigned,
57899055f2SZhangYin                      int
585c663aa9SZhangYin #ifndef TEST_HAS_NO_INT128
59899055f2SZhangYin                      ,
60899055f2SZhangYin                      __int128_t
615c663aa9SZhangYin #endif
62899055f2SZhangYin                      >;
63899055f2SZhangYin using simd_test_types = types::concatenate_t<simd_test_integer_types, types::type_list<float, double>>;
645c663aa9SZhangYin 
650e30dd44SZhangyin template <template <class T, std::size_t N> class Func>
660e30dd44SZhangyin void test_all_simd_abi() {
670e30dd44SZhangyin   types::for_each(arithmetic_no_bool_types(), TestAllSimdAbiFunctor<Func>());
680e30dd44SZhangyin }
690e30dd44SZhangyin 
70a284d0ccSZhangyin constexpr size_t bit_ceil(size_t val) {
71a284d0ccSZhangyin   size_t pow = 1;
72a284d0ccSZhangyin   while (pow < val)
73a284d0ccSZhangyin     pow <<= 1;
74a284d0ccSZhangyin   return pow;
75a284d0ccSZhangyin }
76a284d0ccSZhangyin 
77ed29f275SZhangyin template <class From, class To, class = void>
78ed29f275SZhangyin inline constexpr bool is_non_narrowing_convertible_v = false;
79ed29f275SZhangyin 
80ed29f275SZhangyin template <class From, class To>
81ed29f275SZhangyin inline constexpr bool is_non_narrowing_convertible_v<From, To, std::void_t<decltype(To{std::declval<From>()})>> = true;
82ed29f275SZhangyin 
83ed29f275SZhangyin template <std::size_t ArraySize, class SimdAbi, class T, class U = T>
84ed29f275SZhangyin void assert_simd_values_equal(const ex::simd<T, SimdAbi>& origin_simd, const std::array<U, ArraySize>& expected_value) {
85ed29f275SZhangyin   for (std::size_t i = 0; i < origin_simd.size(); ++i)
86ed29f275SZhangyin     assert(origin_simd[i] == static_cast<T>(expected_value[i]));
87ed29f275SZhangyin }
88ed29f275SZhangyin 
89ed29f275SZhangyin template <std::size_t ArraySize, class T, class SimdAbi>
90ed29f275SZhangyin void assert_simd_mask_values_equal(const ex::simd_mask<T, SimdAbi>& origin_mask,
91ed29f275SZhangyin                                    const std::array<bool, ArraySize>& expected_value) {
92ed29f275SZhangyin   for (std::size_t i = 0; i < origin_mask.size(); ++i)
93ed29f275SZhangyin     assert(origin_mask[i] == expected_value[i]);
94ed29f275SZhangyin }
95ed29f275SZhangyin 
966bb5c989SZhangYin template <class SimdAbi, class T, class U = T>
976bb5c989SZhangYin void assert_simd_values_equal(const ex::simd<T, SimdAbi>& origin_simd, U* expected_value) {
986bb5c989SZhangYin   for (size_t i = 0; i < origin_simd.size(); ++i)
996bb5c989SZhangYin     assert(origin_simd[i] == static_cast<T>(expected_value[i]));
1006bb5c989SZhangYin }
1016bb5c989SZhangYin 
1026bb5c989SZhangYin template <class SimdAbi, class T>
1036bb5c989SZhangYin void assert_simd_mask_values_equal(const ex::simd_mask<T, SimdAbi>& origin_mask, bool* expected_value) {
1046bb5c989SZhangYin   for (size_t i = 0; i < origin_mask.size(); ++i)
1056bb5c989SZhangYin     assert(origin_mask[i] == expected_value[i]);
1066bb5c989SZhangYin }
1076bb5c989SZhangYin 
108b034da7dSLouis Dionne #endif // LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
109