xref: /llvm-project/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp (revision 7f845cba2ccc2ab637b8e40fbafb9f83a2d67c70)
1058e4454SZhangYin //===----------------------------------------------------------------------===//
2058e4454SZhangYin //
3058e4454SZhangYin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4058e4454SZhangYin // See https://llvm.org/LICENSE.txt for license information.
5058e4454SZhangYin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6058e4454SZhangYin //
7058e4454SZhangYin //===----------------------------------------------------------------------===//
8058e4454SZhangYin 
9058e4454SZhangYin // UNSUPPORTED: c++03, c++11, c++14
10058e4454SZhangYin 
11df168427SDavid Tenty // Older versions of clang may encounter a backend error (see 0295c2ad):
12058e4454SZhangYin //   Pass-by-value arguments with alignment greater than register width are not supported.
13*7f845cbaSNikolas Klauser // XFAIL: target=powerpc{{.*}}-ibm-{{.*}} && clang-18
14058e4454SZhangYin 
15058e4454SZhangYin // <experimental/simd>
16058e4454SZhangYin //
17058e4454SZhangYin // [simd.class]
18058e4454SZhangYin // template<class U, class Flags> void copy_from(const U* mem, Flags);
19058e4454SZhangYin // template<class U, class Flags> void copy_to(U* mem, Flags) const;
20058e4454SZhangYin 
21058e4454SZhangYin #include "../test_utils.h"
22058e4454SZhangYin 
23058e4454SZhangYin namespace ex = std::experimental::parallelism_v2;
24058e4454SZhangYin 
25058e4454SZhangYin template <class T, class SimdAbi, std::size_t array_size>
26058e4454SZhangYin struct ElementAlignedCopyFromHelper {
27058e4454SZhangYin   template <class U>
28058e4454SZhangYin   void operator()() const {
29058e4454SZhangYin     U buffer[array_size];
30058e4454SZhangYin     for (size_t i = 0; i < array_size; ++i)
31058e4454SZhangYin       buffer[i] = static_cast<U>(i);
32058e4454SZhangYin     ex::simd<T, SimdAbi> origin_simd;
33058e4454SZhangYin     origin_simd.copy_from(buffer, ex::element_aligned_tag());
34058e4454SZhangYin     assert_simd_values_equal(origin_simd, buffer);
35058e4454SZhangYin   }
36058e4454SZhangYin };
37058e4454SZhangYin 
38058e4454SZhangYin template <class T, class SimdAbi, std::size_t array_size>
39058e4454SZhangYin struct VectorAlignedCopyFromHelper {
40058e4454SZhangYin   template <class U>
41058e4454SZhangYin   void operator()() const {
42058e4454SZhangYin     alignas(ex::memory_alignment_v<ex::simd<T, SimdAbi>, U>) U buffer[array_size];
43058e4454SZhangYin     for (size_t i = 0; i < array_size; ++i)
44058e4454SZhangYin       buffer[i] = static_cast<U>(i);
45058e4454SZhangYin     ex::simd<T, SimdAbi> origin_simd;
46058e4454SZhangYin     origin_simd.copy_from(buffer, ex::vector_aligned_tag());
47058e4454SZhangYin     assert_simd_values_equal(origin_simd, buffer);
48058e4454SZhangYin   }
49058e4454SZhangYin };
50058e4454SZhangYin 
51058e4454SZhangYin template <class T, class SimdAbi, std::size_t array_size>
52058e4454SZhangYin struct OveralignedCopyFromHelper {
53058e4454SZhangYin   template <class U>
54058e4454SZhangYin   void operator()() const {
55058e4454SZhangYin     alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size];
56058e4454SZhangYin     for (size_t i = 0; i < array_size; ++i)
57058e4454SZhangYin       buffer[i] = static_cast<U>(i);
58058e4454SZhangYin     ex::simd<T, SimdAbi> origin_simd;
59058e4454SZhangYin     origin_simd.copy_from(buffer, ex::overaligned_tag<bit_ceil(sizeof(U) + 1)>());
60058e4454SZhangYin     assert_simd_values_equal(origin_simd, buffer);
61058e4454SZhangYin   }
62058e4454SZhangYin };
63058e4454SZhangYin 
64058e4454SZhangYin template <class T, std::size_t>
65058e4454SZhangYin struct CheckSimdCopyFrom {
66058e4454SZhangYin   template <class SimdAbi>
67058e4454SZhangYin   void operator()() {
68058e4454SZhangYin     constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
69058e4454SZhangYin 
70058e4454SZhangYin     types::for_each(simd_test_types(), ElementAlignedCopyFromHelper<T, SimdAbi, array_size>());
71058e4454SZhangYin     types::for_each(simd_test_types(), VectorAlignedCopyFromHelper<T, SimdAbi, array_size>());
72058e4454SZhangYin     types::for_each(simd_test_types(), OveralignedCopyFromHelper<T, SimdAbi, array_size>());
73058e4454SZhangYin   }
74058e4454SZhangYin };
75058e4454SZhangYin 
76058e4454SZhangYin template <class T, class SimdAbi, std::size_t array_size>
77058e4454SZhangYin struct ElementAlignedCopyToHelper {
78058e4454SZhangYin   template <class U>
79058e4454SZhangYin   void operator()() const {
80058e4454SZhangYin     U buffer[array_size];
81058e4454SZhangYin     ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
82058e4454SZhangYin     origin_simd.copy_to(buffer, ex::element_aligned_tag());
83058e4454SZhangYin     assert_simd_values_equal(origin_simd, buffer);
84058e4454SZhangYin   }
85058e4454SZhangYin };
86058e4454SZhangYin 
87058e4454SZhangYin template <class T, class SimdAbi, std::size_t array_size>
88058e4454SZhangYin struct VectorAlignedCopyToHelper {
89058e4454SZhangYin   template <class U>
90058e4454SZhangYin   void operator()() const {
91058e4454SZhangYin     alignas(ex::memory_alignment_v<ex::simd<T, SimdAbi>, U>) U buffer[array_size];
92058e4454SZhangYin     ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
93058e4454SZhangYin     origin_simd.copy_to(buffer, ex::vector_aligned_tag());
94058e4454SZhangYin     assert_simd_values_equal(origin_simd, buffer);
95058e4454SZhangYin   }
96058e4454SZhangYin };
97058e4454SZhangYin 
98058e4454SZhangYin template <class T, class SimdAbi, std::size_t array_size>
99058e4454SZhangYin struct OveralignedCopyToHelper {
100058e4454SZhangYin   template <class U>
101058e4454SZhangYin   void operator()() const {
102058e4454SZhangYin     alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size];
103058e4454SZhangYin     ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
104058e4454SZhangYin     origin_simd.copy_to(buffer, ex::overaligned_tag<bit_ceil(sizeof(U) + 1)>());
105058e4454SZhangYin     assert_simd_values_equal(origin_simd, buffer);
106058e4454SZhangYin   }
107058e4454SZhangYin };
108058e4454SZhangYin 
109058e4454SZhangYin template <class T, std::size_t>
110058e4454SZhangYin struct CheckSimdCopyTo {
111058e4454SZhangYin   template <class SimdAbi>
112058e4454SZhangYin   void operator()() {
113058e4454SZhangYin     constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
114058e4454SZhangYin 
115058e4454SZhangYin     types::for_each(simd_test_types(), ElementAlignedCopyToHelper<T, SimdAbi, array_size>());
116058e4454SZhangYin     types::for_each(simd_test_types(), VectorAlignedCopyToHelper<T, SimdAbi, array_size>());
117058e4454SZhangYin     types::for_each(simd_test_types(), OveralignedCopyToHelper<T, SimdAbi, array_size>());
118058e4454SZhangYin   }
119058e4454SZhangYin };
120058e4454SZhangYin 
121058e4454SZhangYin template <class U, class T, class Flags, class SimdAbi = ex::simd_abi::compatible<T>, class = void>
122058e4454SZhangYin struct has_copy_from : std::false_type {};
123058e4454SZhangYin 
124058e4454SZhangYin template <class U, class T, class Flags, class SimdAbi>
125058e4454SZhangYin struct has_copy_from<U,
126058e4454SZhangYin                      T,
127058e4454SZhangYin                      Flags,
128058e4454SZhangYin                      SimdAbi,
129058e4454SZhangYin                      std::void_t<decltype(std::declval<ex::simd<T, SimdAbi>>().copy_from(
130058e4454SZhangYin                          std::declval<const U*>(), std::declval<Flags>()))>> : std::true_type {};
131058e4454SZhangYin 
132058e4454SZhangYin template <class U, class T, class Flags, class SimdAbi = ex::simd_abi::compatible<T>, class = void>
133058e4454SZhangYin struct has_copy_to : std::false_type {};
134058e4454SZhangYin 
135058e4454SZhangYin template <class U, class T, class Flags, class SimdAbi>
136058e4454SZhangYin struct has_copy_to<
137058e4454SZhangYin     U,
138058e4454SZhangYin     T,
139058e4454SZhangYin     Flags,
140058e4454SZhangYin     SimdAbi,
141058e4454SZhangYin     std::void_t<decltype(std::declval<ex::simd<T, SimdAbi>>().copy_to(std::declval<U*>(), std::declval<Flags>()))>>
142058e4454SZhangYin     : std::true_type {};
143058e4454SZhangYin 
144058e4454SZhangYin template <class T, std::size_t>
145058e4454SZhangYin struct CheckSimdCopyTraits {
146058e4454SZhangYin   template <class SimdAbi>
147058e4454SZhangYin   void operator()() {
148058e4454SZhangYin     // These functions shall not participate in overload resolution unless
149058e4454SZhangYin     // is_simd_flag_type_v<Flags> is true, and
150058e4454SZhangYin     // U is a vectorizable type.
151058e4454SZhangYin     static_assert(has_copy_from<int, T, ex::element_aligned_tag, SimdAbi>::value);
152058e4454SZhangYin     static_assert(has_copy_to<int, T, ex::element_aligned_tag, SimdAbi>::value);
153058e4454SZhangYin 
154058e4454SZhangYin     // is_simd_flag_type_v<Flags> is false
155058e4454SZhangYin     static_assert(!has_copy_from<int, T, T, SimdAbi>::value);
156058e4454SZhangYin     static_assert(!has_copy_to<int, T, T, SimdAbi>::value);
157058e4454SZhangYin     static_assert(!has_copy_from<int, T, SimdAbi, SimdAbi>::value);
158058e4454SZhangYin     static_assert(!has_copy_to<int, T, SimdAbi, SimdAbi>::value);
159058e4454SZhangYin 
160058e4454SZhangYin     // U is not a vectorizable type.
161058e4454SZhangYin     static_assert(!has_copy_from<SimdAbi, T, ex::element_aligned_tag, SimdAbi>::value);
162058e4454SZhangYin     static_assert(!has_copy_to<SimdAbi, T, ex::element_aligned_tag, SimdAbi>::value);
163058e4454SZhangYin     static_assert(!has_copy_from<ex::element_aligned_tag, T, ex::element_aligned_tag, SimdAbi>::value);
164058e4454SZhangYin     static_assert(!has_copy_to<ex::element_aligned_tag, T, ex::element_aligned_tag, SimdAbi>::value);
165058e4454SZhangYin   }
166058e4454SZhangYin };
167058e4454SZhangYin 
168058e4454SZhangYin int main(int, char**) {
169058e4454SZhangYin   test_all_simd_abi<CheckSimdCopyFrom>();
170058e4454SZhangYin   test_all_simd_abi<CheckSimdCopyTo>();
171058e4454SZhangYin   test_all_simd_abi<CheckSimdCopyTraits>();
172058e4454SZhangYin   return 0;
173058e4454SZhangYin }
174