xref: /aosp_15_r20/external/swiftshader/third_party/subzero/crosstest/test_icmp_main.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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