Home | History | Annotate | Download | only in llvmpipe
      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    unsigned fpstate;
    374 
    375    util_cpu_detect();
    376    fpstate = util_fpstate_get();
    377    util_fpstate_set_denorms_to_zero(fpstate);
    378 
    379    if (!lp_build_init())
    380       return 1;
    381 
    382    for(i = 1; i < argc; ++i) {
    383       if(strcmp(argv[i], "-v") == 0)
    384          ++verbose;
    385       else if(strcmp(argv[i], "-s") == 0)
    386          single = TRUE;
    387       else if(strcmp(argv[i], "-o") == 0)
    388          fp = fopen(argv[++i], "wt");
    389       else
    390          n = atoi(argv[i]);
    391    }
    392 
    393 #ifdef DEBUG
    394    if (verbose >= 2) {
    395       gallivm_debug |= GALLIVM_DEBUG_IR;
    396       gallivm_debug |= GALLIVM_DEBUG_ASM;
    397    }
    398 #endif
    399 
    400    if (fp) {
    401       /* Warm up the caches */
    402       test_some(0, NULL, 100);
    403 
    404       write_tsv_header(fp);
    405    }
    406 
    407    if (single)
    408       success = test_single(verbose, fp);
    409    else if (n)
    410       success = test_some(verbose, fp, n);
    411    else
    412       success = test_all(verbose, fp);
    413 
    414    if (fp)
    415       fclose(fp);
    416 
    417    LLVMShutdown();
    418 
    419    return success ? 0 : 1;
    420 }
    421