OLD | NEW |
---|---|
1 /* crosstest.py --test=test_arith.cpp --test=test_arith_frem.ll \ | 1 /* crosstest.py --test=test_arith.cpp --test=test_arith_frem.ll \ |
2 --test=test_arith_sqrt.ll --driver=test_arith_main.cpp \ | 2 --test=test_arith_sqrt.ll --driver=test_arith_main.cpp \ |
3 --prefix=Subzero_ --output=test_arith */ | 3 --prefix=Subzero_ --output=test_arith */ |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include <climits> // CHAR_BIT | |
8 #include <limits> | |
7 #include <cfloat> | 9 #include <cfloat> |
10 #include <cmath> // fmodf | |
8 #include <cstring> // memcmp | 11 #include <cstring> // memcmp |
9 #include <iostream> | 12 #include <iostream> |
10 | 13 |
11 // Include test_arith.h twice - once normally, and once within the | 14 // Include test_arith.h twice - once normally, and once within the |
12 // Subzero_ namespace, corresponding to the llc and Subzero translated | 15 // Subzero_ namespace, corresponding to the llc and Subzero translated |
13 // object files, respectively. | 16 // object files, respectively. |
14 #include "test_arith.h" | 17 #include "test_arith.h" |
15 namespace Subzero_ { | 18 namespace Subzero_ { |
16 #include "test_arith.h" | 19 #include "test_arith.h" |
17 } | 20 } |
18 | 21 |
19 volatile unsigned Values[] = { 0x0, 0x1, 0x7ffffffe, 0x7fffffff, | 22 volatile unsigned Values[] = INT_VALUE_ARRAY; |
20 0x80000000, 0x80000001, 0xfffffffe, 0xffffffff, | |
21 0x7e, 0x7f, 0x80, 0x81, | |
22 0xfe, 0xff, 0x100, 0x101, | |
23 0x7ffe, 0x7fff, 0x8000, 0x8001, | |
24 0xfffe, 0xffff, 0x10000, 0x10001, }; | |
25 const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 23 const static size_t NumValues = sizeof(Values) / sizeof(*Values); |
26 | 24 |
25 template <class T> bool inputsMayTriggerException(T Value1, T Value2) { | |
26 // Avoid HW divide-by-zero exception. | |
27 if (Value2 == 0) | |
28 return true; | |
29 // Avoid HW overflow exception (on x86-32). TODO: adjust | |
30 // for other architecture. | |
31 if (Value1 == std::numeric_limits<T>::min() && Value2 == -1) | |
32 return true; | |
33 return false; | |
34 } | |
35 | |
27 template <typename TypeUnsigned, typename TypeSigned> | 36 template <typename TypeUnsigned, typename TypeSigned> |
28 void testsInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 37 void testsInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { |
29 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); | 38 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); |
30 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); | 39 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); |
31 static struct { | 40 static struct { |
32 const char *Name; | 41 const char *Name; |
33 FuncTypeUnsigned FuncLlc; | 42 FuncTypeUnsigned FuncLlc; |
34 FuncTypeUnsigned FuncSz; | 43 FuncTypeUnsigned FuncSz; |
35 bool ExcludeDivExceptions; // for divide related tests | 44 bool ExcludeDivExceptions; // for divide related tests |
36 } Funcs[] = { | 45 } Funcs[] = { |
(...skipping 18 matching lines...) Expand all Loading... | |
55 | 64 |
56 if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) { | 65 if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) { |
57 // This is the "normal" version of the loop nest, for 32-bit or | 66 // This is the "normal" version of the loop nest, for 32-bit or |
58 // narrower types. | 67 // narrower types. |
59 for (size_t f = 0; f < NumFuncs; ++f) { | 68 for (size_t f = 0; f < NumFuncs; ++f) { |
60 for (size_t i = 0; i < NumValues; ++i) { | 69 for (size_t i = 0; i < NumValues; ++i) { |
61 for (size_t j = 0; j < NumValues; ++j) { | 70 for (size_t j = 0; j < NumValues; ++j) { |
62 TypeUnsigned Value1 = Values[i]; | 71 TypeUnsigned Value1 = Values[i]; |
63 TypeUnsigned Value2 = Values[j]; | 72 TypeUnsigned Value2 = Values[j]; |
64 // Avoid HW divide-by-zero exception. | 73 // Avoid HW divide-by-zero exception. |
65 if (Funcs[f].ExcludeDivExceptions && Value2 == 0) | 74 if (Funcs[f].ExcludeDivExceptions && |
66 continue; | 75 inputsMayTriggerException<TypeSigned>(Value1, Value2)) |
67 // Avoid HW overflow exception (on x86-32). TODO: adjust | |
68 // for other architectures. | |
69 if (Funcs[f].ExcludeDivExceptions && Value1 == 0x80000000 && | |
70 Value2 == 0xffffffff) | |
71 continue; | 76 continue; |
72 ++TotalTests; | 77 ++TotalTests; |
73 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 78 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); |
74 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 79 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); |
75 if (ResultSz == ResultLlc) { | 80 if (ResultSz == ResultLlc) { |
76 ++Passes; | 81 ++Passes; |
77 } else { | 82 } else { |
78 ++Failures; | 83 ++Failures; |
79 std::cout << "test" << Funcs[f].Name << (8 * sizeof(TypeUnsigned)) | 84 std::cout << "test" << Funcs[f].Name |
80 << "(" << Value1 << ", " << Value2 | 85 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1 |
81 << "): sz=" << (unsigned)ResultSz | 86 << ", " << Value2 << "): sz=" << (unsigned)ResultSz |
82 << " llc=" << (unsigned)ResultLlc << std::endl; | 87 << " llc=" << (unsigned)ResultLlc << std::endl; |
83 } | 88 } |
84 } | 89 } |
85 } | 90 } |
86 } | 91 } |
87 } else { | 92 } else { |
88 // This is the 64-bit version. Test values are synthesized from | 93 // This is the 64-bit version. Test values are synthesized from |
89 // the 32-bit values in Values[]. | 94 // the 32-bit values in Values[]. |
90 for (size_t f = 0; f < NumFuncs; ++f) { | 95 for (size_t f = 0; f < NumFuncs; ++f) { |
91 for (size_t iLo = 0; iLo < NumValues; ++iLo) { | 96 for (size_t iLo = 0; iLo < NumValues; ++iLo) { |
92 for (size_t iHi = 0; iHi < NumValues; ++iHi) { | 97 for (size_t iHi = 0; iHi < NumValues; ++iHi) { |
93 for (size_t jLo = 0; jLo < NumValues; ++jLo) { | 98 for (size_t jLo = 0; jLo < NumValues; ++jLo) { |
94 for (size_t jHi = 0; jHi < NumValues; ++jHi) { | 99 for (size_t jHi = 0; jHi < NumValues; ++jHi) { |
95 TypeUnsigned Value1 = | 100 TypeUnsigned Value1 = |
96 (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo]; | 101 (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo]; |
97 TypeUnsigned Value2 = | 102 TypeUnsigned Value2 = |
98 (((TypeUnsigned)Values[jHi]) << 32) + Values[jLo]; | 103 (((TypeUnsigned)Values[jHi]) << 32) + Values[jLo]; |
99 // Avoid HW divide-by-zero exception. | 104 if (Funcs[f].ExcludeDivExceptions && |
100 if (Funcs[f].ExcludeDivExceptions && Value2 == 0) | 105 inputsMayTriggerException<TypeSigned>(Value1, Value2)) |
101 continue; | 106 continue; |
102 ++TotalTests; | 107 ++TotalTests; |
103 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 108 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); |
104 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 109 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); |
105 if (ResultSz == ResultLlc) { | 110 if (ResultSz == ResultLlc) { |
106 ++Passes; | 111 ++Passes; |
107 } else { | 112 } else { |
108 ++Failures; | 113 ++Failures; |
109 std::cout << "test" << Funcs[f].Name | 114 std::cout << "test" << Funcs[f].Name |
110 << (8 * sizeof(TypeUnsigned)) << "(" << Value1 << ", " | 115 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1 |
111 << Value2 << "): sz=" << (unsigned)ResultSz | 116 << ", " << Value2 << "): sz=" << (unsigned)ResultSz |
112 << " llc=" << (unsigned)ResultLlc << std::endl; | 117 << " llc=" << (unsigned)ResultLlc << std::endl; |
113 } | 118 } |
114 } | 119 } |
115 } | 120 } |
116 } | 121 } |
117 } | 122 } |
118 } | 123 } |
119 } | 124 } |
120 } | 125 } |
121 | 126 |
127 // TODO: Replace with a portable PRNG from C++11. | |
Jim Stichnoth
2014/07/16 19:17:10
It would be good to have a comment explaining that
wala
2014/07/17 01:34:53
Adding a comment: Done.
The current size of the i
Jim Stichnoth
2014/07/17 13:03:13
Ah yes - I was forgetting that extra ^2 in my calc
| |
128 class PRNG { | |
129 public: | |
130 PRNG(uint32_t Seed = 1) : State(Seed) {} | |
131 | |
132 uint32_t operator()() { | |
133 // Lewis, Goodman, and Miller (1969) | |
134 State = (16807 * State) % 2147483647; | |
135 return State; | |
136 } | |
137 | |
138 private: | |
139 uint32_t State; | |
140 }; | |
141 | |
142 const static size_t MaxTestsPerFunc = 100000; | |
143 | |
144 template <typename Type, typename ElementType, typename CastType> | |
145 void outputVector(const Type Vect) { | |
146 const static size_t NumElementsInType = sizeof(Type) / sizeof(ElementType); | |
147 for (size_t i = 0; i < NumElementsInType; ++i) { | |
148 if (i > 0) | |
149 std::cout << ", "; | |
150 std::cout << (CastType) Vect[i]; | |
151 } | |
152 } | |
153 | |
154 template <typename TypeUnsigned, typename TypeSigned, | |
155 typename ElementTypeUnsigned, typename ElementTypeSigned> | |
156 void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { | |
157 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); | |
158 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); | |
159 static struct { | |
160 const char *Name; | |
161 FuncTypeUnsigned FuncLlc; | |
162 FuncTypeUnsigned FuncSz; | |
163 bool ExcludeDivExceptions; // for divide related tests | |
164 } Funcs[] = { | |
165 #define X(inst, op, isdiv) \ | |
166 { \ | |
167 STR(inst), (FuncTypeUnsigned)test##inst, \ | |
168 (FuncTypeUnsigned)Subzero_::test##inst, isdiv \ | |
169 } \ | |
170 , | |
171 UINTOP_TABLE | |
172 #undef X | |
173 #define X(inst, op, isdiv) \ | |
174 { \ | |
175 STR(inst), (FuncTypeUnsigned)(FuncTypeSigned)test##inst, \ | |
176 (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::test##inst, isdiv \ | |
177 } \ | |
178 , | |
179 SINTOP_TABLE | |
jvoung (off chromium)
2014/07/16 19:23:26
indent seems a bit more than usual, for SINTOP_TAB
wala
2014/07/17 01:34:53
Done.
| |
180 #undef X | |
181 }; | |
182 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | |
183 const static size_t NumElementsInType = | |
184 sizeof(TypeUnsigned) / sizeof(ElementTypeUnsigned); | |
185 for (size_t f = 0; f < NumFuncs; ++f) { | |
186 PRNG Index; | |
187 for (size_t i = 0; i < MaxTestsPerFunc; ++i) { | |
188 // Initialize the test vectors. | |
189 TypeUnsigned Value1, Value2; | |
190 for (size_t j = 0; j < NumElementsInType;) { | |
191 ElementTypeUnsigned Element1 = Values[Index() % NumElementsInType]; | |
192 ElementTypeUnsigned Element2 = Values[Index() % NumElementsInType]; | |
193 if (Funcs[f].ExcludeDivExceptions && | |
194 inputsMayTriggerException<ElementTypeSigned>(Element1, Element2)) | |
195 continue; | |
196 Value1[j] = Element1; | |
197 Value2[j] = Element2; | |
198 ++j; | |
199 } | |
200 // Perform the test. | |
201 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | |
202 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | |
203 ++TotalTests; | |
204 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { | |
205 ++Passes; | |
206 } else { | |
207 std::cout << "test" << Funcs[f].Name << "v" << NumElementsInType << "i" | |
208 << (CHAR_BIT * sizeof(ElementTypeUnsigned)) << "("; | |
209 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(Value1); | |
210 std::cout << ", "; | |
211 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(Value2); | |
212 std::cout << "): sz="; | |
213 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(ResultSz); | |
214 std::cout << " llc="; | |
215 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(ResultLlc); | |
216 std::cout << std::endl; | |
217 } | |
218 } | |
219 } | |
220 } | |
221 | |
122 template <typename Type> | 222 template <typename Type> |
123 void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 223 void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { |
124 static const Type NegInf = -1.0 / 0.0; | 224 static const Type NegInf = -1.0 / 0.0; |
125 static const Type PosInf = 1.0 / 0.0; | 225 static const Type PosInf = 1.0 / 0.0; |
126 static const Type Nan = 0.0 / 0.0; | 226 static const Type Nan = 0.0 / 0.0; |
127 static const Type NegNan = -0.0 / 0.0; | 227 static const Type NegNan = -0.0 / 0.0; |
128 volatile Type Values[] = { | 228 volatile Type Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan); |
129 0, 1, 0x7e, | |
130 0x7f, 0x80, 0x81, | |
131 0xfe, 0xff, 0x7ffe, | |
132 0x7fff, 0x8000, 0x8001, | |
133 0xfffe, 0xffff, 0x7ffffffe, | |
134 0x7fffffff, 0x80000000, 0x80000001, | |
135 0xfffffffe, 0xffffffff, 0x100000000ll, | |
136 0x100000001ll, 0x7ffffffffffffffell, 0x7fffffffffffffffll, | |
137 0x8000000000000000ll, 0x8000000000000001ll, 0xfffffffffffffffell, | |
138 0xffffffffffffffffll, NegInf, PosInf, | |
139 Nan, NegNan, -0.0, | |
140 FLT_MIN, FLT_MAX, | |
141 DBL_MIN, DBL_MAX | |
142 }; | |
143 const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 229 const static size_t NumValues = sizeof(Values) / sizeof(*Values); |
144 typedef Type (*FuncType)(Type, Type); | 230 typedef Type (*FuncType)(Type, Type); |
145 static struct { | 231 static struct { |
146 const char *Name; | 232 const char *Name; |
147 FuncType FuncLlc; | 233 FuncType FuncLlc; |
148 FuncType FuncSz; | 234 FuncType FuncSz; |
149 } Funcs[] = { | 235 } Funcs[] = { |
150 #define X(inst, op, func) \ | 236 #define X(inst, op, func) \ |
151 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \ | 237 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \ |
152 , | 238 , |
153 FPOP_TABLE | 239 FPOP_TABLE |
154 #undef X | 240 #undef X |
155 }; | 241 }; |
156 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 242 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); |
157 | 243 |
158 for (size_t f = 0; f < NumFuncs; ++f) { | 244 for (size_t f = 0; f < NumFuncs; ++f) { |
159 for (size_t i = 0; i < NumValues; ++i) { | 245 for (size_t i = 0; i < NumValues; ++i) { |
160 for (size_t j = 0; j < NumValues; ++j) { | 246 for (size_t j = 0; j < NumValues; ++j) { |
161 Type Value1 = Values[i]; | 247 Type Value1 = Values[i]; |
162 Type Value2 = Values[j]; | 248 Type Value2 = Values[j]; |
163 ++TotalTests; | 249 ++TotalTests; |
164 Type ResultSz = Funcs[f].FuncSz(Value1, Value2); | 250 Type ResultSz = Funcs[f].FuncSz(Value1, Value2); |
165 Type ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 251 Type ResultLlc = Funcs[f].FuncLlc(Value1, Value2); |
166 // Compare results using memcmp() in case they are both NaN. | 252 // Compare results using memcmp() in case they are both NaN. |
167 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { | 253 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { |
168 ++Passes; | 254 ++Passes; |
169 } else { | 255 } else { |
170 ++Failures; | 256 ++Failures; |
171 std::cout << std::fixed << "test" << Funcs[f].Name | 257 std::cout << std::fixed << "test" << Funcs[f].Name |
172 << (8 * sizeof(Type)) << "(" << Value1 << ", " << Value2 | 258 << (CHAR_BIT * sizeof(Type)) << "(" << Value1 << ", " |
173 << "): sz=" << ResultSz << " llc=" << ResultLlc | 259 << Value2 << "): sz=" << ResultSz << " llc=" << ResultLlc |
174 << std::endl; | 260 << std::endl; |
175 } | 261 } |
176 } | 262 } |
177 } | 263 } |
178 } | 264 } |
179 for (size_t i = 0; i < NumValues; ++i) { | 265 for (size_t i = 0; i < NumValues; ++i) { |
180 Type Value = Values[i]; | 266 Type Value = Values[i]; |
181 ++TotalTests; | 267 ++TotalTests; |
182 Type ResultSz = Subzero_::mySqrt(Value); | 268 Type ResultSz = Subzero_::mySqrt(Value); |
183 Type ResultLlc = mySqrt(Value); | 269 Type ResultLlc = mySqrt(Value); |
184 // Compare results using memcmp() in case they are both NaN. | 270 // Compare results using memcmp() in case they are both NaN. |
185 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { | 271 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { |
186 ++Passes; | 272 ++Passes; |
187 } else { | 273 } else { |
188 ++Failures; | 274 ++Failures; |
189 std::cout << std::fixed << "test_sqrt" | 275 std::cout << std::fixed << "test_sqrt" << (CHAR_BIT * sizeof(Type)) << "(" |
190 << (8 * sizeof(Type)) << "(" << Value | 276 << Value << "): sz=" << ResultSz << " llc=" << ResultLlc |
191 << "): sz=" << ResultSz << " llc=" << ResultLlc | |
192 << std::endl; | 277 << std::endl; |
193 } | 278 } |
194 } | 279 } |
195 } | 280 } |
196 | 281 |
282 void testsVecFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { | |
283 static const float NegInf = -1.0 / 0.0; | |
284 static const float PosInf = 1.0 / 0.0; | |
285 static const float Nan = 0.0 / 0.0; | |
286 static const float NegNan = -0.0 / 0.0; | |
287 volatile float Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan); | |
288 const static size_t NumValues = sizeof(Values) / sizeof(*Values); | |
289 typedef v4f32 (*FuncType)(v4f32, v4f32); | |
290 static struct { | |
291 const char *Name; | |
292 FuncType FuncLlc; | |
293 FuncType FuncSz; | |
294 } Funcs[] = { | |
295 #define X(inst, op, func) \ | |
296 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \ | |
297 , | |
298 FPOP_TABLE | |
299 #undef X | |
300 }; | |
301 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | |
302 const static size_t NumElementsInType = 4; | |
303 for (size_t f = 0; f < NumFuncs; ++f) { | |
304 PRNG Index; | |
305 for (size_t i = 0; i < MaxTestsPerFunc; ++i) { | |
306 // Initialize the test vectors. | |
307 v4f32 Value1, Value2; | |
308 for (size_t j = 0; j < NumElementsInType; ++j) { | |
309 Value1[j] = Values[Index() % NumElementsInType]; | |
310 Value2[j] = Values[Index() % NumElementsInType]; | |
311 } | |
312 // Perform the test. | |
313 v4f32 ResultSz = Funcs[f].FuncSz(Value1, Value2); | |
314 v4f32 ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | |
315 ++TotalTests; | |
316 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { | |
317 ++Passes; | |
318 } else { | |
319 ++Failures; | |
320 std::cout << std::fixed << "test" << Funcs[f].Name << "v4f32" | |
321 << "("; | |
322 outputVector<v4f32, float, float>(Value1); | |
323 std::cout << ", "; | |
324 outputVector<v4f32, float, float>(Value2); | |
325 std::cout << "): sz="; | |
326 outputVector<v4f32, float, float>(ResultSz); | |
327 std::cout << " llc="; | |
328 outputVector<v4f32, float, float>(ResultLlc); | |
329 std::cout << std::endl; | |
330 } | |
331 } | |
332 } | |
333 } | |
334 | |
197 int main(int argc, char **argv) { | 335 int main(int argc, char **argv) { |
198 size_t TotalTests = 0; | 336 size_t TotalTests = 0; |
199 size_t Passes = 0; | 337 size_t Passes = 0; |
200 size_t Failures = 0; | 338 size_t Failures = 0; |
201 | 339 |
202 testsInt<uint8_t, int8_t>(TotalTests, Passes, Failures); | 340 testsInt<uint8_t, int8_t>(TotalTests, Passes, Failures); |
203 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures); | 341 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures); |
204 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures); | 342 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures); |
205 testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures); | 343 testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures); |
344 testsVecInt<v4ui32, v4si32, uint32_t, int32_t>(TotalTests, Passes, Failures); | |
345 testsVecInt<v8ui16, v8si16, uint16_t, int16_t>(TotalTests, Passes, Failures); | |
346 testsVecInt<v16ui8, v16si8, uint8_t, int8_t>(TotalTests, Passes, Failures); | |
206 testsFp<float>(TotalTests, Passes, Failures); | 347 testsFp<float>(TotalTests, Passes, Failures); |
207 testsFp<double>(TotalTests, Passes, Failures); | 348 testsFp<double>(TotalTests, Passes, Failures); |
349 testsVecFp(TotalTests, Passes, Failures); | |
208 | 350 |
209 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes | 351 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes |
210 << " Failures=" << Failures << "\n"; | 352 << " Failures=" << Failures << "\n"; |
211 return Failures; | 353 return Failures; |
212 } | 354 } |
355 | |
356 extern "C" { | |
357 // Subzero helpers | |
358 v4si32 Sz_shl_v4i32(v4si32 a, v4si32 b) { return a << b; } | |
359 v4si32 Sz_ashr_v4i32(v4si32 a, v4si32 b) { return a >> b; } | |
360 v4ui32 Sz_lshr_v4i32(v4ui32 a, v4ui32 b) { return a >> b; } | |
361 v4si32 Sz_sdiv_v4i32(v4si32 a, v4si32 b) { return a / b; } | |
362 v4ui32 Sz_udiv_v4i32(v4ui32 a, v4ui32 b) { return a / b; } | |
363 v4si32 Sz_srem_v4i32(v4si32 a, v4si32 b) { return a % b; } | |
364 v4ui32 Sz_urem_v4i32(v4ui32 a, v4ui32 b) { return a % b; } | |
365 | |
366 v8si16 Sz_shl_v8i16(v8si16 a, v8si16 b) { return a << b; } | |
367 v8si16 Sz_ashr_v8i16(v8si16 a, v8si16 b) { return a >> b; } | |
368 v8ui16 Sz_lshr_v8i16(v8ui16 a, v8ui16 b) { return a >> b; } | |
369 v8si16 Sz_sdiv_v8i16(v8si16 a, v8si16 b) { return a / b; } | |
370 v8ui16 Sz_udiv_v8i16(v8ui16 a, v8ui16 b) { return a / b; } | |
371 v8si16 Sz_srem_v8i16(v8si16 a, v8si16 b) { return a % b; } | |
372 v8ui16 Sz_urem_v8i16(v8ui16 a, v8ui16 b) { return a % b; } | |
373 | |
374 v16ui8 Sz_mul_v16i8(v16ui8 a, v16ui8 b) { return a * b; } | |
375 v16si8 Sz_shl_v16i8(v16si8 a, v16si8 b) { return a << b; } | |
376 v16si8 Sz_ashr_v16i8(v16si8 a, v16si8 b) { return a >> b; } | |
377 v16ui8 Sz_lshr_v16i8(v16ui8 a, v16ui8 b) { return a >> b; } | |
378 v16si8 Sz_sdiv_v16i8(v16si8 a, v16si8 b) { return a / b; } | |
379 v16ui8 Sz_udiv_v16i8(v16ui8 a, v16ui8 b) { return a / b; } | |
380 v16si8 Sz_srem_v16i8(v16si8 a, v16si8 b) { return a % b; } | |
381 v16ui8 Sz_urem_v16i8(v16ui8 a, v16ui8 b) { return a % b; } | |
382 | |
383 v4f32 Sz_frem_v4f32(v4f32 a, v4f32 b) { | |
384 v4f32 Result; | |
385 for (int i = 0; i < 4; ++i) | |
386 Result[i] = fmodf(a[i], b[i]); | |
387 return Result; | |
388 } | |
389 } | |
OLD | NEW |