blob: 8c53ad5289023537261f77156019cffc51022f73 [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001/* crosstest.py --test=test_arith.cpp --test=test_arith_frem.ll \
Jan Voungf37fbbe2014-07-09 16:13:13 -07002 --test=test_arith_sqrt.ll --driver=test_arith_main.cpp \
3 --prefix=Subzero_ --output=test_arith */
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07004
5#include <stdint.h>
6
7#include <cfloat>
8#include <cstring> // memcmp
9#include <iostream>
10
11// Include test_arith.h twice - once normally, and once within the
12// Subzero_ namespace, corresponding to the llc and Subzero translated
13// object files, respectively.
14#include "test_arith.h"
15namespace Subzero_ {
16#include "test_arith.h"
17}
18
19volatile unsigned Values[] = { 0x0, 0x1, 0x7ffffffe, 0x7fffffff,
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, };
25const static size_t NumValues = sizeof(Values) / sizeof(*Values);
26
27template <typename TypeUnsigned, typename TypeSigned>
28void testsInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
29 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned);
30 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned);
31 static struct {
32 const char *Name;
33 FuncTypeUnsigned FuncLlc;
34 FuncTypeUnsigned FuncSz;
35 bool ExcludeDivExceptions; // for divide related tests
36 } Funcs[] = {
37#define X(inst, op, isdiv) \
38 { \
39 STR(inst), (FuncTypeUnsigned)test##inst, \
40 (FuncTypeUnsigned)Subzero_::test##inst, isdiv \
41 } \
42 ,
43 UINTOP_TABLE
44#undef X
45#define X(inst, op, isdiv) \
46 { \
47 STR(inst), (FuncTypeUnsigned)(FuncTypeSigned)test##inst, \
48 (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::test##inst, isdiv \
49 } \
50 ,
51 SINTOP_TABLE
52#undef X
53 };
54 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
55
56 if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) {
57 // This is the "normal" version of the loop nest, for 32-bit or
58 // narrower types.
59 for (size_t f = 0; f < NumFuncs; ++f) {
60 for (size_t i = 0; i < NumValues; ++i) {
61 for (size_t j = 0; j < NumValues; ++j) {
62 TypeUnsigned Value1 = Values[i];
63 TypeUnsigned Value2 = Values[j];
64 // Avoid HW divide-by-zero exception.
65 if (Funcs[f].ExcludeDivExceptions && Value2 == 0)
66 continue;
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;
72 ++TotalTests;
73 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2);
74 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
75 if (ResultSz == ResultLlc) {
76 ++Passes;
77 } else {
78 ++Failures;
79 std::cout << "test" << Funcs[f].Name << (8 * sizeof(TypeUnsigned))
80 << "(" << Value1 << ", " << Value2
81 << "): sz=" << (unsigned)ResultSz
82 << " llc=" << (unsigned)ResultLlc << std::endl;
83 }
84 }
85 }
86 }
87 } else {
88 // This is the 64-bit version. Test values are synthesized from
89 // the 32-bit values in Values[].
90 for (size_t f = 0; f < NumFuncs; ++f) {
91 for (size_t iLo = 0; iLo < NumValues; ++iLo) {
92 for (size_t iHi = 0; iHi < NumValues; ++iHi) {
93 for (size_t jLo = 0; jLo < NumValues; ++jLo) {
94 for (size_t jHi = 0; jHi < NumValues; ++jHi) {
95 TypeUnsigned Value1 =
96 (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo];
97 TypeUnsigned Value2 =
98 (((TypeUnsigned)Values[jHi]) << 32) + Values[jLo];
99 // Avoid HW divide-by-zero exception.
100 if (Funcs[f].ExcludeDivExceptions && Value2 == 0)
101 continue;
102 ++TotalTests;
103 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2);
104 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
105 if (ResultSz == ResultLlc) {
106 ++Passes;
107 } else {
108 ++Failures;
109 std::cout << "test" << Funcs[f].Name
110 << (8 * sizeof(TypeUnsigned)) << "(" << Value1 << ", "
111 << Value2 << "): sz=" << (unsigned)ResultSz
112 << " llc=" << (unsigned)ResultLlc << std::endl;
113 }
114 }
115 }
116 }
117 }
118 }
119 }
120}
121
122template <typename Type>
123void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
124 static const Type NegInf = -1.0 / 0.0;
125 static const Type PosInf = 1.0 / 0.0;
126 static const Type Nan = 0.0 / 0.0;
Jan Voungf37fbbe2014-07-09 16:13:13 -0700127 static const Type NegNan = -0.0 / 0.0;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700128 volatile Type Values[] = {
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,
Jan Voungf37fbbe2014-07-09 16:13:13 -0700139 Nan, NegNan, -0.0,
140 FLT_MIN, FLT_MAX,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700141 DBL_MIN, DBL_MAX
142 };
143 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
144 typedef Type (*FuncType)(Type, Type);
145 static struct {
146 const char *Name;
147 FuncType FuncLlc;
148 FuncType FuncSz;
149 } Funcs[] = {
150#define X(inst, op, func) \
151 { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst } \
152 ,
153 FPOP_TABLE
154#undef X
155 };
156 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
157
158 for (size_t f = 0; f < NumFuncs; ++f) {
159 for (size_t i = 0; i < NumValues; ++i) {
160 for (size_t j = 0; j < NumValues; ++j) {
161 Type Value1 = Values[i];
162 Type Value2 = Values[j];
163 ++TotalTests;
164 Type ResultSz = Funcs[f].FuncSz(Value1, Value2);
165 Type ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
166 // Compare results using memcmp() in case they are both NaN.
167 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) {
168 ++Passes;
169 } else {
170 ++Failures;
171 std::cout << std::fixed << "test" << Funcs[f].Name
172 << (8 * sizeof(Type)) << "(" << Value1 << ", " << Value2
173 << "): sz=" << ResultSz << " llc=" << ResultLlc
174 << std::endl;
175 }
176 }
177 }
178 }
Jan Voungf37fbbe2014-07-09 16:13:13 -0700179 for (size_t i = 0; i < NumValues; ++i) {
180 Type Value = Values[i];
181 ++TotalTests;
182 Type ResultSz = Subzero_::mySqrt(Value);
183 Type ResultLlc = mySqrt(Value);
184 // Compare results using memcmp() in case they are both NaN.
185 if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) {
186 ++Passes;
187 } else {
188 ++Failures;
189 std::cout << std::fixed << "test_sqrt"
190 << (8 * sizeof(Type)) << "(" << Value
191 << "): sz=" << ResultSz << " llc=" << ResultLlc
192 << std::endl;
193 }
194 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700195}
196
197int main(int argc, char **argv) {
198 size_t TotalTests = 0;
199 size_t Passes = 0;
200 size_t Failures = 0;
201
202 testsInt<uint8_t, int8_t>(TotalTests, Passes, Failures);
203 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures);
204 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures);
205 testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures);
206 testsFp<float>(TotalTests, Passes, Failures);
207 testsFp<double>(TotalTests, Passes, Failures);
208
209 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
210 << " Failures=" << Failures << "\n";
211 return Failures;
212}