//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14 // Older versions of clang may encounter a backend error (see 0295c2ad): // Pass-by-value arguments with alignment greater than register width are not supported. // XFAIL: target=powerpc{{.*}}-ibm-{{.*}} && clang-18 // // // [simd.class] // template void copy_from(const U* mem, Flags); // template void copy_to(U* mem, Flags) const; #include "../test_utils.h" namespace ex = std::experimental::parallelism_v2; template struct ElementAlignedCopyFromHelper { template void operator()() const { U buffer[array_size]; for (size_t i = 0; i < array_size; ++i) buffer[i] = static_cast(i); ex::simd origin_simd; origin_simd.copy_from(buffer, ex::element_aligned_tag()); assert_simd_values_equal(origin_simd, buffer); } }; template struct VectorAlignedCopyFromHelper { template void operator()() const { alignas(ex::memory_alignment_v, U>) U buffer[array_size]; for (size_t i = 0; i < array_size; ++i) buffer[i] = static_cast(i); ex::simd origin_simd; origin_simd.copy_from(buffer, ex::vector_aligned_tag()); assert_simd_values_equal(origin_simd, buffer); } }; template struct OveralignedCopyFromHelper { template void operator()() const { alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size]; for (size_t i = 0; i < array_size; ++i) buffer[i] = static_cast(i); ex::simd origin_simd; origin_simd.copy_from(buffer, ex::overaligned_tag()); assert_simd_values_equal(origin_simd, buffer); } }; template struct CheckSimdCopyFrom { template void operator()() { constexpr std::size_t array_size = ex::simd_size_v; types::for_each(simd_test_types(), ElementAlignedCopyFromHelper()); types::for_each(simd_test_types(), VectorAlignedCopyFromHelper()); types::for_each(simd_test_types(), OveralignedCopyFromHelper()); } }; template struct ElementAlignedCopyToHelper { template void operator()() const { U buffer[array_size]; ex::simd origin_simd([](T i) { return i; }); origin_simd.copy_to(buffer, ex::element_aligned_tag()); assert_simd_values_equal(origin_simd, buffer); } }; template struct VectorAlignedCopyToHelper { template void operator()() const { alignas(ex::memory_alignment_v, U>) U buffer[array_size]; ex::simd origin_simd([](T i) { return i; }); origin_simd.copy_to(buffer, ex::vector_aligned_tag()); assert_simd_values_equal(origin_simd, buffer); } }; template struct OveralignedCopyToHelper { template void operator()() const { alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size]; ex::simd origin_simd([](T i) { return i; }); origin_simd.copy_to(buffer, ex::overaligned_tag()); assert_simd_values_equal(origin_simd, buffer); } }; template struct CheckSimdCopyTo { template void operator()() { constexpr std::size_t array_size = ex::simd_size_v; types::for_each(simd_test_types(), ElementAlignedCopyToHelper()); types::for_each(simd_test_types(), VectorAlignedCopyToHelper()); types::for_each(simd_test_types(), OveralignedCopyToHelper()); } }; template , class = void> struct has_copy_from : std::false_type {}; template struct has_copy_from>().copy_from( std::declval(), std::declval()))>> : std::true_type {}; template , class = void> struct has_copy_to : std::false_type {}; template struct has_copy_to< U, T, Flags, SimdAbi, std::void_t>().copy_to(std::declval(), std::declval()))>> : std::true_type {}; template struct CheckSimdCopyTraits { template void operator()() { // These functions shall not participate in overload resolution unless // is_simd_flag_type_v is true, and // U is a vectorizable type. static_assert(has_copy_from::value); static_assert(has_copy_to::value); // is_simd_flag_type_v is false static_assert(!has_copy_from::value); static_assert(!has_copy_to::value); static_assert(!has_copy_from::value); static_assert(!has_copy_to::value); // U is not a vectorizable type. static_assert(!has_copy_from::value); static_assert(!has_copy_to::value); static_assert(!has_copy_from::value); static_assert(!has_copy_to::value); } }; int main(int, char**) { test_all_simd_abi(); test_all_simd_abi(); test_all_simd_abi(); return 0; }