Home | History | Annotate | Download | only in crosstest
      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>
     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>
    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>
    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))
    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>
    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 
    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