xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/llvmpipe/lp_test_main.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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