• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdint.h>
20 #include <iostream>
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   {                                                                            \
53     STR(cmp), (FuncTypeUnsigned)icmp##cmp,                                     \
54         (FuncTypeUnsigned)Subzero_::icmp##cmp                                  \
55   }                                                                            \
56   ,
57       ICMP_U_TABLE
58 #undef X
59 #define X(cmp, op)                                                             \
60   {                                                                            \
61     STR(cmp), (FuncTypeUnsigned)(FuncTypeSigned)icmp##cmp,                     \
62         (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::icmp##cmp                  \
63   }                                                                            \
64   ,
65           ICMP_S_TABLE
66 #undef X
67   };
68   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
69 
70   if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) {
71     // This is the "normal" version of the loop nest, for 32-bit or
72     // narrower types.
73     for (size_t f = 0; f < NumFuncs; ++f) {
74       for (size_t i = 0; i < NumValues; ++i) {
75         for (size_t j = 0; j < NumValues; ++j) {
76           TypeUnsigned Value1 = Values[i];
77           TypeUnsigned Value2 = Values[j];
78           ++TotalTests;
79           bool ResultSz = Funcs[f].FuncSz(Value1, Value2);
80           bool ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
81           if (ResultSz == ResultLlc) {
82             ++Passes;
83           } else {
84             ++Failures;
85             std::cout << "icmp" << Funcs[f].Name
86                       << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1
87                       << ", " << Value2 << "): sz=" << ResultSz
88                       << " llc=" << ResultLlc << "\n";
89           }
90         }
91       }
92     }
93   } else {
94     // This is the 64-bit version.  Test values are synthesized from
95     // the 32-bit values in Values[].
96     for (size_t f = 0; f < NumFuncs; ++f) {
97       for (size_t iLo = 0; iLo < NumValues; ++iLo) {
98         for (size_t iHi = 0; iHi < NumValues; ++iHi) {
99           for (size_t jLo = 0; jLo < NumValues; ++jLo) {
100             for (size_t jHi = 0; jHi < NumValues; ++jHi) {
101               TypeUnsigned Value1 =
102                   (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo];
103               TypeUnsigned Value2 =
104                   (((TypeUnsigned)Values[jHi]) << 32) + Values[jLo];
105               ++TotalTests;
106               bool ResultSz = Funcs[f].FuncSz(Value1, Value2);
107               bool ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
108               if (ResultSz == ResultLlc) {
109                 ++Passes;
110               } else {
111                 ++Failures;
112                 std::cout << "icmp" << Funcs[f].Name
113                           << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1
114                           << ", " << Value2 << "): sz=" << ResultSz
115                           << " llc=" << ResultLlc << "\n";
116               }
117             }
118           }
119         }
120       }
121     }
122   }
123 }
124 
125 template <typename TypeUnsigned, typename TypeSigned>
testsIntWithZero(size_t & TotalTests,size_t & Passes,size_t & Failures)126 void testsIntWithZero(size_t &TotalTests, size_t &Passes, size_t &Failures) {
127   typedef bool (*FuncTypeUnsigned)(TypeUnsigned);
128   typedef bool (*FuncTypeSigned)(TypeSigned);
129   static struct {
130     const char *Name;
131     FuncTypeUnsigned FuncLlc;
132     FuncTypeUnsigned FuncSz;
133   } Funcs[] = {
134 #define X(cmp, op)                                                             \
135   {                                                                            \
136     STR(cmp), (FuncTypeUnsigned)icmp_zero##cmp,                                \
137         (FuncTypeUnsigned)Subzero_::icmp_zero##cmp                             \
138   }                                                                            \
139   ,
140       ICMP_U_TABLE
141 #undef X
142 #define X(cmp, op)                                                             \
143   {                                                                            \
144     STR(cmp), (FuncTypeUnsigned)(FuncTypeSigned)icmp_zero##cmp,                \
145         (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::icmp_zero##cmp             \
146   }                                                                            \
147   ,
148           ICMP_S_TABLE
149 #undef X
150   };
151   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
152 
153   if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) {
154     // This is the "normal" version of the loop nest, for 32-bit or
155     // narrower types.
156     for (size_t f = 0; f < NumFuncs; ++f) {
157       for (size_t i = 0; i < NumValues; ++i) {
158         TypeUnsigned Value = Values[i];
159         ++TotalTests;
160         bool ResultSz = Funcs[f].FuncSz(Value);
161         bool ResultLlc = Funcs[f].FuncLlc(Value);
162         if (ResultSz == ResultLlc) {
163           ++Passes;
164         } else {
165           ++Failures;
166           std::cout << "icmp" << Funcs[f].Name
167                     << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value
168                     << "): sz=" << ResultSz << " llc=" << ResultLlc << "\n";
169         }
170       }
171     }
172   } else {
173     // This is the 64-bit version.  Test values are synthesized from
174     // the 32-bit values in Values[].
175     for (size_t f = 0; f < NumFuncs; ++f) {
176       for (size_t iLo = 0; iLo < NumValues; ++iLo) {
177         for (size_t iHi = 0; iHi < NumValues; ++iHi) {
178           TypeUnsigned Value =
179               (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo];
180           ++TotalTests;
181           bool ResultSz = Funcs[f].FuncSz(Value);
182           bool ResultLlc = Funcs[f].FuncLlc(Value);
183           if (ResultSz == ResultLlc) {
184             ++Passes;
185           } else {
186             ++Failures;
187             std::cout << "icmp" << Funcs[f].Name
188                       << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value
189                       << "): sz=" << ResultSz << " llc=" << ResultLlc << "\n";
190           }
191         }
192       }
193     }
194   }
195 }
196 
197 const static size_t MaxTestsPerFunc = 100000;
198 
199 template <typename TypeUnsignedLabel, typename TypeSignedLabel>
testsVecInt(size_t & TotalTests,size_t & Passes,size_t & Failures)200 void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
201   typedef typename Vectors<TypeUnsignedLabel>::Ty TypeUnsigned;
202   typedef typename Vectors<TypeSignedLabel>::Ty TypeSigned;
203   typedef typename Vectors<TypeUnsignedLabel>::ElementTy ElementTypeUnsigned;
204   typedef typename Vectors<TypeSignedLabel>::ElementTy ElementTypeSigned;
205   typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned);
206   typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned);
207   static struct {
208     const char *Name;
209     FuncTypeUnsigned FuncLlc;
210     FuncTypeUnsigned FuncSz;
211   } Funcs[] = {
212 #define X(cmp, op)                                                             \
213   {                                                                            \
214     STR(cmp), (FuncTypeUnsigned)icmp##cmp,                                     \
215         (FuncTypeUnsigned)Subzero_::icmp##cmp                                  \
216   }                                                                            \
217   ,
218       ICMP_U_TABLE
219 #undef X
220 #define X(cmp, op)                                                             \
221   {                                                                            \
222     STR(cmp), (FuncTypeUnsigned)(FuncTypeSigned)icmp##cmp,                     \
223         (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::icmp##cmp                  \
224   }                                                                            \
225   ,
226           ICMP_S_TABLE
227 #undef X
228   };
229   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
230   const static size_t NumElementsInType = Vectors<TypeUnsigned>::NumElements;
231   for (size_t f = 0; f < NumFuncs; ++f) {
232     PRNG Index;
233     for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
234       // Initialize the test vectors.
235       TypeUnsigned Value1, Value2;
236       for (size_t j = 0; j < NumElementsInType; ++j) {
237         setElement(Value1, j, Values[Index() % NumValues]);
238         setElement(Value2, j, Values[Index() % NumValues]);
239       }
240       // Perform the test.
241       TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2);
242       TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
243       ++TotalTests;
244       if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
245         ++Passes;
246       } else {
247         ++Failures;
248         std::cout << "test" << Funcs[f].Name
249                   << Vectors<TypeUnsignedLabel>::TypeName << "("
250                   << vectAsString<TypeUnsignedLabel>(Value1) << ","
251                   << vectAsString<TypeUnsignedLabel>(Value2)
252                   << "): sz=" << vectAsString<TypeUnsignedLabel>(ResultSz)
253                   << " llc=" << vectAsString<TypeUnsignedLabel>(ResultLlc)
254                   << "\n";
255       }
256     }
257   }
258 }
259 
260 // Return true on wraparound
261 template <typename T>
262 bool __attribute__((noinline))
incrementI1Vector(typename Vectors<T>::Ty & Vect)263 incrementI1Vector(typename Vectors<T>::Ty &Vect) {
264   size_t Pos = 0;
265   const static size_t NumElements = Vectors<T>::NumElements;
266   for (Pos = 0; Pos < NumElements; ++Pos) {
267     if (Vect[Pos] == 0) {
268       Vect[Pos] = 1;
269       break;
270     }
271     Vect[Pos] = 0;
272   }
273   return (Pos == NumElements);
274 }
275 
276 template <typename T>
testsVecI1(size_t & TotalTests,size_t & Passes,size_t & Failures)277 void testsVecI1(size_t &TotalTests, size_t &Passes, size_t &Failures) {
278   typedef typename Vectors<T>::Ty Ty;
279   typedef Ty (*FuncType)(Ty, Ty);
280   static struct {
281     const char *Name;
282     FuncType FuncLlc;
283     FuncType FuncSz;
284   } Funcs[] = {
285 #define X(cmp, op)                                                             \
286   { STR(cmp), (FuncType)icmpi1##cmp, (FuncType)Subzero_::icmpi1##cmp }         \
287   ,
288       ICMP_U_TABLE ICMP_S_TABLE};
289   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
290   const static size_t NumElements = Vectors<T>::NumElements;
291   const static size_t MAX_NUMBER_OF_ELEMENTS_FOR_EXHAUSTIVE_TESTING = 8;
292 
293   // Check if the type is small enough to try all possible input pairs.
294   if (NumElements <= MAX_NUMBER_OF_ELEMENTS_FOR_EXHAUSTIVE_TESTING) {
295     for (size_t f = 0; f < NumFuncs; ++f) {
296       Ty Value1, Value2;
297       memset(&Value1, 0, sizeof(Value1));
298       for (bool IsValue1Done = false; !IsValue1Done;
299            IsValue1Done = incrementI1Vector<T>(Value1)) {
300         memset(&Value2, 0, sizeof(Value2));
301         for (bool IsValue2Done = false; !IsValue2Done;
302              IsValue2Done = incrementI1Vector<T>(Value2)) {
303           Ty ResultSz = Funcs[f].FuncSz(Value1, Value2);
304           Ty ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
305           ++TotalTests;
306           if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
307             ++Passes;
308           } else {
309             ++Failures;
310             std::cout << "test" << Funcs[f].Name << Vectors<T>::TypeName << "("
311                       << vectAsString<T>(Value1) << ","
312                       << vectAsString<T>(Value2)
313                       << "): sz=" << vectAsString<T>(ResultSz)
314                       << " llc=" << vectAsString<T>(ResultLlc) << "\n";
315           }
316         }
317       }
318     }
319   } else {
320     for (size_t f = 0; f < NumFuncs; ++f) {
321       PRNG Index;
322       for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
323         Ty Value1, Value2;
324         // Initialize the test vectors.
325         for (size_t j = 0; j < NumElements; ++j) {
326           setElement(Value1, j, Index() % 2);
327           setElement(Value2, j, Index() % 2);
328         }
329         // Perform the test.
330         Ty ResultSz = Funcs[f].FuncSz(Value1, Value2);
331         Ty ResultLlc = Funcs[f].FuncLlc(Value1, Value2);
332         ++TotalTests;
333         if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
334           ++Passes;
335         } else {
336           ++Failures;
337           std::cout << "test" << Funcs[f].Name << Vectors<T>::TypeName << "("
338                     << vectAsString<T>(Value1) << "," << vectAsString<T>(Value2)
339                     << "): sz=" << vectAsString<T>(ResultSz)
340                     << " llc=" << vectAsString<T>(ResultLlc) << "\n";
341         }
342       }
343     }
344   }
345 }
346 
main(int argc,char * argv[])347 int main(int argc, char *argv[]) {
348   size_t TotalTests = 0;
349   size_t Passes = 0;
350   size_t Failures = 0;
351 
352   testsInt<uint8_t, myint8_t>(TotalTests, Passes, Failures);
353   testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures);
354   testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures);
355   testsInt<uint64, int64>(TotalTests, Passes, Failures);
356   testsIntWithZero<uint8_t, myint8_t>(TotalTests, Passes, Failures);
357   testsIntWithZero<uint16_t, int16_t>(TotalTests, Passes, Failures);
358   testsIntWithZero<uint32_t, int32_t>(TotalTests, Passes, Failures);
359   testsIntWithZero<uint64, int64>(TotalTests, Passes, Failures);
360   testsVecInt<v4ui32, v4si32>(TotalTests, Passes, Failures);
361   testsVecInt<v8ui16, v8si16>(TotalTests, Passes, Failures);
362   testsVecInt<v16ui8, v16si8>(TotalTests, Passes, Failures);
363   testsVecI1<v4i1>(TotalTests, Passes, Failures);
364   testsVecI1<v8i1>(TotalTests, Passes, Failures);
365   testsVecI1<v16i1>(TotalTests, Passes, Failures);
366 
367   std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
368             << " Failures=" << Failures << "\n";
369   return Failures;
370 }
371