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 // This test crashes AppleClang 15 but not later versions. 16 // UNSUPPORTED: apple-clang-15 17 18 // FIXME: The following issue occurs on Windows to Armv7 Ubuntu Linux: 19 // Assertion failed: N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type" 20 // XFAIL: target=armv7-unknown-linux-gnueabihf 21 22 // <experimental/simd> 23 // 24 // [simd.class] 25 // simd& operator++() noexcept; 26 // simd operator++(int) noexcept; 27 // simd& operator--() noexcept; 28 // simd operator--(int) noexcept; 29 // mask_type operator!() const noexcept; 30 // simd operator~() const noexcept; 31 // simd operator+() const noexcept; 32 // simd operator-() const noexcept; 33 34 #include "../test_utils.h" 35 #include <experimental/simd> 36 37 namespace ex = std::experimental::parallelism_v2; 38 39 template <class T, std::size_t> 40 struct CheckSimdPrefixIncrementOperator { 41 template <class SimdAbi> 42 void operator()() { 43 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 44 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 45 static_assert(noexcept(++origin_simd)); 46 std::array<T, array_size> expected_return_value, expected_value; 47 for (size_t i = 0; i < array_size; ++i) { 48 expected_return_value[i] = static_cast<T>(i) + 1; 49 expected_value[i] = static_cast<T>(i) + 1; 50 } 51 assert_simd_values_equal<array_size>(++origin_simd, expected_return_value); 52 assert_simd_values_equal<array_size>(origin_simd, expected_value); 53 } 54 }; 55 56 template <class T, std::size_t> 57 struct CheckSimdPostfixIncrementOperator { 58 template <class SimdAbi> 59 void operator()() { 60 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 61 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 62 static_assert(noexcept(origin_simd++)); 63 std::array<T, array_size> expected_return_value, expected_value; 64 for (size_t i = 0; i < array_size; ++i) { 65 expected_return_value[i] = static_cast<T>(i); 66 expected_value[i] = static_cast<T>(i) + 1; 67 } 68 assert_simd_values_equal<array_size>(origin_simd++, expected_return_value); 69 assert_simd_values_equal<array_size>(origin_simd, expected_value); 70 } 71 }; 72 73 template <class T, std::size_t> 74 struct CheckSimdPrefixDecrementOperator { 75 template <class SimdAbi> 76 void operator()() { 77 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 78 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 79 static_assert(noexcept(--origin_simd)); 80 std::array<T, array_size> expected_return_value, expected_value; 81 for (size_t i = 0; i < array_size; ++i) { 82 expected_return_value[i] = static_cast<T>(i) - 1; 83 expected_value[i] = static_cast<T>(i) - 1; 84 } 85 assert_simd_values_equal<array_size>(--origin_simd, expected_return_value); 86 assert_simd_values_equal<array_size>(origin_simd, expected_value); 87 } 88 }; 89 90 template <class T, std::size_t> 91 struct CheckSimdPostfixDecrementOperator { 92 template <class SimdAbi> 93 void operator()() { 94 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 95 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 96 static_assert(noexcept(origin_simd--)); 97 std::array<T, array_size> expected_return_value, expected_value; 98 for (size_t i = 0; i < array_size; ++i) { 99 expected_return_value[i] = static_cast<T>(i); 100 expected_value[i] = static_cast<T>(i) - 1; 101 } 102 assert_simd_values_equal<array_size>(origin_simd--, expected_return_value); 103 assert_simd_values_equal<array_size>(origin_simd, expected_value); 104 } 105 }; 106 107 template <class T, std::size_t> 108 struct CheckSimdNegationOperator { 109 template <class SimdAbi> 110 void operator()() { 111 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 112 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 113 static_assert(noexcept(!origin_simd)); 114 std::array<bool, array_size> expected_value; 115 for (size_t i = 0; i < array_size; ++i) 116 expected_value[i] = !static_cast<bool>(i); 117 assert_simd_mask_values_equal<array_size>(!origin_simd, expected_value); 118 } 119 }; 120 121 template <class T, std::size_t> 122 struct CheckSimdBitwiseNotOperator { 123 template <class SimdAbi> 124 void operator()() { 125 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 126 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 127 static_assert(noexcept(~origin_simd)); 128 std::array<T, array_size> expected_value; 129 for (size_t i = 0; i < array_size; ++i) 130 expected_value[i] = ~static_cast<T>(i); 131 assert_simd_values_equal<array_size>(~origin_simd, expected_value); 132 } 133 }; 134 135 template <class T, std::size_t> 136 struct CheckSimdPositiveSignOperator { 137 template <class SimdAbi> 138 void operator()() { 139 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 140 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 141 static_assert(noexcept(+origin_simd)); 142 std::array<T, array_size> expected_value; 143 for (size_t i = 0; i < array_size; ++i) 144 expected_value[i] = +static_cast<T>(i); 145 assert_simd_values_equal<array_size>(+origin_simd, expected_value); 146 } 147 }; 148 149 template <class T, std::size_t> 150 struct CheckSimdNegativeSignOperator { 151 template <class SimdAbi> 152 void operator()() { 153 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; 154 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; }); 155 static_assert(noexcept(-origin_simd)); 156 std::array<T, array_size> expected_value; 157 for (size_t i = 0; i < array_size; ++i) 158 expected_value[i] = -static_cast<T>(i); 159 assert_simd_values_equal<array_size>(-origin_simd, expected_value); 160 } 161 }; 162 163 template <class T, class SimdAbi = ex::simd_abi::compatible<T>, class = void> 164 struct has_bitwise_not_op : std::false_type {}; 165 166 template <class T, class SimdAbi> 167 struct has_bitwise_not_op<T, SimdAbi, std::void_t<decltype(~std::declval<ex::simd<T, SimdAbi>>())>> : std::true_type {}; 168 169 template <class T, std::size_t> 170 struct CheckSimdBitwiseNotTraits { 171 template <class SimdAbi> 172 void operator()() { 173 // This function shall not participate in overload resolution unless 174 // T is an integral type. 175 if constexpr (std::is_integral_v<T>) 176 static_assert(has_bitwise_not_op<T, SimdAbi>::value); 177 // T is not an integral type. 178 else 179 static_assert(!has_bitwise_not_op<T, SimdAbi>::value); 180 } 181 }; 182 183 int main(int, char**) { 184 test_all_simd_abi<CheckSimdPrefixIncrementOperator>(); 185 test_all_simd_abi<CheckSimdPostfixIncrementOperator>(); 186 test_all_simd_abi<CheckSimdPrefixDecrementOperator>(); 187 test_all_simd_abi<CheckSimdPostfixDecrementOperator>(); 188 test_all_simd_abi<CheckSimdNegationOperator>(); 189 types::for_each(types::integer_types(), TestAllSimdAbiFunctor<CheckSimdBitwiseNotOperator>()); 190 test_all_simd_abi<CheckSimdPositiveSignOperator>(); 191 test_all_simd_abi<CheckSimdNegativeSignOperator>(); 192 test_all_simd_abi<CheckSimdBitwiseNotTraits>(); 193 return 0; 194 } 195