OLD | NEW |
(Empty) | |
| 1 /* crosstest.py --test=test_vector_ops.ll --driver=test_vector_ops_main.cpp \ |
| 2 --prefix=Subzero_ --output=test_vector_ops */ |
| 3 |
| 4 #include <stdint.h> |
| 5 #include <cstring> |
| 6 #include <sstream> |
| 7 #include <iostream> |
| 8 #include <limits> |
| 9 #include <utility> |
| 10 #include <vector> |
| 11 #include <stdlib.h> |
| 12 |
| 13 #include "test_vector_ops.def" |
| 14 |
| 15 // typedefs of native C++ SIMD vector types |
| 16 #define X(ty, elty, castty) typedef elty ty __attribute__((vector_size(16))); |
| 17 VECTOR_TYPE_TABLE |
| 18 #undef X |
| 19 |
| 20 // i1 vector types are not native C++ SIMD vector types. Instead, they |
| 21 // are expanded by the test code into native 128 bit SIMD vector types |
| 22 // with the appropriate number of elements. Representing the types in |
| 23 // VectorOps<> requires a unique name for each type which this |
| 24 // declaration provides. |
| 25 #define X(ty, expandedty, num_elements) \ |
| 26 class ty {}; |
| 27 I1_VECTOR_TYPE_TABLE |
| 28 #undef X |
| 29 |
| 30 template <typename T> struct VectorOps; |
| 31 |
| 32 #define DECLARE_VECTOR_OPS(TYNAME, TY, ELTY, CASTTY, NUM_ELEMENTS) \ |
| 33 template <> struct VectorOps<TYNAME> { \ |
| 34 typedef TY Ty; \ |
| 35 typedef ELTY ElementTy; \ |
| 36 typedef CASTTY CastTy; \ |
| 37 static TY (*insertelement)(TY, CASTTY, int32_t); \ |
| 38 static TY (*Subzero_insertelement)(TY, CASTTY, int32_t); \ |
| 39 static CASTTY (*extractelement)(TY, int32_t); \ |
| 40 static CASTTY (*Subzero_extractelement)(TY, int32_t); \ |
| 41 static size_t NumElements; \ |
| 42 static const char *TypeName; \ |
| 43 }; \ |
| 44 extern "C" TY insertelement_##TYNAME(TY, CASTTY, int32_t); \ |
| 45 extern "C" TY Subzero_insertelement_##TYNAME(TY, CASTTY, int32_t); \ |
| 46 extern "C" CASTTY extractelement_##TYNAME(TY, int32_t); \ |
| 47 extern "C" CASTTY Subzero_extractelement_##TYNAME(TY, int32_t); \ |
| 48 size_t VectorOps<TYNAME>::NumElements = NUM_ELEMENTS; \ |
| 49 TY (*VectorOps<TYNAME>::insertelement)(TY, CASTTY, int32_t) = \ |
| 50 &insertelement_##TYNAME; \ |
| 51 TY (*VectorOps<TYNAME>::Subzero_insertelement)(TY, CASTTY, int32_t) = \ |
| 52 &Subzero_insertelement_##TYNAME; \ |
| 53 CASTTY (*VectorOps<TYNAME>::extractelement)(TY, int32_t) = \ |
| 54 &extractelement_##TYNAME; \ |
| 55 CASTTY (*VectorOps<TYNAME>::Subzero_extractelement)(TY, int32_t) = \ |
| 56 &Subzero_extractelement_##TYNAME; \ |
| 57 const char *VectorOps<TYNAME>::TypeName = #TYNAME; |
| 58 |
| 59 #define X(ty, elty, castty) \ |
| 60 DECLARE_VECTOR_OPS(ty, ty, elty, castty, (sizeof(ty) / sizeof(elty))) |
| 61 VECTOR_TYPE_TABLE |
| 62 #undef X |
| 63 |
| 64 #define X(ty, expandedty, num_elements) \ |
| 65 DECLARE_VECTOR_OPS(ty, expandedty, bool, int64_t, num_elements) |
| 66 I1_VECTOR_TYPE_TABLE |
| 67 #undef X |
| 68 |
| 69 template <typename T> |
| 70 std::string vectAsString(const typename VectorOps<T>::Ty Vect) { |
| 71 std::ostringstream OS; |
| 72 for (size_t I = 0; I < VectorOps<T>::NumElements; ++I) { |
| 73 if (I > 0) |
| 74 OS << " "; |
| 75 OS << (typename VectorOps<T>::CastTy)Vect[I]; |
| 76 } |
| 77 return OS.str(); |
| 78 } |
| 79 |
| 80 template <typename T> |
| 81 typename VectorOps<T>::Ty *getTestVectors(size_t &NumTestVectors) { |
| 82 typedef typename VectorOps<T>::Ty Ty; |
| 83 typedef typename VectorOps<T>::ElementTy ElementTy; |
| 84 |
| 85 Ty Zero; |
| 86 memset(&Zero, 0, sizeof(Zero)); |
| 87 Ty Incr; |
| 88 // Note: The casts in the next two initializations are necessary, |
| 89 // since ElementTy isn't necessarily the type that the value is stored |
| 90 // in the vector. |
| 91 for (int I = 0; I < VectorOps<T>::NumElements; ++I) |
| 92 Incr[I] = (ElementTy)I; |
| 93 Ty Decr; |
| 94 for (int I = 0; I < VectorOps<T>::NumElements; ++I) |
| 95 Decr[I] = (ElementTy)-I; |
| 96 Ty Min; |
| 97 for (int I = 0; I < VectorOps<T>::NumElements; ++I) |
| 98 Min[I] = std::numeric_limits<ElementTy>::min(); |
| 99 Ty Max; |
| 100 for (int I = 0; I < VectorOps<T>::NumElements; ++I) |
| 101 Max[I] = std::numeric_limits<ElementTy>::max(); |
| 102 Ty TestVectors[] = {Zero, Incr, Decr, Min, Max}; |
| 103 |
| 104 NumTestVectors = sizeof(TestVectors) / sizeof(Ty); |
| 105 |
| 106 const size_t VECTOR_ALIGNMENT = 16; |
| 107 void *Dest; |
| 108 if (posix_memalign(&Dest, VECTOR_ALIGNMENT, sizeof(TestVectors))) { |
| 109 std::cerr << "memory allocation error" << std::endl; |
| 110 abort(); |
| 111 } |
| 112 |
| 113 memcpy(Dest, TestVectors, sizeof(TestVectors)); |
| 114 |
| 115 return static_cast<Ty *>(Dest); |
| 116 } |
| 117 |
| 118 template <typename T> |
| 119 void testInsertElement(size_t &TotalTests, size_t &Passes, size_t &Failures) { |
| 120 typedef typename VectorOps<T>::Ty Ty; |
| 121 typedef typename VectorOps<T>::ElementTy ElementTy; |
| 122 |
| 123 size_t NumTestVectors; |
| 124 Ty *TestVectors = getTestVectors<T>(NumTestVectors); |
| 125 |
| 126 ElementTy TestElements[] = {0, 1, std::numeric_limits<ElementTy>::min(), |
| 127 std::numeric_limits<ElementTy>::max()}; |
| 128 const size_t NumTestElements = sizeof(TestElements) / sizeof(ElementTy); |
| 129 |
| 130 for (size_t VI = 0; VI < NumTestVectors; ++VI) { |
| 131 Ty Vect = TestVectors[VI]; |
| 132 for (size_t EI = 0; EI < NumTestElements; ++EI) { |
| 133 ElementTy Elt = TestElements[EI]; |
| 134 for (size_t I = 0; I < VectorOps<T>::NumElements; ++I) { |
| 135 Ty ResultLlc = VectorOps<T>::insertelement(Vect, Elt, I); |
| 136 Ty ResultSz = VectorOps<T>::Subzero_insertelement(Vect, Elt, I); |
| 137 ++TotalTests; |
| 138 if (!memcmp(&ResultLlc, &ResultSz, sizeof(ResultLlc))) { |
| 139 ++Passes; |
| 140 } else { |
| 141 ++Failures; |
| 142 std::cout << "insertelement<" << VectorOps<T>::TypeName << ">(Vect="; |
| 143 std::cout << vectAsString<T>(Vect) |
| 144 << ", Element=" << (typename VectorOps<T>::CastTy)Elt |
| 145 << ", Pos=" << I << ")" << std::endl; |
| 146 std::cout << "llc=" << vectAsString<T>(ResultLlc) << std::endl; |
| 147 std::cout << "sz =" << vectAsString<T>(ResultSz) << std::endl; |
| 148 } |
| 149 } |
| 150 } |
| 151 } |
| 152 |
| 153 free(TestVectors); |
| 154 } |
| 155 |
| 156 template <typename T> |
| 157 void testExtractElement(size_t &TotalTests, size_t &Passes, size_t &Failures) { |
| 158 typedef typename VectorOps<T>::Ty Ty; |
| 159 typedef typename VectorOps<T>::ElementTy ElementTy; |
| 160 typedef typename VectorOps<T>::CastTy CastTy; |
| 161 |
| 162 size_t NumTestVectors; |
| 163 Ty *TestVectors = getTestVectors<T>(NumTestVectors); |
| 164 |
| 165 for (size_t VI = 0; VI < NumTestVectors; ++VI) { |
| 166 Ty Vect = TestVectors[VI]; |
| 167 for (size_t I = 0; I < VectorOps<T>::NumElements; ++I) { |
| 168 CastTy ResultLlc = VectorOps<T>::extractelement(Vect, I); |
| 169 CastTy ResultSz = VectorOps<T>::Subzero_extractelement(Vect, I); |
| 170 ++TotalTests; |
| 171 if (!memcmp(&ResultLlc, &ResultSz, sizeof(ResultLlc))) { |
| 172 ++Passes; |
| 173 } else { |
| 174 ++Failures; |
| 175 std::cout << "extractelement<" << VectorOps<T>::TypeName << ">(Vect="; |
| 176 std::cout << vectAsString<T>(Vect) << ", Pos=" << I << ")" << std::endl; |
| 177 std::cout << "llc=" << ResultLlc << std::endl; |
| 178 std::cout << "sz =" << ResultSz << std::endl; |
| 179 } |
| 180 } |
| 181 } |
| 182 |
| 183 free(TestVectors); |
| 184 } |
| 185 |
| 186 int main(int argc, char *argv[]) { |
| 187 size_t TotalTests = 0; |
| 188 size_t Passes = 0; |
| 189 size_t Failures = 0; |
| 190 |
| 191 testInsertElement<v4i1>(TotalTests, Passes, Failures); |
| 192 testInsertElement<v8i1>(TotalTests, Passes, Failures); |
| 193 testInsertElement<v16i1>(TotalTests, Passes, Failures); |
| 194 testInsertElement<v16si8>(TotalTests, Passes, Failures); |
| 195 testInsertElement<v16ui8>(TotalTests, Passes, Failures); |
| 196 testInsertElement<v8si16>(TotalTests, Passes, Failures); |
| 197 testInsertElement<v8ui16>(TotalTests, Passes, Failures); |
| 198 testInsertElement<v4si32>(TotalTests, Passes, Failures); |
| 199 testInsertElement<v4ui32>(TotalTests, Passes, Failures); |
| 200 testInsertElement<v4f32>(TotalTests, Passes, Failures); |
| 201 |
| 202 testExtractElement<v4i1>(TotalTests, Passes, Failures); |
| 203 testExtractElement<v8i1>(TotalTests, Passes, Failures); |
| 204 testExtractElement<v16i1>(TotalTests, Passes, Failures); |
| 205 testExtractElement<v16si8>(TotalTests, Passes, Failures); |
| 206 testExtractElement<v16ui8>(TotalTests, Passes, Failures); |
| 207 testExtractElement<v8si16>(TotalTests, Passes, Failures); |
| 208 testExtractElement<v8ui16>(TotalTests, Passes, Failures); |
| 209 testExtractElement<v4si32>(TotalTests, Passes, Failures); |
| 210 testExtractElement<v4ui32>(TotalTests, Passes, Failures); |
| 211 testExtractElement<v4f32>(TotalTests, Passes, Failures); |
| 212 |
| 213 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes |
| 214 << " Failures=" << Failures << "\n"; |
| 215 |
| 216 return Failures; |
| 217 } |
| 218 |
| 219 extern "C" { |
| 220 |
| 221 void ice_unreachable(void) { |
| 222 std::cerr << "\"unreachable\" instruction encountered" << std::endl; |
| 223 abort(); |
| 224 } |
| 225 } |
OLD | NEW |