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@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 46void 47dump_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 59double 60read_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 122void 123write_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 lvalue = MAX2(lvalue, -((long long)1 << (type.width - 1))); 151 switch(type.width) { 152 case 8: 153 *((int8_t *)dst + index) = (int8_t)lvalue; 154 break; 155 case 16: 156 *((int16_t *)dst + index) = (int16_t)lvalue; 157 break; 158 case 32: 159 *((int32_t *)dst + index) = (int32_t)lvalue; 160 break; 161 case 64: 162 *((int64_t *)dst + index) = (int64_t)lvalue; 163 break; 164 default: 165 assert(0); 166 } 167 } 168 else { 169 unsigned long long lvalue = (long long)value; 170 lvalue = MIN2(lvalue, ((unsigned long long)1 << type.width) - 1); 171 switch(type.width) { 172 case 8: 173 *((uint8_t *)dst + index) = (uint8_t)lvalue; 174 break; 175 case 16: 176 *((uint16_t *)dst + index) = (uint16_t)lvalue; 177 break; 178 case 32: 179 *((uint32_t *)dst + index) = (uint32_t)lvalue; 180 break; 181 case 64: 182 *((uint64_t *)dst + index) = (uint64_t)lvalue; 183 break; 184 default: 185 assert(0); 186 } 187 } 188 } 189} 190 191 192void 193random_elem(struct lp_type type, void *dst, unsigned index) 194{ 195 double value; 196 assert(index < type.length); 197 value = (double)rand()/(double)RAND_MAX; 198 if(!type.norm) { 199 if (type.floating) { 200 value *= 2.0; 201 } 202 else { 203 unsigned long long mask; 204 if (type.fixed) 205 mask = ((unsigned long long)1 << (type.width / 2)) - 1; 206 else if (type.sign) 207 mask = ((unsigned long long)1 << (type.width - 1)) - 1; 208 else 209 mask = ((unsigned long long)1 << type.width) - 1; 210 value += (double)(mask & rand()); 211 if (!type.fixed && !type.sign && type.width == 32) { 212 /* 213 * rand only returns half the possible range 214 * XXX 64bit values... 215 */ 216 if(rand() & 1) 217 value += (double)0x80000000; 218 } 219 } 220 } 221 if(type.sign) 222 if(rand() & 1) 223 value = -value; 224 write_elem(type, dst, index, value); 225} 226 227 228void 229read_vec(struct lp_type type, const void *src, double *dst) 230{ 231 unsigned i; 232 for (i = 0; i < type.length; ++i) 233 dst[i] = read_elem(type, src, i); 234} 235 236 237void 238write_vec(struct lp_type type, void *dst, const double *src) 239{ 240 unsigned i; 241 for (i = 0; i < type.length; ++i) 242 write_elem(type, dst, i, src[i]); 243} 244 245 246float 247random_float(void) 248{ 249 return (float)((double)rand()/(double)RAND_MAX); 250} 251 252 253void 254random_vec(struct lp_type type, void *dst) 255{ 256 unsigned i; 257 for (i = 0; i < type.length; ++i) 258 random_elem(type, dst, i); 259} 260 261 262boolean 263compare_vec_with_eps(struct lp_type type, const void *res, const void *ref, double eps) 264{ 265 unsigned i; 266 eps *= type.floating ? 8.0 : 2.0; 267 for (i = 0; i < type.length; ++i) { 268 double res_elem = read_elem(type, res, i); 269 double ref_elem = read_elem(type, ref, i); 270 double delta = res_elem - ref_elem; 271 if (ref_elem < -1.0 || ref_elem > 1.0) { 272 delta /= ref_elem; 273 } 274 delta = fabs(delta); 275 if (delta >= eps) { 276 return FALSE; 277 } 278 } 279 280 return TRUE; 281} 282 283 284boolean 285compare_vec(struct lp_type type, const void *res, const void *ref) 286{ 287 double eps = lp_const_eps(type); 288 return compare_vec_with_eps(type, res, ref, eps); 289} 290 291 292void 293dump_vec(FILE *fp, struct lp_type type, const void *src) 294{ 295 unsigned i; 296 for (i = 0; i < type.length; ++i) { 297 if(i) 298 fprintf(fp, " "); 299 if (type.floating) { 300 double value; 301 switch(type.width) { 302 case 32: 303 value = *((const float *)src + i); 304 break; 305 case 64: 306 value = *((const double *)src + i); 307 break; 308 default: 309 assert(0); 310 value = 0.0; 311 } 312 fprintf(fp, "%f", value); 313 } 314 else { 315 if(type.sign && !type.norm) { 316 long long value; 317 const char *format; 318 switch(type.width) { 319 case 8: 320 value = *((const int8_t *)src + i); 321 format = "%3lli"; 322 break; 323 case 16: 324 value = *((const int16_t *)src + i); 325 format = "%5lli"; 326 break; 327 case 32: 328 value = *((const int32_t *)src + i); 329 format = "%10lli"; 330 break; 331 case 64: 332 value = *((const int64_t *)src + i); 333 format = "%20lli"; 334 break; 335 default: 336 assert(0); 337 value = 0.0; 338 format = "?"; 339 } 340 fprintf(fp, format, value); 341 } 342 else { 343 unsigned long long value; 344 const char *format; 345 switch(type.width) { 346 case 8: 347 value = *((const uint8_t *)src + i); 348 format = type.norm ? "%2x" : "%4llu"; 349 break; 350 case 16: 351 value = *((const uint16_t *)src + i); 352 format = type.norm ? "%4x" : "%6llx"; 353 break; 354 case 32: 355 value = *((const uint32_t *)src + i); 356 format = type.norm ? "%8x" : "%11llx"; 357 break; 358 case 64: 359 value = *((const uint64_t *)src + i); 360 format = type.norm ? "%16x" : "%21llx"; 361 break; 362 default: 363 assert(0); 364 value = 0.0; 365 format = "?"; 366 } 367 fprintf(fp, format, value); 368 } 369 } 370 } 371} 372 373 374int main(int argc, char **argv) 375{ 376 unsigned verbose = 0; 377 FILE *fp = NULL; 378 unsigned long n = 1000; 379 unsigned i; 380 boolean success; 381 boolean single = FALSE; 382 unsigned fpstate; 383 384 util_cpu_detect(); 385 fpstate = util_fpstate_get(); 386 util_fpstate_set_denorms_to_zero(fpstate); 387 388 if (!lp_build_init()) 389 return 1; 390 391 for(i = 1; i < argc; ++i) { 392 if(strcmp(argv[i], "-v") == 0) 393 ++verbose; 394 else if(strcmp(argv[i], "-s") == 0) 395 single = TRUE; 396 else if(strcmp(argv[i], "-o") == 0) 397 fp = fopen(argv[++i], "wt"); 398 else 399 n = atoi(argv[i]); 400 } 401 402#ifdef DEBUG 403 if (verbose >= 2) { 404 gallivm_debug |= GALLIVM_DEBUG_IR; 405 gallivm_debug |= GALLIVM_DEBUG_ASM; 406 } 407#endif 408 409 if (fp) { 410 /* Warm up the caches */ 411 test_some(0, NULL, 100); 412 413 write_tsv_header(fp); 414 } 415 416 if (single) 417 success = test_single(verbose, fp); 418 else if (n) 419 success = test_some(verbose, fp, n); 420 else 421 success = test_all(verbose, fp); 422 423 if (fp) 424 fclose(fp); 425 426 LLVMShutdown(); 427 428 return success ? 0 : 1; 429} 430