170 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// <experimental/simd>12//13// [simd.class]14// template<class U, class Flags> void copy_from(const U* mem, Flags);15// template<class U, class Flags> void copy_to(U* mem, Flags) const;16 17#include "../test_utils.h"18 19namespace ex = std::experimental::parallelism_v2;20 21template <class T, class SimdAbi, std::size_t array_size>22struct ElementAlignedCopyFromHelper {23 template <class U>24 void operator()() const {25 U buffer[array_size];26 for (size_t i = 0; i < array_size; ++i)27 buffer[i] = static_cast<U>(i);28 ex::simd<T, SimdAbi> origin_simd;29 origin_simd.copy_from(buffer, ex::element_aligned_tag());30 assert_simd_values_equal(origin_simd, buffer);31 }32};33 34template <class T, class SimdAbi, std::size_t array_size>35struct VectorAlignedCopyFromHelper {36 template <class U>37 void operator()() const {38 alignas(ex::memory_alignment_v<ex::simd<T, SimdAbi>, U>) U buffer[array_size];39 for (size_t i = 0; i < array_size; ++i)40 buffer[i] = static_cast<U>(i);41 ex::simd<T, SimdAbi> origin_simd;42 origin_simd.copy_from(buffer, ex::vector_aligned_tag());43 assert_simd_values_equal(origin_simd, buffer);44 }45};46 47template <class T, class SimdAbi, std::size_t array_size>48struct OveralignedCopyFromHelper {49 template <class U>50 void operator()() const {51 alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size];52 for (size_t i = 0; i < array_size; ++i)53 buffer[i] = static_cast<U>(i);54 ex::simd<T, SimdAbi> origin_simd;55 origin_simd.copy_from(buffer, ex::overaligned_tag<bit_ceil(sizeof(U) + 1)>());56 assert_simd_values_equal(origin_simd, buffer);57 }58};59 60template <class T, std::size_t>61struct CheckSimdCopyFrom {62 template <class SimdAbi>63 void operator()() {64 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;65 66 types::for_each(simd_test_types(), ElementAlignedCopyFromHelper<T, SimdAbi, array_size>());67 types::for_each(simd_test_types(), VectorAlignedCopyFromHelper<T, SimdAbi, array_size>());68 types::for_each(simd_test_types(), OveralignedCopyFromHelper<T, SimdAbi, array_size>());69 }70};71 72template <class T, class SimdAbi, std::size_t array_size>73struct ElementAlignedCopyToHelper {74 template <class U>75 void operator()() const {76 U buffer[array_size];77 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });78 origin_simd.copy_to(buffer, ex::element_aligned_tag());79 assert_simd_values_equal(origin_simd, buffer);80 }81};82 83template <class T, class SimdAbi, std::size_t array_size>84struct VectorAlignedCopyToHelper {85 template <class U>86 void operator()() const {87 alignas(ex::memory_alignment_v<ex::simd<T, SimdAbi>, U>) U buffer[array_size];88 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });89 origin_simd.copy_to(buffer, ex::vector_aligned_tag());90 assert_simd_values_equal(origin_simd, buffer);91 }92};93 94template <class T, class SimdAbi, std::size_t array_size>95struct OveralignedCopyToHelper {96 template <class U>97 void operator()() const {98 alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size];99 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });100 origin_simd.copy_to(buffer, ex::overaligned_tag<bit_ceil(sizeof(U) + 1)>());101 assert_simd_values_equal(origin_simd, buffer);102 }103};104 105template <class T, std::size_t>106struct CheckSimdCopyTo {107 template <class SimdAbi>108 void operator()() {109 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;110 111 types::for_each(simd_test_types(), ElementAlignedCopyToHelper<T, SimdAbi, array_size>());112 types::for_each(simd_test_types(), VectorAlignedCopyToHelper<T, SimdAbi, array_size>());113 types::for_each(simd_test_types(), OveralignedCopyToHelper<T, SimdAbi, array_size>());114 }115};116 117template <class U, class T, class Flags, class SimdAbi = ex::simd_abi::compatible<T>, class = void>118struct has_copy_from : std::false_type {};119 120template <class U, class T, class Flags, class SimdAbi>121struct has_copy_from<U,122 T,123 Flags,124 SimdAbi,125 std::void_t<decltype(std::declval<ex::simd<T, SimdAbi>>().copy_from(126 std::declval<const U*>(), std::declval<Flags>()))>> : std::true_type {};127 128template <class U, class T, class Flags, class SimdAbi = ex::simd_abi::compatible<T>, class = void>129struct has_copy_to : std::false_type {};130 131template <class U, class T, class Flags, class SimdAbi>132struct has_copy_to<133 U,134 T,135 Flags,136 SimdAbi,137 std::void_t<decltype(std::declval<ex::simd<T, SimdAbi>>().copy_to(std::declval<U*>(), std::declval<Flags>()))>>138 : std::true_type {};139 140template <class T, std::size_t>141struct CheckSimdCopyTraits {142 template <class SimdAbi>143 void operator()() {144 // These functions shall not participate in overload resolution unless145 // is_simd_flag_type_v<Flags> is true, and146 // U is a vectorizable type.147 static_assert(has_copy_from<int, T, ex::element_aligned_tag, SimdAbi>::value);148 static_assert(has_copy_to<int, T, ex::element_aligned_tag, SimdAbi>::value);149 150 // is_simd_flag_type_v<Flags> is false151 static_assert(!has_copy_from<int, T, T, SimdAbi>::value);152 static_assert(!has_copy_to<int, T, T, SimdAbi>::value);153 static_assert(!has_copy_from<int, T, SimdAbi, SimdAbi>::value);154 static_assert(!has_copy_to<int, T, SimdAbi, SimdAbi>::value);155 156 // U is not a vectorizable type.157 static_assert(!has_copy_from<SimdAbi, T, ex::element_aligned_tag, SimdAbi>::value);158 static_assert(!has_copy_to<SimdAbi, T, ex::element_aligned_tag, SimdAbi>::value);159 static_assert(!has_copy_from<ex::element_aligned_tag, T, ex::element_aligned_tag, SimdAbi>::value);160 static_assert(!has_copy_to<ex::element_aligned_tag, T, ex::element_aligned_tag, SimdAbi>::value);161 }162};163 164int main(int, char**) {165 test_all_simd_abi<CheckSimdCopyFrom>();166 test_all_simd_abi<CheckSimdCopyTo>();167 test_all_simd_abi<CheckSimdCopyTraits>();168 return 0;169}170