| OLD | NEW | 
|---|
| 1 /* crosstest.py --test=test_arith.cpp --test=test_arith_frem.ll \ | 1 /* crosstest.py --test=test_arith.cpp --test=test_arith_frem.ll \ | 
| 2    --test=test_arith_sqrt.ll --driver=test_arith_main.cpp \ | 2    --test=test_arith_sqrt.ll --driver=test_arith_main.cpp \ | 
| 3    --prefix=Subzero_ --output=test_arith */ | 3    --prefix=Subzero_ --output=test_arith */ | 
| 4 | 4 | 
| 5 #include <stdint.h> | 5 #include <stdint.h> | 
| 6 | 6 | 
|  | 7 #include <climits> // CHAR_BIT | 
|  | 8 #include <limits> | 
| 7 #include <cfloat> | 9 #include <cfloat> | 
|  | 10 #include <cmath>   // fmodf | 
| 8 #include <cstring> // memcmp | 11 #include <cstring> // memcmp | 
| 9 #include <iostream> | 12 #include <iostream> | 
| 10 | 13 | 
| 11 // Include test_arith.h twice - once normally, and once within the | 14 // Include test_arith.h twice - once normally, and once within the | 
| 12 // Subzero_ namespace, corresponding to the llc and Subzero translated | 15 // Subzero_ namespace, corresponding to the llc and Subzero translated | 
| 13 // object files, respectively. | 16 // object files, respectively. | 
| 14 #include "test_arith.h" | 17 #include "test_arith.h" | 
| 15 namespace Subzero_ { | 18 namespace Subzero_ { | 
| 16 #include "test_arith.h" | 19 #include "test_arith.h" | 
| 17 } | 20 } | 
| 18 | 21 | 
| 19 volatile unsigned Values[] = { 0x0,        0x1,        0x7ffffffe, 0x7fffffff, | 22 volatile unsigned Values[] = INT_VALUE_ARRAY; | 
| 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, }; |  | 
| 25 const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 23 const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 
| 26 | 24 | 
|  | 25 template <class T> bool inputsMayTriggerException(T Value1, T Value2) { | 
|  | 26   // Avoid HW divide-by-zero exception. | 
|  | 27   if (Value2 == 0) | 
|  | 28     return true; | 
|  | 29   // Avoid HW overflow exception (on x86-32).  TODO: adjust | 
|  | 30   // for other architecture. | 
|  | 31   if (Value1 == std::numeric_limits<T>::min() && Value2 == -1) | 
|  | 32     return true; | 
|  | 33   return false; | 
|  | 34 } | 
|  | 35 | 
| 27 template <typename TypeUnsigned, typename TypeSigned> | 36 template <typename TypeUnsigned, typename TypeSigned> | 
| 28 void testsInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 37 void testsInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 
| 29   typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); | 38   typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); | 
| 30   typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); | 39   typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); | 
| 31   static struct { | 40   static struct { | 
| 32     const char *Name; | 41     const char *Name; | 
| 33     FuncTypeUnsigned FuncLlc; | 42     FuncTypeUnsigned FuncLlc; | 
| 34     FuncTypeUnsigned FuncSz; | 43     FuncTypeUnsigned FuncSz; | 
| 35     bool ExcludeDivExceptions; // for divide related tests | 44     bool ExcludeDivExceptions; // for divide related tests | 
| 36   } Funcs[] = { | 45   } Funcs[] = { | 
| 37 #define X(inst, op, isdiv)                                                     \ | 46 #define X(inst, op, isdiv)                                                     \ | 
| 38   {                                                                            \ | 47   {                                                                            \ | 
| 39     STR(inst), (FuncTypeUnsigned)test##inst,                                   \ | 48     STR(inst), (FuncTypeUnsigned)test##inst,                                   \ | 
| 40         (FuncTypeUnsigned)Subzero_::test##inst, isdiv                          \ | 49         (FuncTypeUnsigned)Subzero_::test##inst, isdiv                          \ | 
| 41   }                                                                            \ | 50   }                                                                            \ | 
| 42   , | 51   , | 
| 43       UINTOP_TABLE | 52       UINTOP_TABLE | 
| 44 #undef X | 53 #undef X | 
| 45 #define X(inst, op, isdiv)                                                     \ | 54 #define X(inst, op, isdiv)                                                     \ | 
| 46   {                                                                            \ | 55   {                                                                            \ | 
| 47     STR(inst), (FuncTypeUnsigned)(FuncTypeSigned)test##inst,                   \ | 56     STR(inst), (FuncTypeUnsigned)(FuncTypeSigned)test##inst,                   \ | 
| 48         (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::test##inst, isdiv          \ | 57         (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::test##inst, isdiv          \ | 
| 49   }                                                                            \ | 58   }                                                                            \ | 
| 50   , | 59   , | 
| 51           SINTOP_TABLE | 60       SINTOP_TABLE | 
| 52 #undef X | 61 #undef X | 
| 53     }; | 62   }; | 
| 54   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 63   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 
| 55 | 64 | 
| 56   if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) { | 65   if (sizeof(TypeUnsigned) <= sizeof(uint32_t)) { | 
| 57     // This is the "normal" version of the loop nest, for 32-bit or | 66     // This is the "normal" version of the loop nest, for 32-bit or | 
| 58     // narrower types. | 67     // narrower types. | 
| 59     for (size_t f = 0; f < NumFuncs; ++f) { | 68     for (size_t f = 0; f < NumFuncs; ++f) { | 
| 60       for (size_t i = 0; i < NumValues; ++i) { | 69       for (size_t i = 0; i < NumValues; ++i) { | 
| 61         for (size_t j = 0; j < NumValues; ++j) { | 70         for (size_t j = 0; j < NumValues; ++j) { | 
| 62           TypeUnsigned Value1 = Values[i]; | 71           TypeUnsigned Value1 = Values[i]; | 
| 63           TypeUnsigned Value2 = Values[j]; | 72           TypeUnsigned Value2 = Values[j]; | 
| 64           // Avoid HW divide-by-zero exception. | 73           // Avoid HW divide-by-zero exception. | 
| 65           if (Funcs[f].ExcludeDivExceptions && Value2 == 0) | 74           if (Funcs[f].ExcludeDivExceptions && | 
| 66             continue; | 75               inputsMayTriggerException<TypeSigned>(Value1, Value2)) | 
| 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; | 76             continue; | 
| 72           ++TotalTests; | 77           ++TotalTests; | 
| 73           TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 78           TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 
| 74           TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 79           TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 
| 75           if (ResultSz == ResultLlc) { | 80           if (ResultSz == ResultLlc) { | 
| 76             ++Passes; | 81             ++Passes; | 
| 77           } else { | 82           } else { | 
| 78             ++Failures; | 83             ++Failures; | 
| 79             std::cout << "test" << Funcs[f].Name << (8 * sizeof(TypeUnsigned)) | 84             std::cout << "test" << Funcs[f].Name | 
| 80                       << "(" << Value1 << ", " << Value2 | 85                       << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1 | 
| 81                       << "): sz=" << (unsigned)ResultSz | 86                       << ", " << Value2 << "): sz=" << (unsigned)ResultSz | 
| 82                       << " llc=" << (unsigned)ResultLlc << std::endl; | 87                       << " llc=" << (unsigned)ResultLlc << std::endl; | 
| 83           } | 88           } | 
| 84         } | 89         } | 
| 85       } | 90       } | 
| 86     } | 91     } | 
| 87   } else { | 92   } else { | 
| 88     // This is the 64-bit version.  Test values are synthesized from | 93     // This is the 64-bit version.  Test values are synthesized from | 
| 89     // the 32-bit values in Values[]. | 94     // the 32-bit values in Values[]. | 
| 90     for (size_t f = 0; f < NumFuncs; ++f) { | 95     for (size_t f = 0; f < NumFuncs; ++f) { | 
| 91       for (size_t iLo = 0; iLo < NumValues; ++iLo) { | 96       for (size_t iLo = 0; iLo < NumValues; ++iLo) { | 
| 92         for (size_t iHi = 0; iHi < NumValues; ++iHi) { | 97         for (size_t iHi = 0; iHi < NumValues; ++iHi) { | 
| 93           for (size_t jLo = 0; jLo < NumValues; ++jLo) { | 98           for (size_t jLo = 0; jLo < NumValues; ++jLo) { | 
| 94             for (size_t jHi = 0; jHi < NumValues; ++jHi) { | 99             for (size_t jHi = 0; jHi < NumValues; ++jHi) { | 
| 95               TypeUnsigned Value1 = | 100               TypeUnsigned Value1 = | 
| 96                   (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo]; | 101                   (((TypeUnsigned)Values[iHi]) << 32) + Values[iLo]; | 
| 97               TypeUnsigned Value2 = | 102               TypeUnsigned Value2 = | 
| 98                   (((TypeUnsigned)Values[jHi]) << 32) + Values[jLo]; | 103                   (((TypeUnsigned)Values[jHi]) << 32) + Values[jLo]; | 
| 99               // Avoid HW divide-by-zero exception. | 104               if (Funcs[f].ExcludeDivExceptions && | 
| 100               if (Funcs[f].ExcludeDivExceptions && Value2 == 0) | 105                   inputsMayTriggerException<TypeSigned>(Value1, Value2)) | 
| 101                 continue; | 106                 continue; | 
| 102               ++TotalTests; | 107               ++TotalTests; | 
| 103               TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 108               TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 
| 104               TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 109               TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 
| 105               if (ResultSz == ResultLlc) { | 110               if (ResultSz == ResultLlc) { | 
| 106                 ++Passes; | 111                 ++Passes; | 
| 107               } else { | 112               } else { | 
| 108                 ++Failures; | 113                 ++Failures; | 
| 109                 std::cout << "test" << Funcs[f].Name | 114                 std::cout << "test" << Funcs[f].Name | 
| 110                           << (8 * sizeof(TypeUnsigned)) << "(" << Value1 << ", " | 115                           << (CHAR_BIT * sizeof(TypeUnsigned)) << "(" << Value1 | 
| 111                           << Value2 << "): sz=" << (unsigned)ResultSz | 116                           << ", " << Value2 << "): sz=" << (unsigned)ResultSz | 
| 112                           << " llc=" << (unsigned)ResultLlc << std::endl; | 117                           << " llc=" << (unsigned)ResultLlc << std::endl; | 
| 113               } | 118               } | 
| 114             } | 119             } | 
| 115           } | 120           } | 
| 116         } | 121         } | 
| 117       } | 122       } | 
| 118     } | 123     } | 
| 119   } | 124   } | 
| 120 } | 125 } | 
| 121 | 126 | 
|  | 127 // Vectors are deterministically constructed by selecting elements from | 
|  | 128 // a pool of scalar values based on a pseudorandom sequence.  Testing | 
|  | 129 // all possible combinations of scalar values from the value table is | 
|  | 130 // not tractable. | 
|  | 131 // TODO: Replace with a portable PRNG from C++11. | 
|  | 132 class PRNG { | 
|  | 133 public: | 
|  | 134   PRNG(uint32_t Seed = 1) : State(Seed) {} | 
|  | 135 | 
|  | 136   uint32_t operator()() { | 
|  | 137     // Lewis, Goodman, and Miller (1969) | 
|  | 138     State = (16807 * State) % 2147483647; | 
|  | 139     return State; | 
|  | 140   } | 
|  | 141 | 
|  | 142 private: | 
|  | 143   uint32_t State; | 
|  | 144 }; | 
|  | 145 | 
|  | 146 const static size_t MaxTestsPerFunc = 100000; | 
|  | 147 | 
|  | 148 template <typename Type, typename ElementType, typename CastType> | 
|  | 149 void outputVector(const Type Vect) { | 
|  | 150   const static size_t NumElementsInType = sizeof(Type) / sizeof(ElementType); | 
|  | 151   for (size_t i = 0; i < NumElementsInType; ++i) { | 
|  | 152     if (i > 0) | 
|  | 153       std::cout << ", "; | 
|  | 154     std::cout << (CastType) Vect[i]; | 
|  | 155   } | 
|  | 156 } | 
|  | 157 | 
|  | 158 template <typename TypeUnsigned, typename TypeSigned, | 
|  | 159           typename ElementTypeUnsigned, typename ElementTypeSigned> | 
|  | 160 void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 
|  | 161   typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned); | 
|  | 162   typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned); | 
|  | 163   static struct { | 
|  | 164     const char *Name; | 
|  | 165     FuncTypeUnsigned FuncLlc; | 
|  | 166     FuncTypeUnsigned FuncSz; | 
|  | 167     bool ExcludeDivExceptions; // for divide related tests | 
|  | 168   } Funcs[] = { | 
|  | 169 #define X(inst, op, isdiv)                                                     \ | 
|  | 170   {                                                                            \ | 
|  | 171     STR(inst), (FuncTypeUnsigned)test##inst,                                   \ | 
|  | 172         (FuncTypeUnsigned)Subzero_::test##inst, isdiv                          \ | 
|  | 173   }                                                                            \ | 
|  | 174   , | 
|  | 175         UINTOP_TABLE | 
|  | 176 #undef X | 
|  | 177 #define X(inst, op, isdiv)                                                     \ | 
|  | 178   {                                                                            \ | 
|  | 179     STR(inst), (FuncTypeUnsigned)(FuncTypeSigned)test##inst,                   \ | 
|  | 180         (FuncTypeUnsigned)(FuncTypeSigned)Subzero_::test##inst, isdiv          \ | 
|  | 181   }                                                                            \ | 
|  | 182   , | 
|  | 183         SINTOP_TABLE | 
|  | 184 #undef X | 
|  | 185   }; | 
|  | 186   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 
|  | 187   const static size_t NumElementsInType = | 
|  | 188       sizeof(TypeUnsigned) / sizeof(ElementTypeUnsigned); | 
|  | 189   for (size_t f = 0; f < NumFuncs; ++f) { | 
|  | 190     PRNG Index; | 
|  | 191     for (size_t i = 0; i < MaxTestsPerFunc; ++i) { | 
|  | 192       // Initialize the test vectors. | 
|  | 193       TypeUnsigned Value1, Value2; | 
|  | 194       for (size_t j = 0; j < NumElementsInType;) { | 
|  | 195         ElementTypeUnsigned Element1 = Values[Index() % NumElementsInType]; | 
|  | 196         ElementTypeUnsigned Element2 = Values[Index() % NumElementsInType]; | 
|  | 197         if (Funcs[f].ExcludeDivExceptions && | 
|  | 198             inputsMayTriggerException<ElementTypeSigned>(Element1, Element2)) | 
|  | 199           continue; | 
|  | 200         Value1[j] = Element1; | 
|  | 201         Value2[j] = Element2; | 
|  | 202         ++j; | 
|  | 203       } | 
|  | 204       // Perform the test. | 
|  | 205       TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2); | 
|  | 206       TypeUnsigned ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 
|  | 207       ++TotalTests; | 
|  | 208       if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { | 
|  | 209         ++Passes; | 
|  | 210       } else { | 
|  | 211         std::cout << "test" << Funcs[f].Name << "v" << NumElementsInType << "i" | 
|  | 212                   << (CHAR_BIT * sizeof(ElementTypeUnsigned)) << "("; | 
|  | 213          outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(Value1); | 
|  | 214          std::cout << ", "; | 
|  | 215          outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(Value2); | 
|  | 216          std::cout << "): sz="; | 
|  | 217          outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(ResultSz); | 
|  | 218          std::cout << " llc="; | 
|  | 219          outputVector<TypeUnsigned, ElementTypeUnsigned, unsigned>(ResultLlc); | 
|  | 220          std::cout << std::endl; | 
|  | 221       } | 
|  | 222     } | 
|  | 223   } | 
|  | 224 } | 
|  | 225 | 
| 122 template <typename Type> | 226 template <typename Type> | 
| 123 void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 227 void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 
| 124   static const Type NegInf = -1.0 / 0.0; | 228   static const Type NegInf = -1.0 / 0.0; | 
| 125   static const Type PosInf = 1.0 / 0.0; | 229   static const Type PosInf = 1.0 / 0.0; | 
| 126   static const Type Nan = 0.0 / 0.0; | 230   static const Type Nan = 0.0 / 0.0; | 
| 127   static const Type NegNan = -0.0 / 0.0; | 231   static const Type NegNan = -0.0 / 0.0; | 
| 128   volatile Type Values[] = { | 232   volatile Type Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan); | 
| 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, |  | 
| 139     Nan,                  NegNan,               -0.0, |  | 
| 140     FLT_MIN,              FLT_MAX, |  | 
| 141     DBL_MIN,              DBL_MAX |  | 
| 142   }; |  | 
| 143   const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 233   const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 
| 144   typedef Type (*FuncType)(Type, Type); | 234   typedef Type (*FuncType)(Type, Type); | 
| 145   static struct { | 235   static struct { | 
| 146     const char *Name; | 236     const char *Name; | 
| 147     FuncType FuncLlc; | 237     FuncType FuncLlc; | 
| 148     FuncType FuncSz; | 238     FuncType FuncSz; | 
| 149   } Funcs[] = { | 239   } Funcs[] = { | 
| 150 #define X(inst, op, func)                                                      \ | 240 #define X(inst, op, func)                                                      \ | 
| 151   { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst }          \ | 241   { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst }          \ | 
| 152   , | 242   , | 
| 153       FPOP_TABLE | 243       FPOP_TABLE | 
| 154 #undef X | 244 #undef X | 
| 155     }; | 245   }; | 
| 156   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 246   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 
| 157 | 247 | 
| 158   for (size_t f = 0; f < NumFuncs; ++f) { | 248   for (size_t f = 0; f < NumFuncs; ++f) { | 
| 159     for (size_t i = 0; i < NumValues; ++i) { | 249     for (size_t i = 0; i < NumValues; ++i) { | 
| 160       for (size_t j = 0; j < NumValues; ++j) { | 250       for (size_t j = 0; j < NumValues; ++j) { | 
| 161         Type Value1 = Values[i]; | 251         Type Value1 = Values[i]; | 
| 162         Type Value2 = Values[j]; | 252         Type Value2 = Values[j]; | 
| 163         ++TotalTests; | 253         ++TotalTests; | 
| 164         Type ResultSz = Funcs[f].FuncSz(Value1, Value2); | 254         Type ResultSz = Funcs[f].FuncSz(Value1, Value2); | 
| 165         Type ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 255         Type ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 
| 166         // Compare results using memcmp() in case they are both NaN. | 256         // Compare results using memcmp() in case they are both NaN. | 
| 167         if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { | 257         if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { | 
| 168           ++Passes; | 258           ++Passes; | 
| 169         } else { | 259         } else { | 
| 170           ++Failures; | 260           ++Failures; | 
| 171           std::cout << std::fixed << "test" << Funcs[f].Name | 261           std::cout << std::fixed << "test" << Funcs[f].Name | 
| 172                     << (8 * sizeof(Type)) << "(" << Value1 << ", " << Value2 | 262                     << (CHAR_BIT * sizeof(Type)) << "(" << Value1 << ", " | 
| 173                     << "): sz=" << ResultSz << " llc=" << ResultLlc | 263                     << Value2 << "): sz=" << ResultSz << " llc=" << ResultLlc | 
| 174                     << std::endl; | 264                     << std::endl; | 
| 175         } | 265         } | 
| 176       } | 266       } | 
| 177     } | 267     } | 
| 178   } | 268   } | 
| 179   for (size_t i = 0; i < NumValues; ++i) { | 269   for (size_t i = 0; i < NumValues; ++i) { | 
| 180     Type Value = Values[i]; | 270     Type Value = Values[i]; | 
| 181     ++TotalTests; | 271     ++TotalTests; | 
| 182     Type ResultSz = Subzero_::mySqrt(Value); | 272     Type ResultSz = Subzero_::mySqrt(Value); | 
| 183     Type ResultLlc = mySqrt(Value); | 273     Type ResultLlc = mySqrt(Value); | 
| 184     // Compare results using memcmp() in case they are both NaN. | 274     // Compare results using memcmp() in case they are both NaN. | 
| 185     if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { | 275     if (!memcmp(&ResultSz, &ResultLlc, sizeof(Type))) { | 
| 186       ++Passes; | 276       ++Passes; | 
| 187     } else { | 277     } else { | 
| 188       ++Failures; | 278       ++Failures; | 
| 189       std::cout << std::fixed << "test_sqrt" | 279       std::cout << std::fixed << "test_sqrt" << (CHAR_BIT * sizeof(Type)) << "(" | 
| 190                 << (8 * sizeof(Type)) << "(" << Value | 280                 << Value << "): sz=" << ResultSz << " llc=" << ResultLlc | 
| 191                 << "): sz=" << ResultSz << " llc=" << ResultLlc |  | 
| 192                 << std::endl; | 281                 << std::endl; | 
| 193     } | 282     } | 
| 194   } | 283   } | 
| 195 } | 284 } | 
| 196 | 285 | 
|  | 286 void testsVecFp(size_t &TotalTests, size_t &Passes, size_t &Failures) { | 
|  | 287   static const float NegInf = -1.0 / 0.0; | 
|  | 288   static const float PosInf = 1.0 / 0.0; | 
|  | 289   static const float Nan = 0.0 / 0.0; | 
|  | 290   static const float NegNan = -0.0 / 0.0; | 
|  | 291   volatile float Values[] = FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan); | 
|  | 292   const static size_t NumValues = sizeof(Values) / sizeof(*Values); | 
|  | 293   typedef v4f32 (*FuncType)(v4f32, v4f32); | 
|  | 294   static struct { | 
|  | 295     const char *Name; | 
|  | 296     FuncType FuncLlc; | 
|  | 297     FuncType FuncSz; | 
|  | 298   } Funcs[] = { | 
|  | 299 #define X(inst, op, func)                                                      \ | 
|  | 300   { STR(inst), (FuncType)test##inst, (FuncType)Subzero_::test##inst }          \ | 
|  | 301   , | 
|  | 302       FPOP_TABLE | 
|  | 303 #undef X | 
|  | 304   }; | 
|  | 305   const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | 
|  | 306   const static size_t NumElementsInType = 4; | 
|  | 307   for (size_t f = 0; f < NumFuncs; ++f) { | 
|  | 308     PRNG Index; | 
|  | 309     for (size_t i = 0; i < MaxTestsPerFunc; ++i) { | 
|  | 310       // Initialize the test vectors. | 
|  | 311       v4f32 Value1, Value2; | 
|  | 312       for (size_t j = 0; j < NumElementsInType; ++j) { | 
|  | 313         Value1[j] = Values[Index() % NumElementsInType]; | 
|  | 314         Value2[j] = Values[Index() % NumElementsInType]; | 
|  | 315       } | 
|  | 316       // Perform the test. | 
|  | 317       v4f32 ResultSz = Funcs[f].FuncSz(Value1, Value2); | 
|  | 318       v4f32 ResultLlc = Funcs[f].FuncLlc(Value1, Value2); | 
|  | 319       ++TotalTests; | 
|  | 320       if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) { | 
|  | 321         ++Passes; | 
|  | 322       } else { | 
|  | 323         ++Failures; | 
|  | 324         std::cout << std::fixed << "test" << Funcs[f].Name << "v4f32" | 
|  | 325                   << "("; | 
|  | 326         outputVector<v4f32, float, float>(Value1); | 
|  | 327         std::cout << ", "; | 
|  | 328         outputVector<v4f32, float, float>(Value2); | 
|  | 329         std::cout << "): sz="; | 
|  | 330         outputVector<v4f32, float, float>(ResultSz); | 
|  | 331         std::cout << " llc="; | 
|  | 332         outputVector<v4f32, float, float>(ResultLlc); | 
|  | 333         std::cout << std::endl; | 
|  | 334       } | 
|  | 335     } | 
|  | 336   } | 
|  | 337 } | 
|  | 338 | 
| 197 int main(int argc, char **argv) { | 339 int main(int argc, char **argv) { | 
| 198   size_t TotalTests = 0; | 340   size_t TotalTests = 0; | 
| 199   size_t Passes = 0; | 341   size_t Passes = 0; | 
| 200   size_t Failures = 0; | 342   size_t Failures = 0; | 
| 201 | 343 | 
| 202   testsInt<uint8_t, int8_t>(TotalTests, Passes, Failures); | 344   testsInt<uint8_t, int8_t>(TotalTests, Passes, Failures); | 
| 203   testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures); | 345   testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures); | 
| 204   testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures); | 346   testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures); | 
| 205   testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures); | 347   testsInt<uint64_t, int64_t>(TotalTests, Passes, Failures); | 
|  | 348   testsVecInt<v4ui32, v4si32, uint32_t, int32_t>(TotalTests, Passes, Failures); | 
|  | 349   testsVecInt<v8ui16, v8si16, uint16_t, int16_t>(TotalTests, Passes, Failures); | 
|  | 350   testsVecInt<v16ui8, v16si8, uint8_t, int8_t>(TotalTests, Passes, Failures); | 
| 206   testsFp<float>(TotalTests, Passes, Failures); | 351   testsFp<float>(TotalTests, Passes, Failures); | 
| 207   testsFp<double>(TotalTests, Passes, Failures); | 352   testsFp<double>(TotalTests, Passes, Failures); | 
|  | 353   testsVecFp(TotalTests, Passes, Failures); | 
| 208 | 354 | 
| 209   std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes | 355   std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes | 
| 210             << " Failures=" << Failures << "\n"; | 356             << " Failures=" << Failures << "\n"; | 
| 211   return Failures; | 357   return Failures; | 
| 212 } | 358 } | 
|  | 359 | 
|  | 360 extern "C" { | 
|  | 361 // Subzero helpers | 
|  | 362   v4si32 Sz_shl_v4i32(v4si32 a, v4si32 b) { return a << b; } | 
|  | 363   v4si32 Sz_ashr_v4i32(v4si32 a, v4si32 b) { return a >> b; } | 
|  | 364   v4ui32 Sz_lshr_v4i32(v4ui32 a, v4ui32 b) { return a >> b; } | 
|  | 365   v4si32 Sz_sdiv_v4i32(v4si32 a, v4si32 b) { return a / b; } | 
|  | 366   v4ui32 Sz_udiv_v4i32(v4ui32 a, v4ui32 b) { return a / b; } | 
|  | 367   v4si32 Sz_srem_v4i32(v4si32 a, v4si32 b) { return a % b; } | 
|  | 368   v4ui32 Sz_urem_v4i32(v4ui32 a, v4ui32 b) { return a % b; } | 
|  | 369 | 
|  | 370   v8si16 Sz_shl_v8i16(v8si16 a, v8si16 b) { return a << b; } | 
|  | 371   v8si16 Sz_ashr_v8i16(v8si16 a, v8si16 b) { return a >> b; } | 
|  | 372   v8ui16 Sz_lshr_v8i16(v8ui16 a, v8ui16 b) { return a >> b; } | 
|  | 373   v8si16 Sz_sdiv_v8i16(v8si16 a, v8si16 b) { return a / b; } | 
|  | 374   v8ui16 Sz_udiv_v8i16(v8ui16 a, v8ui16 b) { return a / b; } | 
|  | 375   v8si16 Sz_srem_v8i16(v8si16 a, v8si16 b) { return a % b; } | 
|  | 376   v8ui16 Sz_urem_v8i16(v8ui16 a, v8ui16 b) { return a % b; } | 
|  | 377 | 
|  | 378   v16ui8 Sz_mul_v16i8(v16ui8 a, v16ui8 b) { return a * b; } | 
|  | 379   v16si8 Sz_shl_v16i8(v16si8 a, v16si8 b) { return a << b; } | 
|  | 380   v16si8 Sz_ashr_v16i8(v16si8 a, v16si8 b) { return a >> b; } | 
|  | 381   v16ui8 Sz_lshr_v16i8(v16ui8 a, v16ui8 b) { return a >> b; } | 
|  | 382   v16si8 Sz_sdiv_v16i8(v16si8 a, v16si8 b) { return a / b; } | 
|  | 383   v16ui8 Sz_udiv_v16i8(v16ui8 a, v16ui8 b) { return a / b; } | 
|  | 384   v16si8 Sz_srem_v16i8(v16si8 a, v16si8 b) { return a % b; } | 
|  | 385   v16ui8 Sz_urem_v16i8(v16ui8 a, v16ui8 b) { return a % b; } | 
|  | 386 | 
|  | 387   v4f32 Sz_frem_v4f32(v4f32 a, v4f32 b) { | 
|  | 388     v4f32 Result; | 
|  | 389     for (int i = 0; i < 4; ++i) | 
|  | 390       Result[i] = fmodf(a[i], b[i]); | 
|  | 391     return Result; | 
|  | 392   } | 
|  | 393 } | 
| OLD | NEW | 
|---|