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 <[email protected]>
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 } else {
77 if (type.sign) {
78 switch (type.width) {
79 case 8:
80 value = *((const int8_t *)src + index);
81 break;
82 case 16:
83 value = *((const int16_t *)src + index);
84 break;
85 case 32:
86 value = *((const int32_t *)src + index);
87 break;
88 case 64:
89 value = *((const int64_t *)src + index);
90 break;
91 default:
92 assert(0);
93 return 0.0;
94 }
95 } else {
96 switch (type.width) {
97 case 8:
98 value = *((const uint8_t *)src + index);
99 break;
100 case 16:
101 value = *((const uint16_t *)src + index);
102 break;
103 case 32:
104 value = *((const uint32_t *)src + index);
105 break;
106 case 64:
107 value = *((const uint64_t *)src + index);
108 break;
109 default:
110 assert(0);
111 return 0.0;
112 }
113 }
114 }
115 return value/scale;
116 }
117
118
119 void
write_elem(struct lp_type type,void * dst,unsigned index,double value)120 write_elem(struct lp_type type, void *dst, unsigned index, double value)
121 {
122 assert(index < type.length);
123 if (!type.sign && value < 0.0)
124 value = 0.0;
125 if (type.norm && value < -1.0)
126 value = -1.0;
127 if (type.norm && value > 1.0)
128 value = 1.0;
129 if (type.floating) {
130 switch (type.width) {
131 case 32:
132 *((float *)dst + index) = (float)(value);
133 break;
134 case 64:
135 *((double *)dst + index) = value;
136 break;
137 default:
138 assert(0);
139 }
140 } else {
141 double scale = lp_const_scale(type);
142 value = round(value*scale);
143 if (type.sign) {
144 long long lvalue = (long long)value;
145 lvalue = MIN2(lvalue, ((long long)1 << (type.width - 1)) - 1);
146 lvalue = MAX2(lvalue, -((long long)1 << (type.width - 1)));
147 switch (type.width) {
148 case 8:
149 *((int8_t *)dst + index) = (int8_t)lvalue;
150 break;
151 case 16:
152 *((int16_t *)dst + index) = (int16_t)lvalue;
153 break;
154 case 32:
155 *((int32_t *)dst + index) = (int32_t)lvalue;
156 break;
157 case 64:
158 *((int64_t *)dst + index) = (int64_t)lvalue;
159 break;
160 default:
161 assert(0);
162 }
163 } else {
164 unsigned long long lvalue = (long long)value;
165 lvalue = MIN2(lvalue, ((unsigned long long)1 << type.width) - 1);
166 switch (type.width) {
167 case 8:
168 *((uint8_t *)dst + index) = (uint8_t)lvalue;
169 break;
170 case 16:
171 *((uint16_t *)dst + index) = (uint16_t)lvalue;
172 break;
173 case 32:
174 *((uint32_t *)dst + index) = (uint32_t)lvalue;
175 break;
176 case 64:
177 *((uint64_t *)dst + index) = (uint64_t)lvalue;
178 break;
179 default:
180 assert(0);
181 }
182 }
183 }
184 }
185
186
187 void
random_elem(struct lp_type type,void * dst,unsigned index)188 random_elem(struct lp_type type, void *dst, unsigned index)
189 {
190 double value;
191 assert(index < type.length);
192 value = (double)rand()/(double)RAND_MAX;
193 if (!type.norm) {
194 if (type.floating) {
195 value *= 2.0;
196 } else {
197 unsigned long long mask;
198 if (type.fixed)
199 mask = ((unsigned long long)1 << (type.width / 2)) - 1;
200 else if (type.sign)
201 mask = ((unsigned long long)1 << (type.width - 1)) - 1;
202 else
203 mask = ((unsigned long long)1 << type.width) - 1;
204 value += (double)(mask & rand());
205 if (!type.fixed && !type.sign && type.width == 32) {
206 /*
207 * rand only returns half the possible range
208 * XXX 64bit values...
209 */
210 if (rand() & 1)
211 value += (double)0x80000000;
212 }
213 }
214 }
215 if (type.sign)
216 if (rand() & 1)
217 value = -value;
218 write_elem(type, dst, index, value);
219 }
220
221
222 void
read_vec(struct lp_type type,const void * src,double * dst)223 read_vec(struct lp_type type, const void *src, double *dst)
224 {
225 unsigned i;
226 for (i = 0; i < type.length; ++i)
227 dst[i] = read_elem(type, src, i);
228 }
229
230
231 void
write_vec(struct lp_type type,void * dst,const double * src)232 write_vec(struct lp_type type, void *dst, const double *src)
233 {
234 unsigned i;
235 for (i = 0; i < type.length; ++i)
236 write_elem(type, dst, i, src[i]);
237 }
238
239
240 float
random_float(void)241 random_float(void)
242 {
243 return (float)((double)rand()/(double)RAND_MAX);
244 }
245
246
247 void
random_vec(struct lp_type type,void * dst)248 random_vec(struct lp_type type, void *dst)
249 {
250 unsigned i;
251 for (i = 0; i < type.length; ++i)
252 random_elem(type, dst, i);
253 }
254
255
256 bool
compare_vec_with_eps(struct lp_type type,const void * res,const void * ref,double eps)257 compare_vec_with_eps(struct lp_type type, const void *res, const void *ref, double eps)
258 {
259 unsigned i;
260 eps *= type.floating ? 8.0 : 2.0;
261 for (i = 0; i < type.length; ++i) {
262 double res_elem = read_elem(type, res, i);
263 double ref_elem = read_elem(type, ref, i);
264 double delta = res_elem - ref_elem;
265 if (ref_elem < -1.0 || ref_elem > 1.0) {
266 delta /= ref_elem;
267 }
268 delta = fabs(delta);
269 if (delta >= eps) {
270 return false;
271 }
272 }
273
274 return true;
275 }
276
277
278 bool
compare_vec(struct lp_type type,const void * res,const void * ref)279 compare_vec(struct lp_type type, const void *res, const void *ref)
280 {
281 double eps = lp_const_eps(type);
282 return compare_vec_with_eps(type, res, ref, eps);
283 }
284
285
286 void
dump_vec(FILE * fp,struct lp_type type,const void * src)287 dump_vec(FILE *fp, struct lp_type type, const void *src)
288 {
289 unsigned i;
290 for (i = 0; i < type.length; ++i) {
291 if (i)
292 fprintf(fp, " ");
293 if (type.floating) {
294 double value;
295 switch (type.width) {
296 case 32:
297 value = *((const float *)src + i);
298 break;
299 case 64:
300 value = *((const double *)src + i);
301 break;
302 default:
303 assert(0);
304 value = 0.0;
305 }
306 fprintf(fp, "%f", value);
307 } else {
308 if (type.sign && !type.norm) {
309 long long value;
310 const char *format;
311 switch (type.width) {
312 case 8:
313 value = *((const int8_t *)src + i);
314 format = "%3lli";
315 break;
316 case 16:
317 value = *((const int16_t *)src + i);
318 format = "%5lli";
319 break;
320 case 32:
321 value = *((const int32_t *)src + i);
322 format = "%10lli";
323 break;
324 case 64:
325 value = *((const int64_t *)src + i);
326 format = "%20lli";
327 break;
328 default:
329 assert(0);
330 value = 0.0;
331 format = "?";
332 }
333 fprintf(fp, format, value);
334 } else {
335 unsigned long long value;
336 const char *format;
337 switch (type.width) {
338 case 8:
339 value = *((const uint8_t *)src + i);
340 format = type.norm ? "%2x" : "%4llu";
341 break;
342 case 16:
343 value = *((const uint16_t *)src + i);
344 format = type.norm ? "%4x" : "%6llx";
345 break;
346 case 32:
347 value = *((const uint32_t *)src + i);
348 format = type.norm ? "%8x" : "%11llx";
349 break;
350 case 64:
351 value = *((const uint64_t *)src + i);
352 format = type.norm ? "%16x" : "%21llx";
353 break;
354 default:
355 assert(0);
356 value = 0.0;
357 format = "?";
358 }
359 fprintf(fp, format, value);
360 }
361 }
362 }
363 }
364
365
366 int
main(int argc,char ** argv)367 main(int argc, char **argv)
368 {
369 unsigned verbose = 0;
370 FILE *fp = NULL;
371 unsigned long n = 1000;
372 unsigned i;
373 bool success;
374 bool single = false;
375 unsigned fpstate;
376
377 fpstate = util_fpstate_get();
378 util_fpstate_set_denorms_to_zero(fpstate);
379
380 if (!lp_build_init())
381 return 1;
382
383 for (i = 1; i < argc; ++i) {
384 if (strcmp(argv[i], "-v") == 0)
385 ++verbose;
386 else if (strcmp(argv[i], "-s") == 0)
387 single = true;
388 else if (strcmp(argv[i], "-o") == 0)
389 fp = fopen(argv[++i], "wt");
390 else
391 n = atoi(argv[i]);
392 }
393
394 #if MESA_DEBUG
395 if (verbose >= 2) {
396 gallivm_debug |= GALLIVM_DEBUG_IR;
397 gallivm_debug |= GALLIVM_DEBUG_ASM;
398 }
399 #endif
400
401 if (fp) {
402 /* Warm up the caches */
403 test_some(0, NULL, 100);
404
405 write_tsv_header(fp);
406 }
407
408 if (single)
409 success = test_single(verbose, fp);
410 else if (n)
411 success = test_some(verbose, fp, n);
412 else
413 success = test_all(verbose, fp);
414
415 if (fp)
416 fclose(fp);
417
418 LLVMShutdown();
419
420 return success ? 0 : 1;
421 }
422