blob: 84bc6b72ebd6827d4df56e5cf4164e5f2791de4b [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[] = {
Matt Walaafeaee42014-08-07 13:47:30 -070064#define X(inst, op, isdiv, isshift) \
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
Matt Walaafeaee42014-08-07 13:47:30 -070069#define X(inst, op, isdiv, isshift) \
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
Matt Walaafeaee42014-08-07 13:47:30 -0700175 bool MaskShiftOperations; // for shift related tests
Matt Wala7fa22d82014-07-17 12:41:31 -0700176 } Funcs[] = {
Matt Walaafeaee42014-08-07 13:47:30 -0700177#define X(inst, op, isdiv, isshift) \
Matt Wala7fa22d82014-07-17 12:41:31 -0700178 { \
Matt Walaafeaee42014-08-07 13:47:30 -0700179 STR(inst), test##inst, Subzero_::test##inst, NULL, NULL, isdiv, isshift \
Matt Wala7fa22d82014-07-17 12:41:31 -0700180 } \
181 ,
182 UINTOP_TABLE
183#undef X
Matt Walaafeaee42014-08-07 13:47:30 -0700184#define X(inst, op, isdiv, isshift) \
Matt Wala7fa22d82014-07-17 12:41:31 -0700185 { \
Matt Walaafeaee42014-08-07 13:47:30 -0700186 STR(inst), NULL, NULL, test##inst, Subzero_::test##inst, isdiv, isshift \
Matt Wala7fa22d82014-07-17 12:41:31 -0700187 } \
188 ,
189 SINTOP_TABLE
190#undef X
191 };
192 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
Matt Wala89a7c2b2014-07-22 10:55:30 -0700193 const static size_t NumElementsInType = Vectors<TypeUnsigned>::NumElements;
Matt Wala7fa22d82014-07-17 12:41:31 -0700194 for (size_t f = 0; f < NumFuncs; ++f) {
195 PRNG Index;
196 for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
197 // Initialize the test vectors.
198 TypeUnsigned Value1, Value2;
199 for (size_t j = 0; j < NumElementsInType;) {
Matt Wala35ec3732014-07-18 16:32:16 -0700200 ElementTypeUnsigned Element1 = Values[Index() % NumValues];
201 ElementTypeUnsigned Element2 = Values[Index() % NumValues];
Matt Wala7fa22d82014-07-17 12:41:31 -0700202 if (Funcs[f].ExcludeDivExceptions &&
203 inputsMayTriggerException<ElementTypeSigned>(Element1, Element2))
204 continue;
Matt Walaafeaee42014-08-07 13:47:30 -0700205 if (Funcs[f].MaskShiftOperations)
206 Element2 &= CHAR_BIT * sizeof(ElementTypeUnsigned) - 1;
Matt Wala7fa22d82014-07-17 12:41:31 -0700207 Value1[j] = Element1;
208 Value2[j] = Element2;
209 ++j;
210 }
211 // Perform the test.
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700212 TypeUnsigned ResultSz, ResultLlc;
Matt Wala7fa22d82014-07-17 12:41:31 -0700213 ++TotalTests;
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700214 if (Funcs[f].FuncSzUnsigned) {
215 ResultSz = Funcs[f].FuncSzUnsigned(Value1, Value2);
216 ResultLlc = Funcs[f].FuncLlcUnsigned(Value1, Value2);
217 } else {
218 ResultSz = Funcs[f].FuncSzSigned(Value1, Value2);
219 ResultLlc = Funcs[f].FuncLlcSigned(Value1, Value2);
220 }
Matt Wala7fa22d82014-07-17 12:41:31 -0700221 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
222 ++Passes;
223 } else {
Matt Wala89a7c2b2014-07-22 10:55:30 -0700224 ++Failures;
Matt Wala7fa22d82014-07-17 12:41:31 -0700225 std::cout << "test" << Funcs[f].Name << "v" << NumElementsInType << "i"
Matt Wala89a7c2b2014-07-22 10:55:30 -0700226 << (CHAR_BIT * sizeof(ElementTypeUnsigned)) << "("
227 << vectAsString<TypeUnsignedLabel>(Value1) << ","
228 << vectAsString<TypeUnsignedLabel>(Value2)
229 << "): sz=" << vectAsString<TypeUnsignedLabel>(ResultSz)
230 << " llc=" << vectAsString<TypeUnsignedLabel>(ResultLlc)
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700231 << "\n";
Matt Wala7fa22d82014-07-17 12:41:31 -0700232 }
233 }
234 }
235}
236
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700237template <typename Type>
238void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
239 static const Type NegInf = -1.0 / 0.0;
240 static const Type PosInf = 1.0 / 0.0;
241 static const Type Nan = 0.0 / 0.0;
Jan Voungf37fbbe2014-07-09 16:13:13 -0700242 static const Type NegNan = -0.0 / 0.0;
Matt Wala7fa22d82014-07-17 12:41:31 -0700243 volatile Type Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700244 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
245 typedef Type (*FuncType)(Type, Type);
246 static struct {
247 const char *Name;
248 FuncType FuncLlc;
249 FuncType FuncSz;
250 } Funcs[] = {
251#define X(inst, op, func) \
252 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \
253 ,
254 FPOP_TABLE
255#undef X
Matt Wala7fa22d82014-07-17 12:41:31 -0700256 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700257 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
258
259 for (size_t f = 0; f < NumFuncs; ++f) {
260 for (size_t i = 0; i < NumValues; ++i) {
261 for (size_t j = 0; j < NumValues; ++j) {
262 Type Value1 = Values[i];
263 Type Value2 = Values[j];
264 ++TotalTests;
265 Type ResultSz = Funcs[f].FuncSz(Value1, Value2);
266 Type ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
267 // Compare results using memcmp() in case they are both NaN.
268 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) {
269 ++Passes;
270 } else {
271 ++Failures;
272 std::cout << std::fixed << "test" << Funcs[f].Name
Matt Wala7fa22d82014-07-17 12:41:31 -0700273 << (CHAR_BIT * sizeof(Type)) << "(" << Value1 << ", "
274 << Value2 << "): sz=" << ResultSz << " llc=" << ResultLlc
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700275 << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700276 }
277 }
278 }
279 }
Jan Voungf37fbbe2014-07-09 16:13:13 -0700280 for (size_t i = 0; i < NumValues; ++i) {
281 Type Value = Values[i];
282 ++TotalTests;
283 Type ResultSz = Subzero_::mySqrt(Value);
284 Type ResultLlc = mySqrt(Value);
285 // Compare results using memcmp() in case they are both NaN.
286 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) {
287 ++Passes;
288 } else {
289 ++Failures;
Matt Wala7fa22d82014-07-17 12:41:31 -0700290 std::cout << std::fixed << "test_sqrt" << (CHAR_BIT * sizeof(Type)) << "("
291 << Value << "): sz=" << ResultSz << " llc=" << ResultLlc
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700292 << "\n";
Jan Voungf37fbbe2014-07-09 16:13:13 -0700293 }
294 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700295}
296
Matt Wala7fa22d82014-07-17 12:41:31 -0700297void testsVecFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
298 static const float NegInf = -1.0 / 0.0;
299 static const float PosInf = 1.0 / 0.0;
300 static const float Nan = 0.0 / 0.0;
301 static const float NegNan = -0.0 / 0.0;
302 volatile float Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan);
303 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
304 typedef v4f32 (*FuncType)(v4f32, v4f32);
305 static struct {
306 const char *Name;
307 FuncType FuncLlc;
308 FuncType FuncSz;
309 } Funcs[] = {
310#define X(inst, op, func) \
311 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \
312 ,
313 FPOP_TABLE
314#undef X
315 };
316 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
317 const static size_t NumElementsInType = 4;
318 for (size_t f = 0; f < NumFuncs; ++f) {
319 PRNG Index;
320 for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
321 // Initialize the test vectors.
322 v4f32 Value1, Value2;
323 for (size_t j = 0; j < NumElementsInType; ++j) {
Matt Wala35ec3732014-07-18 16:32:16 -0700324 Value1[j] = Values[Index() % NumValues];
325 Value2[j] = Values[Index() % NumValues];
Matt Wala7fa22d82014-07-17 12:41:31 -0700326 }
327 // Perform the test.
328 v4f32 ResultSz = Funcs[f].FuncSz(Value1, Value2);
329 v4f32 ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
330 ++TotalTests;
331 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
332 ++Passes;
333 } else {
334 ++Failures;
Matt Wala89a7c2b2014-07-22 10:55:30 -0700335 std::cout << "test" << Funcs[f].Name << "v4f32"
336 << "(" << vectAsString<v4f32>(Value1) << ","
337 << vectAsString<v4f32>(Value2)
338 << "): sz=" << vectAsString<v4f32>(ResultSz) << " llc"
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700339 << vectAsString<v4f32>(ResultLlc) << "\n";
Matt Wala7fa22d82014-07-17 12:41:31 -0700340 }
341 }
342 }
343}
344
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700345int main(int argc, char **argv) {
346 size_t TotalTests = 0;
347 size_t Passes = 0;
348 size_t Failures = 0;
349
Jim Stichnoth7da431b2014-08-05 11:22:37 -0700350 testsInt<uint8_t, myint8_t>(TotalTests, Passes, Failures);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700351 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures);
352 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures);
353 testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures);
Matt Wala89a7c2b2014-07-22 10:55:30 -0700354 testsVecInt<v4ui32, v4si32>(TotalTests, Passes, Failures);
355 testsVecInt<v8ui16, v8si16>(TotalTests, Passes, Failures);
356 testsVecInt<v16ui8, v16si8>(TotalTests, Passes, Failures);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700357 testsFp<float>(TotalTests, Passes, Failures);
358 testsFp<double>(TotalTests, Passes, Failures);
Matt Wala7fa22d82014-07-17 12:41:31 -0700359 testsVecFp(TotalTests, Passes, Failures);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700360
361 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
362 << " Failures=" << Failures << "\n";
363 return Failures;
364}
Matt Wala7fa22d82014-07-17 12:41:31 -0700365