1 /************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29 /** 30 * @file 31 * Shared testing code. 32 * 33 * @author Jose Fonseca <jfonseca (at) vmware.com> 34 */ 35 36 37 #include "util/u_cpu_detect.h" 38 #include "util/u_math.h" 39 40 #include "gallivm/lp_bld_const.h" 41 #include "gallivm/lp_bld_init.h" 42 #include "gallivm/lp_bld_debug.h" 43 #include "lp_test.h" 44 45 46 void 47 dump_type(FILE *fp, 48 struct lp_type type) 49 { 50 fprintf(fp, "%s%s%u%sx%u", 51 type.sign ? (type.floating || type.fixed ? "" : "s") : "u", 52 type.floating ? "f" : (type.fixed ? "h" : "i"), 53 type.width, 54 type.norm ? "n" : "", 55 type.length); 56 } 57 58 59 double 60 read_elem(struct lp_type type, const void *src, unsigned index) 61 { 62 double scale = lp_const_scale(type); 63 double value; 64 assert(index < type.length); 65 if (type.floating) { 66 switch(type.width) { 67 case 32: 68 value = *((const float *)src + index); 69 break; 70 case 64: 71 value = *((const double *)src + index); 72 break; 73 default: 74 assert(0); 75 return 0.0; 76 } 77 } 78 else { 79 if(type.sign) { 80 switch(type.width) { 81 case 8: 82 value = *((const int8_t *)src + index); 83 break; 84 case 16: 85 value = *((const int16_t *)src + index); 86 break; 87 case 32: 88 value = *((const int32_t *)src + index); 89 break; 90 case 64: 91 value = *((const int64_t *)src + index); 92 break; 93 default: 94 assert(0); 95 return 0.0; 96 } 97 } 98 else { 99 switch(type.width) { 100 case 8: 101 value = *((const uint8_t *)src + index); 102 break; 103 case 16: 104 value = *((const uint16_t *)src + index); 105 break; 106 case 32: 107 value = *((const uint32_t *)src + index); 108 break; 109 case 64: 110 value = *((const uint64_t *)src + index); 111 break; 112 default: 113 assert(0); 114 return 0.0; 115 } 116 } 117 } 118 return value/scale; 119 } 120 121 122 void 123 write_elem(struct lp_type type, void *dst, unsigned index, double value) 124 { 125 assert(index < type.length); 126 if(!type.sign && value < 0.0) 127 value = 0.0; 128 if(type.norm && value < -1.0) 129 value = -1.0; 130 if(type.norm && value > 1.0) 131 value = 1.0; 132 if (type.floating) { 133 switch(type.width) { 134 case 32: 135 *((float *)dst + index) = (float)(value); 136 break; 137 case 64: 138 *((double *)dst + index) = value; 139 break; 140 default: 141 assert(0); 142 } 143 } 144 else { 145 double scale = lp_const_scale(type); 146 value = round(value*scale); 147 if(type.sign) { 148 long long lvalue = (long long)value; 149 lvalue = MIN2(lvalue, ((long long)1 << (type.width - 1)) - 1); 150 switch(type.width) { 151 case 8: 152 *((int8_t *)dst + index) = (int8_t)lvalue; 153 break; 154 case 16: 155 *((int16_t *)dst + index) = (int16_t)lvalue; 156 break; 157 case 32: 158 *((int32_t *)dst + index) = (int32_t)lvalue; 159 break; 160 case 64: 161 *((int64_t *)dst + index) = (int64_t)lvalue; 162 break; 163 default: 164 assert(0); 165 } 166 } 167 else { 168 unsigned long long lvalue = (long long)value; 169 lvalue = MIN2(lvalue, ((unsigned long long)1 << type.width) - 1); 170 switch(type.width) { 171 case 8: 172 *((uint8_t *)dst + index) = (uint8_t)lvalue; 173 break; 174 case 16: 175 *((uint16_t *)dst + index) = (uint16_t)lvalue; 176 break; 177 case 32: 178 *((uint32_t *)dst + index) = (uint32_t)lvalue; 179 break; 180 case 64: 181 *((uint64_t *)dst + index) = (uint64_t)lvalue; 182 break; 183 default: 184 assert(0); 185 } 186 } 187 } 188 } 189 190 191 void 192 random_elem(struct lp_type type, void *dst, unsigned index) 193 { 194 double value; 195 assert(index < type.length); 196 value = (double)rand()/(double)RAND_MAX; 197 if(!type.norm) { 198 if (type.floating) { 199 value *= 2.0; 200 } 201 else { 202 unsigned long long mask; 203 if (type.fixed) 204 mask = ((unsigned long long)1 << (type.width / 2)) - 1; 205 else if (type.sign) 206 mask = ((unsigned long long)1 << (type.width - 1)) - 1; 207 else 208 mask = ((unsigned long long)1 << type.width) - 1; 209 value += (double)(mask & rand()); 210 } 211 } 212 if(!type.sign) 213 if(rand() & 1) 214 value = -value; 215 write_elem(type, dst, index, value); 216 } 217 218 219 void 220 read_vec(struct lp_type type, const void *src, double *dst) 221 { 222 unsigned i; 223 for (i = 0; i < type.length; ++i) 224 dst[i] = read_elem(type, src, i); 225 } 226 227 228 void 229 write_vec(struct lp_type type, void *dst, const double *src) 230 { 231 unsigned i; 232 for (i = 0; i < type.length; ++i) 233 write_elem(type, dst, i, src[i]); 234 } 235 236 237 float 238 random_float(void) 239 { 240 return (float)((double)rand()/(double)RAND_MAX); 241 } 242 243 244 void 245 random_vec(struct lp_type type, void *dst) 246 { 247 unsigned i; 248 for (i = 0; i < type.length; ++i) 249 random_elem(type, dst, i); 250 } 251 252 253 boolean 254 compare_vec_with_eps(struct lp_type type, const void *res, const void *ref, double eps) 255 { 256 unsigned i; 257 eps *= type.floating ? 8.0 : 2.0; 258 for (i = 0; i < type.length; ++i) { 259 double res_elem = read_elem(type, res, i); 260 double ref_elem = read_elem(type, ref, i); 261 double delta = res_elem - ref_elem; 262 if (ref_elem < -1.0 || ref_elem > 1.0) { 263 delta /= ref_elem; 264 } 265 delta = fabs(delta); 266 if (delta >= eps) { 267 return FALSE; 268 } 269 } 270 271 return TRUE; 272 } 273 274 275 boolean 276 compare_vec(struct lp_type type, const void *res, const void *ref) 277 { 278 double eps = lp_const_eps(type); 279 return compare_vec_with_eps(type, res, ref, eps); 280 } 281 282 283 void 284 dump_vec(FILE *fp, struct lp_type type, const void *src) 285 { 286 unsigned i; 287 for (i = 0; i < type.length; ++i) { 288 if(i) 289 fprintf(fp, " "); 290 if (type.floating) { 291 double value; 292 switch(type.width) { 293 case 32: 294 value = *((const float *)src + i); 295 break; 296 case 64: 297 value = *((const double *)src + i); 298 break; 299 default: 300 assert(0); 301 value = 0.0; 302 } 303 fprintf(fp, "%f", value); 304 } 305 else { 306 if(type.sign && !type.norm) { 307 long long value; 308 const char *format; 309 switch(type.width) { 310 case 8: 311 value = *((const int8_t *)src + i); 312 format = "%3lli"; 313 break; 314 case 16: 315 value = *((const int16_t *)src + i); 316 format = "%5lli"; 317 break; 318 case 32: 319 value = *((const int32_t *)src + i); 320 format = "%10lli"; 321 break; 322 case 64: 323 value = *((const int64_t *)src + i); 324 format = "%20lli"; 325 break; 326 default: 327 assert(0); 328 value = 0.0; 329 format = "?"; 330 } 331 fprintf(fp, format, value); 332 } 333 else { 334 unsigned long long value; 335 const char *format; 336 switch(type.width) { 337 case 8: 338 value = *((const uint8_t *)src + i); 339 format = type.norm ? "%2x" : "%4llu"; 340 break; 341 case 16: 342 value = *((const uint16_t *)src + i); 343 format = type.norm ? "%4x" : "%6llx"; 344 break; 345 case 32: 346 value = *((const uint32_t *)src + i); 347 format = type.norm ? "%8x" : "%11llx"; 348 break; 349 case 64: 350 value = *((const uint64_t *)src + i); 351 format = type.norm ? "%16x" : "%21llx"; 352 break; 353 default: 354 assert(0); 355 value = 0.0; 356 format = "?"; 357 } 358 fprintf(fp, format, value); 359 } 360 } 361 } 362 } 363 364 365 int main(int argc, char **argv) 366 { 367 unsigned verbose = 0; 368 FILE *fp = NULL; 369 unsigned long n = 1000; 370 unsigned i; 371 boolean success; 372 boolean single = FALSE; 373 374 for(i = 1; i < argc; ++i) { 375 if(strcmp(argv[i], "-v") == 0) 376 ++verbose; 377 else if(strcmp(argv[i], "-s") == 0) 378 single = TRUE; 379 else if(strcmp(argv[i], "-o") == 0) 380 fp = fopen(argv[++i], "wt"); 381 else 382 n = atoi(argv[i]); 383 } 384 385 lp_build_init(); 386 387 #ifdef DEBUG 388 if (verbose >= 2) { 389 gallivm_debug |= GALLIVM_DEBUG_IR; 390 gallivm_debug |= GALLIVM_DEBUG_ASM; 391 } 392 #endif 393 394 util_cpu_detect(); 395 396 if(fp) { 397 /* Warm up the caches */ 398 test_some(0, NULL, 100); 399 400 write_tsv_header(fp); 401 } 402 403 if (single) 404 success = test_single(verbose, fp); 405 else if (n) 406 success = test_some(verbose, fp, n); 407 else 408 success = test_all(verbose, fp); 409 410 if(fp) 411 fclose(fp); 412 413 return success ? 0 : 1; 414 } 415