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 
46 void
dump_type(FILE * fp,struct lp_type type)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
read_elem(struct lp_type type,const void * src,unsigned index)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
write_elem(struct lp_type type,void * dst,unsigned index,double value)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          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 
192 void
random_elem(struct lp_type type,void * dst,unsigned index)193 random_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 
228 void
read_vec(struct lp_type type,const void * src,double * dst)229 read_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 
237 void
write_vec(struct lp_type type,void * dst,const double * src)238 write_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 
246 float
random_float(void)247 random_float(void)
248 {
249     return (float)((double)rand()/(double)RAND_MAX);
250 }
251 
252 
253 void
random_vec(struct lp_type type,void * dst)254 random_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 
262 boolean
compare_vec_with_eps(struct lp_type type,const void * res,const void * ref,double eps)263 compare_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 
284 boolean
compare_vec(struct lp_type type,const void * res,const void * ref)285 compare_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 
292 void
dump_vec(FILE * fp,struct lp_type type,const void * src)293 dump_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 
main(int argc,char ** argv)374 int 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