xref: /llvm-project/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp (revision 7f845cba2ccc2ab637b8e40fbafb9f83a2d67c70)
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