1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14
10
11// Older versions of clang may encounter a backend error (see 0295c2ad):
12// Pass-by-value arguments with alignment greater than register width are not supported.
13// XFAIL: target=powerpc{{.*}}-ibm-{{.*}} && clang-18
14
15// <experimental/simd>
16//
17// [simd.class]
18// template<class U, class Flags> void copy_from(const U* mem, Flags);
19// template<class U, class Flags> void copy_to(U* mem, Flags) const;
20
21#include "../test_utils.h"
22
23namespace ex = std::experimental::parallelism_v2;
24
25template <class T, class SimdAbi, std::size_t array_size>
26struct ElementAlignedCopyFromHelper {
27 template <class U>
28 void operator()() const {
29 U buffer[array_size];
30 for (size_t i = 0; i < array_size; ++i)
31 buffer[i] = static_cast<U>(i);
32 ex::simd<T, SimdAbi> origin_simd;
33 origin_simd.copy_from(buffer, ex::element_aligned_tag());
34 assert_simd_values_equal(origin_simd, buffer);
35 }
36};
37
38template <class T, class SimdAbi, std::size_t array_size>
39struct VectorAlignedCopyFromHelper {
40 template <class U>
41 void operator()() const {
42 alignas(ex::memory_alignment_v<ex::simd<T, SimdAbi>, U>) U buffer[array_size];
43 for (size_t i = 0; i < array_size; ++i)
44 buffer[i] = static_cast<U>(i);
45 ex::simd<T, SimdAbi> origin_simd;
46 origin_simd.copy_from(buffer, ex::vector_aligned_tag());
47 assert_simd_values_equal(origin_simd, buffer);
48 }
49};
50
51template <class T, class SimdAbi, std::size_t array_size>
52struct OveralignedCopyFromHelper {
53 template <class U>
54 void operator()() const {
55 alignas(bit_ceil(val: sizeof(U) + 1)) U buffer[array_size];
56 for (size_t i = 0; i < array_size; ++i)
57 buffer[i] = static_cast<U>(i);
58 ex::simd<T, SimdAbi> origin_simd;
59 origin_simd.copy_from(buffer, ex::overaligned_tag<bit_ceil(val: sizeof(U) + 1)>());
60 assert_simd_values_equal(origin_simd, buffer);
61 }
62};
63
64template <class T, std::size_t>
65struct CheckSimdCopyFrom {
66 template <class SimdAbi>
67 void operator()() {
68 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
69
70 types::for_each(simd_test_types(), ElementAlignedCopyFromHelper<T, SimdAbi, array_size>());
71 types::for_each(simd_test_types(), VectorAlignedCopyFromHelper<T, SimdAbi, array_size>());
72 types::for_each(simd_test_types(), OveralignedCopyFromHelper<T, SimdAbi, array_size>());
73 }
74};
75
76template <class T, class SimdAbi, std::size_t array_size>
77struct ElementAlignedCopyToHelper {
78 template <class U>
79 void operator()() const {
80 U buffer[array_size];
81 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
82 origin_simd.copy_to(buffer, ex::element_aligned_tag());
83 assert_simd_values_equal(origin_simd, buffer);
84 }
85};
86
87template <class T, class SimdAbi, std::size_t array_size>
88struct VectorAlignedCopyToHelper {
89 template <class U>
90 void operator()() const {
91 alignas(ex::memory_alignment_v<ex::simd<T, SimdAbi>, U>) U buffer[array_size];
92 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
93 origin_simd.copy_to(buffer, ex::vector_aligned_tag());
94 assert_simd_values_equal(origin_simd, buffer);
95 }
96};
97
98template <class T, class SimdAbi, std::size_t array_size>
99struct OveralignedCopyToHelper {
100 template <class U>
101 void operator()() const {
102 alignas(bit_ceil(val: sizeof(U) + 1)) U buffer[array_size];
103 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
104 origin_simd.copy_to(buffer, ex::overaligned_tag<bit_ceil(val: sizeof(U) + 1)>());
105 assert_simd_values_equal(origin_simd, buffer);
106 }
107};
108
109template <class T, std::size_t>
110struct CheckSimdCopyTo {
111 template <class SimdAbi>
112 void operator()() {
113 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
114
115 types::for_each(simd_test_types(), ElementAlignedCopyToHelper<T, SimdAbi, array_size>());
116 types::for_each(simd_test_types(), VectorAlignedCopyToHelper<T, SimdAbi, array_size>());
117 types::for_each(simd_test_types(), OveralignedCopyToHelper<T, SimdAbi, array_size>());
118 }
119};
120
121template <class U, class T, class Flags, class SimdAbi = ex::simd_abi::compatible<T>, class = void>
122struct has_copy_from : std::false_type {};
123
124template <class U, class T, class Flags, class SimdAbi>
125struct has_copy_from<U,
126 T,
127 Flags,
128 SimdAbi,
129 std::void_t<decltype(std::declval<ex::simd<T, SimdAbi>>().copy_from(
130 std::declval<const U*>(), std::declval<Flags>()))>> : std::true_type {};
131
132template <class U, class T, class Flags, class SimdAbi = ex::simd_abi::compatible<T>, class = void>
133struct has_copy_to : std::false_type {};
134
135template <class U, class T, class Flags, class SimdAbi>
136struct has_copy_to<
137 U,
138 T,
139 Flags,
140 SimdAbi,
141 std::void_t<decltype(std::declval<ex::simd<T, SimdAbi>>().copy_to(std::declval<U*>(), std::declval<Flags>()))>>
142 : std::true_type {};
143
144template <class T, std::size_t>
145struct CheckSimdCopyTraits {
146 template <class SimdAbi>
147 void operator()() {
148 // These functions shall not participate in overload resolution unless
149 // is_simd_flag_type_v<Flags> is true, and
150 // U is a vectorizable type.
151 static_assert(has_copy_from<int, T, ex::element_aligned_tag, SimdAbi>::value);
152 static_assert(has_copy_to<int, T, ex::element_aligned_tag, SimdAbi>::value);
153
154 // is_simd_flag_type_v<Flags> is false
155 static_assert(!has_copy_from<int, T, T, SimdAbi>::value);
156 static_assert(!has_copy_to<int, T, T, SimdAbi>::value);
157 static_assert(!has_copy_from<int, T, SimdAbi, SimdAbi>::value);
158 static_assert(!has_copy_to<int, T, SimdAbi, SimdAbi>::value);
159
160 // U is not a vectorizable type.
161 static_assert(!has_copy_from<SimdAbi, T, ex::element_aligned_tag, SimdAbi>::value);
162 static_assert(!has_copy_to<SimdAbi, T, ex::element_aligned_tag, SimdAbi>::value);
163 static_assert(!has_copy_from<ex::element_aligned_tag, T, ex::element_aligned_tag, SimdAbi>::value);
164 static_assert(!has_copy_to<ex::element_aligned_tag, T, ex::element_aligned_tag, SimdAbi>::value);
165 }
166};
167
168int main(int, char**) {
169 test_all_simd_abi<CheckSimdCopyFrom>();
170 test_all_simd_abi<CheckSimdCopyTo>();
171 test_all_simd_abi<CheckSimdCopyTraits>();
172 return 0;
173}
174

source code of libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp