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_math.h" 38 39#include "gallivm/lp_bld_const.h" 40#include "gallivm/lp_bld_init.h" 41#include "gallivm/lp_bld_debug.h" 42#include "lp_test.h" 43 44 45void 46dump_type(FILE *fp, 47 struct lp_type type) 48{ 49 fprintf(fp, "%s%s%u%sx%u", 50 type.sign ? (type.floating || type.fixed ? "" : "s") : "u", 51 type.floating ? "f" : (type.fixed ? "h" : "i"), 52 type.width, 53 type.norm ? "n" : "", 54 type.length); 55} 56 57 58double 59read_elem(struct lp_type type, const void *src, unsigned index) 60{ 61 double scale = lp_const_scale(type); 62 double value; 63 assert(index < type.length); 64 if (type.floating) { 65 switch(type.width) { 66 case 32: 67 value = *((const float *)src + index); 68 break; 69 case 64: 70 value = *((const double *)src + index); 71 break; 72 default: 73 assert(0); 74 return 0.0; 75 } 76 } 77 else { 78 if(type.sign) { 79 switch(type.width) { 80 case 8: 81 value = *((const int8_t *)src + index); 82 break; 83 case 16: 84 value = *((const int16_t *)src + index); 85 break; 86 case 32: 87 value = *((const int32_t *)src + index); 88 break; 89 case 64: 90 value = *((const int64_t *)src + index); 91 break; 92 default: 93 assert(0); 94 return 0.0; 95 } 96 } 97 else { 98 switch(type.width) { 99 case 8: 100 value = *((const uint8_t *)src + index); 101 break; 102 case 16: 103 value = *((const uint16_t *)src + index); 104 break; 105 case 32: 106 value = *((const uint32_t *)src + index); 107 break; 108 case 64: 109 value = *((const uint64_t *)src + index); 110 break; 111 default: 112 assert(0); 113 return 0.0; 114 } 115 } 116 } 117 return value/scale; 118} 119 120 121void 122write_elem(struct lp_type type, void *dst, unsigned index, double value) 123{ 124 assert(index < type.length); 125 if(!type.sign && value < 0.0) 126 value = 0.0; 127 if(type.norm && value < -1.0) 128 value = -1.0; 129 if(type.norm && value > 1.0) 130 value = 1.0; 131 if (type.floating) { 132 switch(type.width) { 133 case 32: 134 *((float *)dst + index) = (float)(value); 135 break; 136 case 64: 137 *((double *)dst + index) = value; 138 break; 139 default: 140 assert(0); 141 } 142 } 143 else { 144 double scale = lp_const_scale(type); 145 value = round(value*scale); 146 if(type.sign) { 147 long long lvalue = (long long)value; 148 lvalue = MIN2(lvalue, ((long long)1 << (type.width - 1)) - 1); 149 lvalue = MAX2(lvalue, -((long long)1 << (type.width - 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 191void 192random_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 if (!type.fixed && !type.sign && type.width == 32) { 211 /* 212 * rand only returns half the possible range 213 * XXX 64bit values... 214 */ 215 if(rand() & 1) 216 value += (double)0x80000000; 217 } 218 } 219 } 220 if(type.sign) 221 if(rand() & 1) 222 value = -value; 223 write_elem(type, dst, index, value); 224} 225 226 227void 228read_vec(struct lp_type type, const void *src, double *dst) 229{ 230 unsigned i; 231 for (i = 0; i < type.length; ++i) 232 dst[i] = read_elem(type, src, i); 233} 234 235 236void 237write_vec(struct lp_type type, void *dst, const double *src) 238{ 239 unsigned i; 240 for (i = 0; i < type.length; ++i) 241 write_elem(type, dst, i, src[i]); 242} 243 244 245float 246random_float(void) 247{ 248 return (float)((double)rand()/(double)RAND_MAX); 249} 250 251 252void 253random_vec(struct lp_type type, void *dst) 254{ 255 unsigned i; 256 for (i = 0; i < type.length; ++i) 257 random_elem(type, dst, i); 258} 259 260 261boolean 262compare_vec_with_eps(struct lp_type type, const void *res, const void *ref, double eps) 263{ 264 unsigned i; 265 eps *= type.floating ? 8.0 : 2.0; 266 for (i = 0; i < type.length; ++i) { 267 double res_elem = read_elem(type, res, i); 268 double ref_elem = read_elem(type, ref, i); 269 double delta = res_elem - ref_elem; 270 if (ref_elem < -1.0 || ref_elem > 1.0) { 271 delta /= ref_elem; 272 } 273 delta = fabs(delta); 274 if (delta >= eps) { 275 return FALSE; 276 } 277 } 278 279 return TRUE; 280} 281 282 283boolean 284compare_vec(struct lp_type type, const void *res, const void *ref) 285{ 286 double eps = lp_const_eps(type); 287 return compare_vec_with_eps(type, res, ref, eps); 288} 289 290 291void 292dump_vec(FILE *fp, struct lp_type type, const void *src) 293{ 294 unsigned i; 295 for (i = 0; i < type.length; ++i) { 296 if(i) 297 fprintf(fp, " "); 298 if (type.floating) { 299 double value; 300 switch(type.width) { 301 case 32: 302 value = *((const float *)src + i); 303 break; 304 case 64: 305 value = *((const double *)src + i); 306 break; 307 default: 308 assert(0); 309 value = 0.0; 310 } 311 fprintf(fp, "%f", value); 312 } 313 else { 314 if(type.sign && !type.norm) { 315 long long value; 316 const char *format; 317 switch(type.width) { 318 case 8: 319 value = *((const int8_t *)src + i); 320 format = "%3lli"; 321 break; 322 case 16: 323 value = *((const int16_t *)src + i); 324 format = "%5lli"; 325 break; 326 case 32: 327 value = *((const int32_t *)src + i); 328 format = "%10lli"; 329 break; 330 case 64: 331 value = *((const int64_t *)src + i); 332 format = "%20lli"; 333 break; 334 default: 335 assert(0); 336 value = 0.0; 337 format = "?"; 338 } 339 fprintf(fp, format, value); 340 } 341 else { 342 unsigned long long value; 343 const char *format; 344 switch(type.width) { 345 case 8: 346 value = *((const uint8_t *)src + i); 347 format = type.norm ? "%2x" : "%4llu"; 348 break; 349 case 16: 350 value = *((const uint16_t *)src + i); 351 format = type.norm ? "%4x" : "%6llx"; 352 break; 353 case 32: 354 value = *((const uint32_t *)src + i); 355 format = type.norm ? "%8x" : "%11llx"; 356 break; 357 case 64: 358 value = *((const uint64_t *)src + i); 359 format = type.norm ? "%16x" : "%21llx"; 360 break; 361 default: 362 assert(0); 363 value = 0.0; 364 format = "?"; 365 } 366 fprintf(fp, format, value); 367 } 368 } 369 } 370} 371 372 373int main(int argc, char **argv) 374{ 375 unsigned verbose = 0; 376 FILE *fp = NULL; 377 unsigned long n = 1000; 378 unsigned i; 379 boolean success; 380 boolean single = FALSE; 381 unsigned fpstate; 382 383 fpstate = util_fpstate_get(); 384 util_fpstate_set_denorms_to_zero(fpstate); 385 386 if (!lp_build_init()) 387 return 1; 388 389 for(i = 1; i < argc; ++i) { 390 if(strcmp(argv[i], "-v") == 0) 391 ++verbose; 392 else if(strcmp(argv[i], "-s") == 0) 393 single = TRUE; 394 else if(strcmp(argv[i], "-o") == 0) 395 fp = fopen(argv[++i], "wt"); 396 else 397 n = atoi(argv[i]); 398 } 399 400#ifdef DEBUG 401 if (verbose >= 2) { 402 gallivm_debug |= GALLIVM_DEBUG_IR; 403 gallivm_debug |= GALLIVM_DEBUG_ASM; 404 } 405#endif 406 407 if (fp) { 408 /* Warm up the caches */ 409 test_some(0, NULL, 100); 410 411 write_tsv_header(fp); 412 } 413 414 if (single) 415 success = test_single(verbose, fp); 416 else if (n) 417 success = test_some(verbose, fp, n); 418 else 419 success = test_all(verbose, fp); 420 421 if (fp) 422 fclose(fp); 423 424 LLVMShutdown(); 425 426 return success ? 0 : 1; 427} 428