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 | 7 #include <climits> // CHAR_BIT |
8 #include <limits> | 8 #include <limits> |
9 #include <cfloat> | 9 #include <cfloat> |
10 #include <cmath> // fmodf | 10 #include <cmath> // fmodf |
11 #include <cstring> // memcmp | 11 #include <cstring> // memcmp |
12 #include <iostream> | 12 #include <iostream> |
13 | 13 |
| 14 #include "vectors.h" |
| 15 |
14 // Include test_arith.h twice - once normally, and once within the | 16 // Include test_arith.h twice - once normally, and once within the |
15 // Subzero_ namespace, corresponding to the llc and Subzero translated | 17 // Subzero_ namespace, corresponding to the llc and Subzero translated |
16 // object files, respectively. | 18 // object files, respectively. |
17 #include "test_arith.h" | 19 #include "test_arith.h" |
18 namespace Subzero_ { | 20 namespace Subzero_ { |
19 #include "test_arith.h" | 21 #include "test_arith.h" |
20 } | 22 } |
21 | 23 |
22 volatile unsigned Values[] = INT_VALUE_ARRAY; | 24 volatile unsigned Values[] = INT_VALUE_ARRAY; |
23 const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 25 const static size_t NumValues = sizeof(Values) / sizeof(*Values); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 << " llc=" << (unsigned)ResultLlc << std::endl; | 119 << " llc=" << (unsigned)ResultLlc << std::endl; |
118 } | 120 } |
119 } | 121 } |
120 } | 122 } |
121 } | 123 } |
122 } | 124 } |
123 } | 125 } |
124 } | 126 } |
125 } | 127 } |
126 | 128 |
127 // Vectors are deterministically constructed by selecting elements from | |
128 // a pool of scalar values based on a pseudorandom sequence. Testing | |
129 // all possible combinations of scalar values from the value table is | |
130 // not tractable. | |
131 // TODO: Replace with a portable PRNG from C++11. | |
132 class PRNG { | |
133 public: | |
134 PRNG(uint32_t Seed = 1) : State(Seed) {} | |
135 | |
136 uint32_t operator()() { | |
137 // Lewis, Goodman, and Miller (1969) | |
138 State = (16807 * State) % 2147483647; | |
139 return State; | |
140 } | |
141 | |
142 private: | |
143 uint32_t State; | |
144 }; | |
145 | |
146 const static size_t MaxTestsPerFunc = 100000; | 129 const static size_t MaxTestsPerFunc = 100000; |
147 | 130 |
148 template <typename Type, typename ElementType, typename CastType> | 131 template <typename TypeUnsignedLabel, typename TypeSignedLabel> |
149 void outputVector(const Type Vect) { | 132 void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { |
150 const static size_t NumElementsInType = sizeof(Type) / sizeof(ElementType); | 133 typedef typename Vectors<TypeUnsignedLabel>::Ty TypeUnsigned; |
151 for (size_t i = 0; i < NumElementsInType; ++i) { | 134 typedef typename Vectors<TypeSignedLabel>::Ty TypeSigned; |
152 if (i > 0) | 135 typedef typename Vectors<TypeUnsignedLabel>::ElementTy ElementTypeUnsigned; |
153 std::cout << ", "; | 136 typedef typename Vectors<TypeSignedLabel>::ElementTy ElementTypeSigned; |
154 std::cout << (CastType) Vect[i]; | |
155 } | |
156 } | |
157 | 137 |
158 template <typename TypeUnsigned, typename TypeSigned, | |
159 typename ElementTypeUnsigned, typename ElementTypeSigned> | |
160 void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { | |
161 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); | 138 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); |
162 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); | 139 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); |
163 static struct { | 140 static struct { |
164 const char *Name; | 141 const char *Name; |
165 FuncTypeUnsigned FuncLlc; | 142 FuncTypeUnsigned FuncLlc; |
166 FuncTypeUnsigned FuncSz; | 143 FuncTypeUnsigned FuncSz; |
167 bool ExcludeDivExceptions; // for divide related tests | 144 bool ExcludeDivExceptions; // for divide related tests |
168 } Funcs[] = { | 145 } Funcs[] = { |
169 #define X(inst, op, isdiv) \ | 146 #define X(inst, op, isdiv) \ |
170 { \ | 147 { \ |
171 STR(inst), (FuncTypeUnsigned)test##inst, \ | 148 STR(inst), (FuncTypeUnsigned)test##inst, \ |
172 (FuncTypeUnsigned)Subzero_::test##inst, isdiv \ | 149 (FuncTypeUnsigned)Subzero_::test##inst, isdiv \ |
173 } \ | 150 } \ |
174 , | 151 , |
175 UINTOP_TABLE | 152 UINTOP_TABLE |
176 #undef X | 153 #undef X |
177 #define X(inst, op, isdiv) \ | 154 #define X(inst, op, isdiv) \ |
178 { \ | 155 { \ |
179 STR(inst), (FuncTypeUnsigned)(FuncTypeSigned)test##inst, \ | 156 STR(inst), (FuncTypeUnsigned)(FuncTypeSigned)test##inst, \ |
180 (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::test##inst, isdiv \ | 157 (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::test##inst, isdiv \ |
181 } \ | 158 } \ |
182 , | 159 , |
183 SINTOP_TABLE | 160 SINTOP_TABLE |
184 #undef X | 161 #undef X |
185 }; | 162 }; |
186 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 163 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); |
187 const static size_t NumElementsInType = | 164 const static size_t NumElementsInType = Vectors<TypeUnsigned>::NumElements; |
188 sizeof(TypeUnsigned) / sizeof(ElementTypeUnsigned); | |
189 for (size_t f = 0; f < NumFuncs; ++f) { | 165 for (size_t f = 0; f < NumFuncs; ++f) { |
190 PRNG Index; | 166 PRNG Index; |
191 for (size_t i = 0; i < MaxTestsPerFunc; ++i) { | 167 for (size_t i = 0; i < MaxTestsPerFunc; ++i) { |
192 // Initialize the test vectors. | 168 // Initialize the test vectors. |
193 TypeUnsigned Value1, Value2; | 169 TypeUnsigned Value1, Value2; |
194 for (size_t j = 0; j < NumElementsInType;) { | 170 for (size_t j = 0; j < NumElementsInType;) { |
195 ElementTypeUnsigned Element1 = Values[Index() % NumElementsInType]; | 171 ElementTypeUnsigned Element1 = Values[Index() % NumElementsInType]; |
196 ElementTypeUnsigned Element2 = Values[Index() % NumElementsInType]; | 172 ElementTypeUnsigned Element2 = Values[Index() % NumElementsInType]; |
197 if (Funcs[f].ExcludeDivExceptions && | 173 if (Funcs[f].ExcludeDivExceptions && |
198 inputsMayTriggerException<ElementTypeSigned>(Element1, Element2)) | 174 inputsMayTriggerException<ElementTypeSigned>(Element1, Element2)) |
199 continue; | 175 continue; |
200 Value1[j] = Element1; | 176 Value1[j] = Element1; |
201 Value2[j] = Element2; | 177 Value2[j] = Element2; |
202 ++j; | 178 ++j; |
203 } | 179 } |
204 // Perform the test. | 180 // Perform the test. |
205 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 181 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); |
206 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 182 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); |
207 ++TotalTests; | 183 ++TotalTests; |
208 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { | 184 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { |
209 ++Passes; | 185 ++Passes; |
210 } else { | 186 } else { |
| 187 ++Failures; |
211 std::cout << "test" << Funcs[f].Name << "v" << NumElementsInType << "i" | 188 std::cout << "test" << Funcs[f].Name << "v" << NumElementsInType << "i" |
212 << (CHAR_BIT * sizeof(ElementTypeUnsigned)) << "("; | 189 << (CHAR_BIT * sizeof(ElementTypeUnsigned)) << "(" |
213 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(Value1); | 190 << vectAsString<TypeUnsignedLabel>(Value1) << "," |
214 std::cout << ", "; | 191 << vectAsString<TypeUnsignedLabel>(Value2) |
215 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(Value2); | 192 << "): sz=" << vectAsString<TypeUnsignedLabel>(ResultSz) |
216 std::cout << "): sz="; | 193 << " llc=" << vectAsString<TypeUnsignedLabel>(ResultLlc) |
217 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(ResultSz); | 194 << std::endl; |
218 std::cout << " llc="; | |
219 outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(ResultLlc); | |
220 std::cout << std::endl; | |
221 } | 195 } |
222 } | 196 } |
223 } | 197 } |
224 } | 198 } |
225 | 199 |
226 template <typename Type> | 200 template <typename Type> |
227 void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 201 void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { |
228 static const Type NegInf = -1.0 / 0.0; | 202 static const Type NegInf = -1.0 / 0.0; |
229 static const Type PosInf = 1.0 / 0.0; | 203 static const Type PosInf = 1.0 / 0.0; |
230 static const Type Nan = 0.0 / 0.0; | 204 static const Type Nan = 0.0 / 0.0; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 Value2[j] = Values[Index() % NumElementsInType]; | 288 Value2[j] = Values[Index() % NumElementsInType]; |
315 } | 289 } |
316 // Perform the test. | 290 // Perform the test. |
317 v4f32 ResultSz = Funcs[f].FuncSz(Value1, Value2); | 291 v4f32 ResultSz = Funcs[f].FuncSz(Value1, Value2); |
318 v4f32 ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 292 v4f32 ResultLlc = Funcs[f].FuncLlc(Value1, Value2); |
319 ++TotalTests; | 293 ++TotalTests; |
320 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { | 294 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { |
321 ++Passes; | 295 ++Passes; |
322 } else { | 296 } else { |
323 ++Failures; | 297 ++Failures; |
324 std::cout << std::fixed << "test" << Funcs[f].Name << "v4f32" | 298 std::cout << "test" << Funcs[f].Name << "v4f32" |
325 << "("; | 299 << "(" << vectAsString<v4f32>(Value1) << "," |
326 outputVector<v4f32, float, float>(Value1); | 300 << vectAsString<v4f32>(Value2) |
327 std::cout << ", "; | 301 << "): sz=" << vectAsString<v4f32>(ResultSz) << " llc" |
328 outputVector<v4f32, float, float>(Value2); | 302 << vectAsString<v4f32>(ResultLlc) << std::endl; |
329 std::cout << "): sz="; | |
330 outputVector<v4f32, float, float>(ResultSz); | |
331 std::cout << " llc="; | |
332 outputVector<v4f32, float, float>(ResultLlc); | |
333 std::cout << std::endl; | |
334 } | 303 } |
335 } | 304 } |
336 } | 305 } |
337 } | 306 } |
338 | 307 |
339 int main(int argc, char **argv) { | 308 int main(int argc, char **argv) { |
340 size_t TotalTests = 0; | 309 size_t TotalTests = 0; |
341 size_t Passes = 0; | 310 size_t Passes = 0; |
342 size_t Failures = 0; | 311 size_t Failures = 0; |
343 | 312 |
344 testsInt<uint8_t, int8_t>(TotalTests, Passes, Failures); | 313 testsInt<uint8_t, int8_t>(TotalTests, Passes, Failures); |
345 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures); | 314 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures); |
346 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures); | 315 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures); |
347 testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures); | 316 testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures); |
348 testsVecInt<v4ui32, v4si32, uint32_t, int32_t>(TotalTests, Passes, Failures); | 317 testsVecInt<v4ui32, v4si32>(TotalTests, Passes, Failures); |
349 testsVecInt<v8ui16, v8si16, uint16_t, int16_t>(TotalTests, Passes, Failures); | 318 testsVecInt<v8ui16, v8si16>(TotalTests, Passes, Failures); |
350 testsVecInt<v16ui8, v16si8, uint8_t, int8_t>(TotalTests, Passes, Failures); | 319 testsVecInt<v16ui8, v16si8>(TotalTests, Passes, Failures); |
351 testsFp<float>(TotalTests, Passes, Failures); | 320 testsFp<float>(TotalTests, Passes, Failures); |
352 testsFp<double>(TotalTests, Passes, Failures); | 321 testsFp<double>(TotalTests, Passes, Failures); |
353 testsVecFp(TotalTests, Passes, Failures); | 322 testsVecFp(TotalTests, Passes, Failures); |
354 | 323 |
355 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes | 324 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes |
356 << " Failures=" << Failures << "\n"; | 325 << " Failures=" << Failures << "\n"; |
357 return Failures; | 326 return Failures; |
358 } | 327 } |
359 | 328 |
360 extern "C" { | 329 extern "C" { |
(...skipping 23 matching lines...) Expand all Loading... |
384 v16si8 Sz_srem_v16i8(v16si8 a, v16si8 b) { return a % b; } | 353 v16si8 Sz_srem_v16i8(v16si8 a, v16si8 b) { return a % b; } |
385 v16ui8 Sz_urem_v16i8(v16ui8 a, v16ui8 b) { return a % b; } | 354 v16ui8 Sz_urem_v16i8(v16ui8 a, v16ui8 b) { return a % b; } |
386 | 355 |
387 v4f32 Sz_frem_v4f32(v4f32 a, v4f32 b) { | 356 v4f32 Sz_frem_v4f32(v4f32 a, v4f32 b) { |
388 v4f32 Result; | 357 v4f32 Result; |
389 for (int i = 0; i < 4; ++i) | 358 for (int i = 0; i < 4; ++i) |
390 Result[i] = fmodf(a[i], b[i]); | 359 Result[i] = fmodf(a[i], b[i]); |
391 return Result; | 360 return Result; |
392 } | 361 } |
393 } | 362 } |
OLD | NEW |