• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
45 void
dump_type(FILE * fp,struct lp_type type)46 dump_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 
58 double
read_elem(struct lp_type type,const void * src,unsigned index)59 read_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 
121 void
write_elem(struct lp_type type,void * dst,unsigned index,double value)122 write_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 
191 void
random_elem(struct lp_type type,void * dst,unsigned index)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          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 
227 void
read_vec(struct lp_type type,const void * src,double * dst)228 read_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 
236 void
write_vec(struct lp_type type,void * dst,const double * src)237 write_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 
245 float
random_float(void)246 random_float(void)
247 {
248     return (float)((double)rand()/(double)RAND_MAX);
249 }
250 
251 
252 void
random_vec(struct lp_type type,void * dst)253 random_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 
261 boolean
compare_vec_with_eps(struct lp_type type,const void * res,const void * ref,double eps)262 compare_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 
283 boolean
compare_vec(struct lp_type type,const void * res,const void * ref)284 compare_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 
291 void
dump_vec(FILE * fp,struct lp_type type,const void * src)292 dump_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 
main(int argc,char ** argv)373 int 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