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