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