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