1*a284d0ccSZhangyin //===----------------------------------------------------------------------===//
2*a284d0ccSZhangyin //
3*a284d0ccSZhangyin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*a284d0ccSZhangyin // See https://llvm.org/LICENSE.txt for license information.
5*a284d0ccSZhangyin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*a284d0ccSZhangyin //
7*a284d0ccSZhangyin //===----------------------------------------------------------------------===//
8*a284d0ccSZhangyin
9*a284d0ccSZhangyin // UNSUPPORTED: c++03, c++11, c++14
10*a284d0ccSZhangyin
11*a284d0ccSZhangyin // <experimental/simd>
12*a284d0ccSZhangyin //
13*a284d0ccSZhangyin // [simd.traits]
14*a284d0ccSZhangyin // template <class T, class U = typename T::value_type> struct memory_alignment;
15*a284d0ccSZhangyin // template <class T, class U = typename T::value_type>
16*a284d0ccSZhangyin // inline constexpr std::size_t memory_alignment_v = memory_alignment<T, U>::value;
17*a284d0ccSZhangyin
18*a284d0ccSZhangyin #include "../test_utils.h"
19*a284d0ccSZhangyin
20*a284d0ccSZhangyin namespace ex = std::experimental::parallelism_v2;
21*a284d0ccSZhangyin
22*a284d0ccSZhangyin template <class T, std::size_t N>
23*a284d0ccSZhangyin struct CheckMemoryAlignmentMask {
24*a284d0ccSZhangyin template <class SimdAbi>
operator ()CheckMemoryAlignmentMask25*a284d0ccSZhangyin void operator()() {
26*a284d0ccSZhangyin LIBCPP_STATIC_ASSERT(
27*a284d0ccSZhangyin ex::memory_alignment<ex::simd_mask<T, SimdAbi>>::value == bit_ceil(sizeof(bool) * ex::simd_size_v<T, SimdAbi>));
28*a284d0ccSZhangyin LIBCPP_STATIC_ASSERT(
29*a284d0ccSZhangyin ex::memory_alignment_v<ex::simd_mask<T, SimdAbi>> == bit_ceil(sizeof(bool) * ex::simd_size_v<T, SimdAbi>));
30*a284d0ccSZhangyin }
31*a284d0ccSZhangyin };
32*a284d0ccSZhangyin
33*a284d0ccSZhangyin template <class T, std::size_t N>
34*a284d0ccSZhangyin struct CheckMemoryAlignmentLongDouble {
35*a284d0ccSZhangyin template <class SimdAbi>
operator ()CheckMemoryAlignmentLongDouble36*a284d0ccSZhangyin void operator()() {
37*a284d0ccSZhangyin if constexpr (std::is_same_v<T, long double>) {
38*a284d0ccSZhangyin // on i686-w64-mingw32-clang++, the size of long double is 12 bytes. Disambiguation is needed.
39*a284d0ccSZhangyin static_assert(
40*a284d0ccSZhangyin ex::memory_alignment<ex::simd<T, SimdAbi>>::value == bit_ceil(sizeof(T) * ex::simd_size_v<T, SimdAbi>));
41*a284d0ccSZhangyin static_assert(ex::memory_alignment_v<ex::simd<T, SimdAbi>> == bit_ceil(sizeof(T) * ex::simd_size_v<T, SimdAbi>));
42*a284d0ccSZhangyin }
43*a284d0ccSZhangyin }
44*a284d0ccSZhangyin };
45*a284d0ccSZhangyin
46*a284d0ccSZhangyin struct CheckMemAlignmentFixedDeduce {
47*a284d0ccSZhangyin template <class T, std::size_t N>
checkCheckMemAlignmentFixedDeduce48*a284d0ccSZhangyin void check() {
49*a284d0ccSZhangyin if constexpr (!std::is_same_v<T, long double>) {
50*a284d0ccSZhangyin static_assert(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::fixed_size<N>>> == sizeof(T) * bit_ceil(N),
51*a284d0ccSZhangyin "Memory Alignment mismatch with abi fixed_size");
52*a284d0ccSZhangyin static_assert(ex::memory_alignment<ex::simd<T, ex::simd_abi::fixed_size<N>>>::value == sizeof(T) * bit_ceil(N),
53*a284d0ccSZhangyin "Memory Alignment mismatch with abi fixed_size");
54*a284d0ccSZhangyin
55*a284d0ccSZhangyin static_assert(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::deduce_t<T, N>>> == sizeof(T) * bit_ceil(N),
56*a284d0ccSZhangyin "Memory Alignment mismatch with abi deduce");
57*a284d0ccSZhangyin static_assert(ex::memory_alignment<ex::simd<T, ex::simd_abi::deduce_t<T, N>>>::value == sizeof(T) * bit_ceil(N),
58*a284d0ccSZhangyin "Memory Alignment mismatch with abi deduce");
59*a284d0ccSZhangyin }
60*a284d0ccSZhangyin }
61*a284d0ccSZhangyin
62*a284d0ccSZhangyin template <class T, std::size_t... N>
performChecksCheckMemAlignmentFixedDeduce63*a284d0ccSZhangyin void performChecks(std::index_sequence<N...>) {
64*a284d0ccSZhangyin (check<T, N + 1>(), ...);
65*a284d0ccSZhangyin }
66*a284d0ccSZhangyin
67*a284d0ccSZhangyin template <class T>
operator ()CheckMemAlignmentFixedDeduce68*a284d0ccSZhangyin void operator()() {
69*a284d0ccSZhangyin performChecks<T>(std::make_index_sequence<max_simd_size>{});
70*a284d0ccSZhangyin }
71*a284d0ccSZhangyin };
72*a284d0ccSZhangyin
73*a284d0ccSZhangyin struct CheckMemAlignmentScalarNativeCompatible {
74*a284d0ccSZhangyin template <class T>
operator ()CheckMemAlignmentScalarNativeCompatible75*a284d0ccSZhangyin void operator()() {
76*a284d0ccSZhangyin if constexpr (!std::is_same_v<T, long double>) {
77*a284d0ccSZhangyin static_assert(ex::memory_alignment<ex::simd<T, ex::simd_abi::scalar>>::value == sizeof(T));
78*a284d0ccSZhangyin static_assert(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::scalar>> == sizeof(T));
79*a284d0ccSZhangyin
80*a284d0ccSZhangyin LIBCPP_STATIC_ASSERT(ex::memory_alignment<ex::simd<T, ex::simd_abi::compatible<T>>>::value == 16);
81*a284d0ccSZhangyin LIBCPP_STATIC_ASSERT(ex::memory_alignment_v<ex::simd<T, ex::simd_abi::compatible<T>>> == 16);
82*a284d0ccSZhangyin
83*a284d0ccSZhangyin LIBCPP_STATIC_ASSERT(
84*a284d0ccSZhangyin ex::memory_alignment<ex::simd<T, ex::simd_abi::native<T>>>::value == _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES);
85*a284d0ccSZhangyin LIBCPP_STATIC_ASSERT(
86*a284d0ccSZhangyin ex::memory_alignment_v<ex::simd<T, ex::simd_abi::native<T>>> == _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES);
87*a284d0ccSZhangyin }
88*a284d0ccSZhangyin }
89*a284d0ccSZhangyin };
90*a284d0ccSZhangyin
91*a284d0ccSZhangyin template <class T, class U = typename T::value_type, class = void>
92*a284d0ccSZhangyin struct has_memory_alignment : std::false_type {};
93*a284d0ccSZhangyin
94*a284d0ccSZhangyin template <class T, class U>
95*a284d0ccSZhangyin struct has_memory_alignment<T, U, std::void_t<decltype(ex::memory_alignment<T, U>::value)>> : std::true_type {};
96*a284d0ccSZhangyin
97*a284d0ccSZhangyin struct CheckMemoryAlignmentTraits {
98*a284d0ccSZhangyin template <class T>
operator ()CheckMemoryAlignmentTraits99*a284d0ccSZhangyin void operator()() {
100*a284d0ccSZhangyin static_assert(has_memory_alignment<ex::native_simd<T>>::value);
101*a284d0ccSZhangyin static_assert(has_memory_alignment<ex::fixed_size_simd_mask<T, 4>>::value);
102*a284d0ccSZhangyin static_assert(has_memory_alignment<ex::native_simd<T>, T>::value);
103*a284d0ccSZhangyin static_assert(has_memory_alignment<ex::fixed_size_simd_mask<T, 4>, bool>::value);
104*a284d0ccSZhangyin
105*a284d0ccSZhangyin static_assert(!has_memory_alignment<T, T>::value);
106*a284d0ccSZhangyin static_assert(!has_memory_alignment<T, bool>::value);
107*a284d0ccSZhangyin static_assert(!has_memory_alignment<ex::native_simd<T>, bool>::value);
108*a284d0ccSZhangyin static_assert(!has_memory_alignment<ex::fixed_size_simd_mask<T, 4>, T>::value);
109*a284d0ccSZhangyin }
110*a284d0ccSZhangyin };
111*a284d0ccSZhangyin
main(int,char **)112*a284d0ccSZhangyin int main(int, char**) {
113*a284d0ccSZhangyin types::for_each(arithmetic_no_bool_types(), CheckMemAlignmentFixedDeduce());
114*a284d0ccSZhangyin types::for_each(arithmetic_no_bool_types(), CheckMemAlignmentScalarNativeCompatible());
115*a284d0ccSZhangyin test_all_simd_abi<CheckMemoryAlignmentMask>();
116*a284d0ccSZhangyin test_all_simd_abi<CheckMemoryAlignmentLongDouble>();
117*a284d0ccSZhangyin types::for_each(arithmetic_no_bool_types(), CheckMemoryAlignmentTraits());
118*a284d0ccSZhangyin return 0;
119*a284d0ccSZhangyin }
120