blob: b032a5fcc06a0c4705f9b437ba11b704f8ee090f [file] [log] [blame]
Matt Wala89a7c2b2014-07-22 10:55:30 -07001//===- subzero/crosstest/test_arith_main.cpp - Driver for tests -----------===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Driver for crosstesting arithmetic operations
11//
12//===----------------------------------------------------------------------===//
13
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070014/* crosstest.py --test=test_arith.cpp --test=test_arith_frem.ll \
Jan Voungf37fbbe2014-07-09 16:13:13 -070015 --test=test_arith_sqrt.ll --driver=test_arith_main.cpp \
16 --prefix=Subzero_ --output=test_arith */
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070017
18#include <stdint.h>
19
Matt Wala7fa22d82014-07-17 12:41:31 -070020#include <climits> // CHAR_BIT
21#include <limits>
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070022#include <cfloat>
Matt Wala7fa22d82014-07-17 12:41:31 -070023#include <cmath> // fmodf
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070024#include <cstring> // memcmp
25#include <iostream>
26
27// Include test_arith.h twice - once normally, and once within the
28// Subzero_ namespace, corresponding to the llc and Subzero translated
29// object files, respectively.
30#include "test_arith.h"
31namespace Subzero_ {
32#include "test_arith.h"
33}
34
Matt Wala7fa22d82014-07-17 12:41:31 -070035template <class T> bool inputsMayTriggerException(T Value1, T Value2) {
36 // Avoid HW divide-by-zero exception.
37 if (Value2 == 0)
38 return true;
39 // Avoid HW overflow exception (on x86-32). TODO: adjust
40 // for other architecture.
41 if (Value1 == std::numeric_limits<T>::min() && Value2 == -1)
42 return true;
43 return false;
44}
45
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070046template <typename TypeUnsigned, typename TypeSigned>
47void testsInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
48 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned);
49 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned);
Matt Wala35ec3732014-07-18 16:32:16 -070050 volatile unsigned Values[] = INT_VALUE_ARRAY;
51 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070052 static struct {
Jim Stichnoth7da431b2014-08-05 11:22:37 -070053 // For functions that operate on unsigned values, the
54 // FuncLlcSigned and FuncSzSigned fields are NULL. For functions
55 // that operate on signed values, the FuncLlcUnsigned and
56 // FuncSzUnsigned fields are NULL.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070057 const char *Name;
Jim Stichnoth7da431b2014-08-05 11:22:37 -070058 FuncTypeUnsigned FuncLlcUnsigned;
59 FuncTypeUnsigned FuncSzUnsigned;
60 FuncTypeSigned FuncLlcSigned;
61 FuncTypeSigned FuncSzSigned;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070062 bool ExcludeDivExceptions; // for divide related tests
63 } Funcs[] = {
64#define X(inst, op, isdiv) \
Jim Stichnoth7da431b2014-08-05 11:22:37 -070065 { STR(inst), test##inst, Subzero_::test##inst, NULL, NULL, isdiv } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070066 ,
67 UINTOP_TABLE
68#undef X
69#define X(inst, op, isdiv) \
Jim Stichnoth7da431b2014-08-05 11:22:37 -070070 { STR(inst), NULL, NULL, test##inst, Subzero_::test##inst, isdiv } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070071 ,
Matt Wala7fa22d82014-07-17 12:41:31 -070072 SINTOP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070073#undef X
Matt Wala7fa22d82014-07-17 12:41:31 -070074 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070075 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
76
77 if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) {
78 // This is the "normal" version of the loop nest, for 32-bit or
79 // narrower types.
80 for (size_t f = 0; f < NumFuncs; ++f) {
81 for (size_t i = 0; i < NumValues; ++i) {
82 for (size_t j = 0; j < NumValues; ++j) {
83 TypeUnsigned Value1 = Values[i];
84 TypeUnsigned Value2 = Values[j];
85 // Avoid HW divide-by-zero exception.
Matt Wala7fa22d82014-07-17 12:41:31 -070086 if (Funcs[f].ExcludeDivExceptions &&
87 inputsMayTriggerException<TypeSigned>(Value1, Value2))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070088 continue;
89 ++TotalTests;
Jim Stichnoth7da431b2014-08-05 11:22:37 -070090 TypeUnsigned ResultSz, ResultLlc;
91 if (Funcs[f].FuncSzUnsigned) {
92 ResultSz = Funcs[f].FuncSzUnsigned(Value1, Value2);
93 ResultLlc = Funcs[f].FuncLlcUnsigned(Value1, Value2);
94 } else {
95 ResultSz = Funcs[f].FuncSzSigned(Value1, Value2);
96 ResultLlc = Funcs[f].FuncLlcSigned(Value1, Value2);
97 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070098 if (ResultSz == ResultLlc) {
99 ++Passes;
100 } else {
101 ++Failures;
Matt Wala7fa22d82014-07-17 12:41:31 -0700102 std::cout << "test" << Funcs[f].Name
103 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1
104 << ", " << Value2 << "): sz=" << (unsigned)ResultSz
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700105 << " llc=" << (unsigned)ResultLlc << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700106 }
107 }
108 }
109 }
110 } else {
111 // This is the 64-bit version. Test values are synthesized from
112 // the 32-bit values in Values[].
113 for (size_t f = 0; f < NumFuncs; ++f) {
114 for (size_t iLo = 0; iLo < NumValues; ++iLo) {
115 for (size_t iHi = 0; iHi < NumValues; ++iHi) {
116 for (size_t jLo = 0; jLo < NumValues; ++jLo) {
117 for (size_t jHi = 0; jHi < NumValues; ++jHi) {
118 TypeUnsigned Value1 =
119 (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo];
120 TypeUnsigned Value2 =
121 (((TypeUnsigned)Values[jHi]) << 32) + Values[jLo];
Matt Wala7fa22d82014-07-17 12:41:31 -0700122 if (Funcs[f].ExcludeDivExceptions &&
123 inputsMayTriggerException<TypeSigned>(Value1, Value2))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700124 continue;
125 ++TotalTests;
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700126 TypeUnsigned ResultSz, ResultLlc;
127 if (Funcs[f].FuncSzUnsigned) {
128 ResultSz = Funcs[f].FuncSzUnsigned(Value1, Value2);
129 ResultLlc = Funcs[f].FuncLlcUnsigned(Value1, Value2);
130 } else {
131 ResultSz = Funcs[f].FuncSzSigned(Value1, Value2);
132 ResultLlc = Funcs[f].FuncLlcSigned(Value1, Value2);
133 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700134 if (ResultSz == ResultLlc) {
135 ++Passes;
136 } else {
137 ++Failures;
138 std::cout << "test" << Funcs[f].Name
Matt Wala7fa22d82014-07-17 12:41:31 -0700139 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1
140 << ", " << Value2 << "): sz=" << (unsigned)ResultSz
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700141 << " llc=" << (unsigned)ResultLlc << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700142 }
143 }
144 }
145 }
146 }
147 }
148 }
149}
150
Matt Wala7fa22d82014-07-17 12:41:31 -0700151const static size_t MaxTestsPerFunc = 100000;
152
Matt Wala89a7c2b2014-07-22 10:55:30 -0700153template <typename TypeUnsignedLabel, typename TypeSignedLabel>
Matt Wala7fa22d82014-07-17 12:41:31 -0700154void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
Matt Wala89a7c2b2014-07-22 10:55:30 -0700155 typedef typename Vectors<TypeUnsignedLabel>::Ty TypeUnsigned;
156 typedef typename Vectors<TypeSignedLabel>::Ty TypeSigned;
157 typedef typename Vectors<TypeUnsignedLabel>::ElementTy ElementTypeUnsigned;
158 typedef typename Vectors<TypeSignedLabel>::ElementTy ElementTypeSigned;
159
Matt Wala7fa22d82014-07-17 12:41:31 -0700160 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned);
161 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned);
Matt Wala35ec3732014-07-18 16:32:16 -0700162 volatile unsigned Values[] = INT_VALUE_ARRAY;
163 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
Matt Wala7fa22d82014-07-17 12:41:31 -0700164 static struct {
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700165 // For functions that operate on unsigned values, the
166 // FuncLlcSigned and FuncSzSigned fields are NULL. For functions
167 // that operate on signed values, the FuncLlcUnsigned and
168 // FuncSzUnsigned fields are NULL.
Matt Wala7fa22d82014-07-17 12:41:31 -0700169 const char *Name;
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700170 FuncTypeUnsigned FuncLlcUnsigned;
171 FuncTypeUnsigned FuncSzUnsigned;
172 FuncTypeSigned FuncLlcSigned;
173 FuncTypeSigned FuncSzSigned;
Matt Wala7fa22d82014-07-17 12:41:31 -0700174 bool ExcludeDivExceptions; // for divide related tests
175 } Funcs[] = {
176#define X(inst, op, isdiv) \
177 { \
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700178 STR(inst), test##inst, Subzero_::test##inst, NULL, NULL, isdiv \
Matt Wala7fa22d82014-07-17 12:41:31 -0700179 } \
180 ,
181 UINTOP_TABLE
182#undef X
183#define X(inst, op, isdiv) \
184 { \
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700185 STR(inst), NULL, NULL, test##inst, Subzero_::test##inst, isdiv \
Matt Wala7fa22d82014-07-17 12:41:31 -0700186 } \
187 ,
188 SINTOP_TABLE
189#undef X
190 };
191 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
Matt Wala89a7c2b2014-07-22 10:55:30 -0700192 const static size_t NumElementsInType = Vectors<TypeUnsigned>::NumElements;
Matt Wala7fa22d82014-07-17 12:41:31 -0700193 for (size_t f = 0; f < NumFuncs; ++f) {
194 PRNG Index;
195 for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
196 // Initialize the test vectors.
197 TypeUnsigned Value1, Value2;
198 for (size_t j = 0; j < NumElementsInType;) {
Matt Wala35ec3732014-07-18 16:32:16 -0700199 ElementTypeUnsigned Element1 = Values[Index() % NumValues];
200 ElementTypeUnsigned Element2 = Values[Index() % NumValues];
Matt Wala7fa22d82014-07-17 12:41:31 -0700201 if (Funcs[f].ExcludeDivExceptions &&
202 inputsMayTriggerException<ElementTypeSigned>(Element1, Element2))
203 continue;
204 Value1[j] = Element1;
205 Value2[j] = Element2;
206 ++j;
207 }
208 // Perform the test.
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700209 TypeUnsigned ResultSz, ResultLlc;
Matt Wala7fa22d82014-07-17 12:41:31 -0700210 ++TotalTests;
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700211 if (Funcs[f].FuncSzUnsigned) {
212 ResultSz = Funcs[f].FuncSzUnsigned(Value1, Value2);
213 ResultLlc = Funcs[f].FuncLlcUnsigned(Value1, Value2);
214 } else {
215 ResultSz = Funcs[f].FuncSzSigned(Value1, Value2);
216 ResultLlc = Funcs[f].FuncLlcSigned(Value1, Value2);
217 }
Matt Wala7fa22d82014-07-17 12:41:31 -0700218 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
219 ++Passes;
220 } else {
Matt Wala89a7c2b2014-07-22 10:55:30 -0700221 ++Failures;
Matt Wala7fa22d82014-07-17 12:41:31 -0700222 std::cout << "test" << Funcs[f].Name << "v" << NumElementsInType << "i"
Matt Wala89a7c2b2014-07-22 10:55:30 -0700223 << (CHAR_BIT * sizeof(ElementTypeUnsigned)) << "("
224 << vectAsString<TypeUnsignedLabel>(Value1) << ","
225 << vectAsString<TypeUnsignedLabel>(Value2)
226 << "): sz=" << vectAsString<TypeUnsignedLabel>(ResultSz)
227 << " llc=" << vectAsString<TypeUnsignedLabel>(ResultLlc)
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700228 << "\n";
Matt Wala7fa22d82014-07-17 12:41:31 -0700229 }
230 }
231 }
232}
233
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700234template <typename Type>
235void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
236 static const Type NegInf = -1.0 / 0.0;
237 static const Type PosInf = 1.0 / 0.0;
238 static const Type Nan = 0.0 / 0.0;
Jan Voungf37fbbe2014-07-09 16:13:13 -0700239 static const Type NegNan = -0.0 / 0.0;
Matt Wala7fa22d82014-07-17 12:41:31 -0700240 volatile Type Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700241 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
242 typedef Type (*FuncType)(Type, Type);
243 static struct {
244 const char *Name;
245 FuncType FuncLlc;
246 FuncType FuncSz;
247 } Funcs[] = {
248#define X(inst, op, func) \
249 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \
250 ,
251 FPOP_TABLE
252#undef X
Matt Wala7fa22d82014-07-17 12:41:31 -0700253 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700254 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
255
256 for (size_t f = 0; f < NumFuncs; ++f) {
257 for (size_t i = 0; i < NumValues; ++i) {
258 for (size_t j = 0; j < NumValues; ++j) {
259 Type Value1 = Values[i];
260 Type Value2 = Values[j];
261 ++TotalTests;
262 Type ResultSz = Funcs[f].FuncSz(Value1, Value2);
263 Type ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
264 // Compare results using memcmp() in case they are both NaN.
265 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) {
266 ++Passes;
267 } else {
268 ++Failures;
269 std::cout << std::fixed << "test" << Funcs[f].Name
Matt Wala7fa22d82014-07-17 12:41:31 -0700270 << (CHAR_BIT * sizeof(Type)) << "(" << Value1 << ", "
271 << Value2 << "): sz=" << ResultSz << " llc=" << ResultLlc
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700272 << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700273 }
274 }
275 }
276 }
Jan Voungf37fbbe2014-07-09 16:13:13 -0700277 for (size_t i = 0; i < NumValues; ++i) {
278 Type Value = Values[i];
279 ++TotalTests;
280 Type ResultSz = Subzero_::mySqrt(Value);
281 Type ResultLlc = mySqrt(Value);
282 // Compare results using memcmp() in case they are both NaN.
283 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) {
284 ++Passes;
285 } else {
286 ++Failures;
Matt Wala7fa22d82014-07-17 12:41:31 -0700287 std::cout << std::fixed << "test_sqrt" << (CHAR_BIT * sizeof(Type)) << "("
288 << Value << "): sz=" << ResultSz << " llc=" << ResultLlc
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700289 << "\n";
Jan Voungf37fbbe2014-07-09 16:13:13 -0700290 }
291 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700292}
293
Matt Wala7fa22d82014-07-17 12:41:31 -0700294void testsVecFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
295 static const float NegInf = -1.0 / 0.0;
296 static const float PosInf = 1.0 / 0.0;
297 static const float Nan = 0.0 / 0.0;
298 static const float NegNan = -0.0 / 0.0;
299 volatile float Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan);
300 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
301 typedef v4f32 (*FuncType)(v4f32, v4f32);
302 static struct {
303 const char *Name;
304 FuncType FuncLlc;
305 FuncType FuncSz;
306 } Funcs[] = {
307#define X(inst, op, func) \
308 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \
309 ,
310 FPOP_TABLE
311#undef X
312 };
313 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
314 const static size_t NumElementsInType = 4;
315 for (size_t f = 0; f < NumFuncs; ++f) {
316 PRNG Index;
317 for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
318 // Initialize the test vectors.
319 v4f32 Value1, Value2;
320 for (size_t j = 0; j < NumElementsInType; ++j) {
Matt Wala35ec3732014-07-18 16:32:16 -0700321 Value1[j] = Values[Index() % NumValues];
322 Value2[j] = Values[Index() % NumValues];
Matt Wala7fa22d82014-07-17 12:41:31 -0700323 }
324 // Perform the test.
325 v4f32 ResultSz = Funcs[f].FuncSz(Value1, Value2);
326 v4f32 ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
327 ++TotalTests;
328 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
329 ++Passes;
330 } else {
331 ++Failures;
Matt Wala89a7c2b2014-07-22 10:55:30 -0700332 std::cout << "test" << Funcs[f].Name << "v4f32"
333 << "(" << vectAsString<v4f32>(Value1) << ","
334 << vectAsString<v4f32>(Value2)
335 << "): sz=" << vectAsString<v4f32>(ResultSz) << " llc"
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700336 << vectAsString<v4f32>(ResultLlc) << "\n";
Matt Wala7fa22d82014-07-17 12:41:31 -0700337 }
338 }
339 }
340}
341
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700342int main(int argc, char **argv) {
343 size_t TotalTests = 0;
344 size_t Passes = 0;
345 size_t Failures = 0;
346
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700347 testsInt<uint8_t, myint8_t>(TotalTests, Passes, Failures);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700348 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures);
349 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures);
350 testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures);
Matt Wala89a7c2b2014-07-22 10:55:30 -0700351 testsVecInt<v4ui32, v4si32>(TotalTests, Passes, Failures);
352 testsVecInt<v8ui16, v8si16>(TotalTests, Passes, Failures);
353 testsVecInt<v16ui8, v16si8>(TotalTests, Passes, Failures);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700354 testsFp<float>(TotalTests, Passes, Failures);
355 testsFp<double>(TotalTests, Passes, Failures);
Matt Wala7fa22d82014-07-17 12:41:31 -0700356 testsVecFp(TotalTests, Passes, Failures);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700357
358 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
359 << " Failures=" << Failures << "\n";
360 return Failures;
361}
Matt Wala7fa22d82014-07-17 12:41:31 -0700362
363extern "C" {
364// Subzero helpers
365 v4si32 Sz_shl_v4i32(v4si32 a, v4si32 b) { return a << b; }
366 v4si32 Sz_ashr_v4i32(v4si32 a, v4si32 b) { return a >> b; }
367 v4ui32 Sz_lshr_v4i32(v4ui32 a, v4ui32 b) { return a >> b; }
368 v4si32 Sz_sdiv_v4i32(v4si32 a, v4si32 b) { return a / b; }
369 v4ui32 Sz_udiv_v4i32(v4ui32 a, v4ui32 b) { return a / b; }
370 v4si32 Sz_srem_v4i32(v4si32 a, v4si32 b) { return a % b; }
371 v4ui32 Sz_urem_v4i32(v4ui32 a, v4ui32 b) { return a % b; }
372
373 v8si16 Sz_shl_v8i16(v8si16 a, v8si16 b) { return a << b; }
374 v8si16 Sz_ashr_v8i16(v8si16 a, v8si16 b) { return a >> b; }
375 v8ui16 Sz_lshr_v8i16(v8ui16 a, v8ui16 b) { return a >> b; }
376 v8si16 Sz_sdiv_v8i16(v8si16 a, v8si16 b) { return a / b; }
377 v8ui16 Sz_udiv_v8i16(v8ui16 a, v8ui16 b) { return a / b; }
378 v8si16 Sz_srem_v8i16(v8si16 a, v8si16 b) { return a % b; }
379 v8ui16 Sz_urem_v8i16(v8ui16 a, v8ui16 b) { return a % b; }
380
381 v16ui8 Sz_mul_v16i8(v16ui8 a, v16ui8 b) { return a * b; }
382 v16si8 Sz_shl_v16i8(v16si8 a, v16si8 b) { return a << b; }
383 v16si8 Sz_ashr_v16i8(v16si8 a, v16si8 b) { return a >> b; }
384 v16ui8 Sz_lshr_v16i8(v16ui8 a, v16ui8 b) { return a >> b; }
385 v16si8 Sz_sdiv_v16i8(v16si8 a, v16si8 b) { return a / b; }
386 v16ui8 Sz_udiv_v16i8(v16ui8 a, v16ui8 b) { return a / b; }
387 v16si8 Sz_srem_v16i8(v16si8 a, v16si8 b) { return a % b; }
388 v16ui8 Sz_urem_v16i8(v16ui8 a, v16ui8 b) { return a % b; }
389
390 v4f32 Sz_frem_v4f32(v4f32 a, v4f32 b) {
391 v4f32 Result;
392 for (int i = 0; i < 4; ++i)
393 Result[i] = fmodf(a[i], b[i]);
394 return Result;
395 }
396}