1 //===- subzero/crosstest/test_icmp_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 cross testing the icmp bitcode instruction
11 //
12 //===----------------------------------------------------------------------===//
13
14 /* crosstest.py --test=test_icmp.cpp --test=test_icmp_i1vec.ll \
15 --driver=test_icmp_main.cpp --prefix=Subzero_ --output=test_icmp */
16
17 #include <climits> // CHAR_BIT
18 #include <cstring> // memcmp, memset
19 #include <iostream>
20 #include <stdint.h>
21
22 // Include test_icmp.h twice - once normally, and once within the
23 // Subzero_ namespace, corresponding to the llc and Subzero translated
24 // object files, respectively.
25 #include "test_icmp.h"
26
27 namespace Subzero_ {
28 #include "test_icmp.h"
29 }
30
31 #include "insertelement.h"
32 #include "xdefs.h"
33
34 volatile unsigned Values[] = {
35 0x0, 0x1, 0x7ffffffe, 0x7fffffff, 0x80000000, 0x80000001,
36 0xfffffffe, 0xffffffff, 0x7e, 0x7f, 0x80, 0x81,
37 0xfe, 0xff, 0x100, 0x101, 0x7ffe, 0x7fff,
38 0x8000, 0x8001, 0xfffe, 0xffff, 0x10000, 0x10001,
39 };
40 const static size_t NumValues = sizeof(Values) / sizeof(*Values);
41
42 template <typename TypeUnsigned, typename TypeSigned>
testsInt(size_t & TotalTests,size_t & Passes,size_t & Failures)43 void testsInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
44 typedef bool (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned);
45 typedef bool (*FuncTypeSigned)(TypeSigned, TypeSigned);
46 static struct {
47 const char *Name;
48 FuncTypeUnsigned FuncLlc;
49 FuncTypeUnsigned FuncSz;
50 } Funcs[] = {
51 #define X(cmp, op) \
52 {STR(cmp), (FuncTypeUnsigned)icmp##cmp, \
53 (FuncTypeUnsigned)Subzero_::icmp##cmp},
54 ICMP_U_TABLE
55 #undef X
56 #define X(cmp, op) \
57 {STR(cmp), (FuncTypeUnsigned)(FuncTypeSigned)icmp##cmp, \
58 (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::icmp##cmp},
59 ICMP_S_TABLE
60 #undef X
61 };
62 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
63
64 if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) {
65 // This is the "normal" version of the loop nest, for 32-bit or
66 // narrower types.
67 for (size_t f = 0; f < NumFuncs; ++f) {
68 for (size_t i = 0; i < NumValues; ++i) {
69 for (size_t j = 0; j < NumValues; ++j) {
70 TypeUnsigned Value1 = Values[i];
71 TypeUnsigned Value2 = Values[j];
72 ++TotalTests;
73 bool ResultSz = Funcs[f].FuncSz(Value1, Value2);
74 bool ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
75 if (ResultSz == ResultLlc) {
76 ++Passes;
77 } else {
78 ++Failures;
79 std::cout << "icmp" << Funcs[f].Name
80 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1
81 << ", " << Value2 << "): sz=" << ResultSz
82 << " llc=" << ResultLlc << "\n";
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 ++TotalTests;
100 bool ResultSz = Funcs[f].FuncSz(Value1, Value2);
101 bool ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
102 if (ResultSz == ResultLlc) {
103 ++Passes;
104 } else {
105 ++Failures;
106 std::cout << "icmp" << Funcs[f].Name
107 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1
108 << ", " << Value2 << "): sz=" << ResultSz
109 << " llc=" << ResultLlc << "\n";
110 }
111 }
112 }
113 }
114 }
115 }
116 }
117 }
118
119 template <typename TypeUnsigned, typename TypeSigned>
testsIntWithZero(size_t & TotalTests,size_t & Passes,size_t & Failures)120 void testsIntWithZero(size_t &TotalTests, size_t &Passes, size_t &Failures) {
121 typedef bool (*FuncTypeUnsigned)(TypeUnsigned);
122 typedef bool (*FuncTypeSigned)(TypeSigned);
123 static struct {
124 const char *Name;
125 FuncTypeUnsigned FuncLlc;
126 FuncTypeUnsigned FuncSz;
127 } Funcs[] = {
128 #define X(cmp, op) \
129 {STR(cmp), (FuncTypeUnsigned)icmp_zero##cmp, \
130 (FuncTypeUnsigned)Subzero_::icmp_zero##cmp},
131 ICMP_U_TABLE
132 #undef X
133 #define X(cmp, op) \
134 {STR(cmp), (FuncTypeUnsigned)(FuncTypeSigned)icmp_zero##cmp, \
135 (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::icmp_zero##cmp},
136 ICMP_S_TABLE
137 #undef X
138 };
139 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
140
141 if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) {
142 // This is the "normal" version of the loop nest, for 32-bit or
143 // narrower types.
144 for (size_t f = 0; f < NumFuncs; ++f) {
145 for (size_t i = 0; i < NumValues; ++i) {
146 TypeUnsigned Value = Values[i];
147 ++TotalTests;
148 bool ResultSz = Funcs[f].FuncSz(Value);
149 bool ResultLlc = Funcs[f].FuncLlc(Value);
150 if (ResultSz == ResultLlc) {
151 ++Passes;
152 } else {
153 ++Failures;
154 std::cout << "icmp" << Funcs[f].Name
155 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value
156 << "): sz=" << ResultSz << " llc=" << ResultLlc << "\n";
157 }
158 }
159 }
160 } else {
161 // This is the 64-bit version. Test values are synthesized from
162 // the 32-bit values in Values[].
163 for (size_t f = 0; f < NumFuncs; ++f) {
164 for (size_t iLo = 0; iLo < NumValues; ++iLo) {
165 for (size_t iHi = 0; iHi < NumValues; ++iHi) {
166 TypeUnsigned Value =
167 (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo];
168 ++TotalTests;
169 bool ResultSz = Funcs[f].FuncSz(Value);
170 bool ResultLlc = Funcs[f].FuncLlc(Value);
171 if (ResultSz == ResultLlc) {
172 ++Passes;
173 } else {
174 ++Failures;
175 std::cout << "icmp" << Funcs[f].Name
176 << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value
177 << "): sz=" << ResultSz << " llc=" << ResultLlc << "\n";
178 }
179 }
180 }
181 }
182 }
183 }
184
185 const static size_t MaxTestsPerFunc = 100000;
186
187 template <typename TypeUnsignedLabel, typename TypeSignedLabel>
testsVecInt(size_t & TotalTests,size_t & Passes,size_t & Failures)188 void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
189 typedef typename Vectors<TypeUnsignedLabel>::Ty TypeUnsigned;
190 typedef typename Vectors<TypeSignedLabel>::Ty TypeSigned;
191 typedef typename Vectors<TypeUnsignedLabel>::ElementTy ElementTypeUnsigned;
192 typedef typename Vectors<TypeSignedLabel>::ElementTy ElementTypeSigned;
193 typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned);
194 typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned);
195 static struct {
196 const char *Name;
197 FuncTypeUnsigned FuncLlc;
198 FuncTypeUnsigned FuncSz;
199 } Funcs[] = {
200 #define X(cmp, op) \
201 {STR(cmp), (FuncTypeUnsigned)icmp##cmp, \
202 (FuncTypeUnsigned)Subzero_::icmp##cmp},
203 ICMP_U_TABLE
204 #undef X
205 #define X(cmp, op) \
206 {STR(cmp), (FuncTypeUnsigned)(FuncTypeSigned)icmp##cmp, \
207 (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::icmp##cmp},
208 ICMP_S_TABLE
209 #undef X
210 };
211 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
212 const static size_t NumElementsInType = Vectors<TypeUnsigned>::NumElements;
213 for (size_t f = 0; f < NumFuncs; ++f) {
214 PRNG Index;
215 for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
216 // Initialize the test vectors.
217 TypeUnsigned Value1, Value2;
218 for (size_t j = 0; j < NumElementsInType; ++j) {
219 setElement(Value1, j, Values[Index() % NumValues]);
220 setElement(Value2, j, Values[Index() % NumValues]);
221 }
222 // Perform the test.
223 TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2);
224 TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
225 ++TotalTests;
226 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
227 ++Passes;
228 } else {
229 ++Failures;
230 std::cout << "test" << Funcs[f].Name
231 << Vectors<TypeUnsignedLabel>::TypeName << "("
232 << vectAsString<TypeUnsignedLabel>(Value1) << ","
233 << vectAsString<TypeUnsignedLabel>(Value2)
234 << "): sz=" << vectAsString<TypeUnsignedLabel>(ResultSz)
235 << " llc=" << vectAsString<TypeUnsignedLabel>(ResultLlc)
236 << "\n";
237 }
238 }
239 }
240 }
241
242 // Return true on wraparound
243 template <typename T>
244 bool __attribute__((noinline))
incrementI1Vector(typename Vectors<T>::Ty & Vect)245 incrementI1Vector(typename Vectors<T>::Ty &Vect) {
246 size_t Pos = 0;
247 const static size_t NumElements = Vectors<T>::NumElements;
248 for (Pos = 0; Pos < NumElements; ++Pos) {
249 if (Vect[Pos] == 0) {
250 Vect[Pos] = 1;
251 break;
252 }
253 Vect[Pos] = 0;
254 }
255 return (Pos == NumElements);
256 }
257
258 template <typename T>
testsVecI1(size_t & TotalTests,size_t & Passes,size_t & Failures)259 void testsVecI1(size_t &TotalTests, size_t &Passes, size_t &Failures) {
260 typedef typename Vectors<T>::Ty Ty;
261 typedef Ty (*FuncType)(Ty, Ty);
262 static struct {
263 const char *Name;
264 FuncType FuncLlc;
265 FuncType FuncSz;
266 } Funcs[] = {
267 #define X(cmp, op) \
268 {STR(cmp), (FuncType)icmpi1##cmp, (FuncType)Subzero_::icmpi1##cmp},
269 ICMP_U_TABLE ICMP_S_TABLE};
270 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
271 const static size_t NumElements = Vectors<T>::NumElements;
272 const static size_t MAX_NUMBER_OF_ELEMENTS_FOR_EXHAUSTIVE_TESTING = 8;
273
274 // Check if the type is small enough to try all possible input pairs.
275 if (NumElements <= MAX_NUMBER_OF_ELEMENTS_FOR_EXHAUSTIVE_TESTING) {
276 for (size_t f = 0; f < NumFuncs; ++f) {
277 Ty Value1, Value2;
278 memset(&Value1, 0, sizeof(Value1));
279 for (bool IsValue1Done = false; !IsValue1Done;
280 IsValue1Done = incrementI1Vector<T>(Value1)) {
281 memset(&Value2, 0, sizeof(Value2));
282 for (bool IsValue2Done = false; !IsValue2Done;
283 IsValue2Done = incrementI1Vector<T>(Value2)) {
284 Ty ResultSz = Funcs[f].FuncSz(Value1, Value2);
285 Ty ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
286 ++TotalTests;
287 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
288 ++Passes;
289 } else {
290 ++Failures;
291 std::cout << "test" << Funcs[f].Name << Vectors<T>::TypeName << "("
292 << vectAsString<T>(Value1) << ","
293 << vectAsString<T>(Value2)
294 << "): sz=" << vectAsString<T>(ResultSz)
295 << " llc=" << vectAsString<T>(ResultLlc) << "\n";
296 }
297 }
298 }
299 }
300 } else {
301 for (size_t f = 0; f < NumFuncs; ++f) {
302 PRNG Index;
303 for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
304 Ty Value1, Value2;
305 // Initialize the test vectors.
306 for (size_t j = 0; j < NumElements; ++j) {
307 setElement(Value1, j, Index() % 2);
308 setElement(Value2, j, Index() % 2);
309 }
310 // Perform the test.
311 Ty ResultSz = Funcs[f].FuncSz(Value1, Value2);
312 Ty ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
313 ++TotalTests;
314 if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
315 ++Passes;
316 } else {
317 ++Failures;
318 std::cout << "test" << Funcs[f].Name << Vectors<T>::TypeName << "("
319 << vectAsString<T>(Value1) << "," << vectAsString<T>(Value2)
320 << "): sz=" << vectAsString<T>(ResultSz)
321 << " llc=" << vectAsString<T>(ResultLlc) << "\n";
322 }
323 }
324 }
325 }
326 }
327
main(int argc,char * argv[])328 int main(int argc, char *argv[]) {
329 size_t TotalTests = 0;
330 size_t Passes = 0;
331 size_t Failures = 0;
332
333 testsInt<uint8_t, myint8_t>(TotalTests, Passes, Failures);
334 testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures);
335 testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures);
336 testsInt<uint64, int64>(TotalTests, Passes, Failures);
337 testsIntWithZero<uint8_t, myint8_t>(TotalTests, Passes, Failures);
338 testsIntWithZero<uint16_t, int16_t>(TotalTests, Passes, Failures);
339 testsIntWithZero<uint32_t, int32_t>(TotalTests, Passes, Failures);
340 testsIntWithZero<uint64, int64>(TotalTests, Passes, Failures);
341 testsVecInt<v4ui32, v4si32>(TotalTests, Passes, Failures);
342 testsVecInt<v8ui16, v8si16>(TotalTests, Passes, Failures);
343 testsVecInt<v16ui8, v16si8>(TotalTests, Passes, Failures);
344 testsVecI1<v4i1>(TotalTests, Passes, Failures);
345 testsVecI1<v8i1>(TotalTests, Passes, Failures);
346 testsVecI1<v16i1>(TotalTests, Passes, Failures);
347
348 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
349 << " Failures=" << Failures << "\n";
350 return Failures;
351 }
352