2 * Copyright (c) 2004 David A. Schleef <ds@schleef.org>
3 * Copyright (c) 2005 Eric Anholt <anholt@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
33 #include <liboil/liboil.h>
38 #ifdef HAVE_INTTYPES_H
42 #include <liboil/liboilprototype.h>
43 #include <liboil/liboiltest.h>
44 #include <liboil/liboilcpu.h>
48 /* Amount by which results of different types are allowed to deviate from the
52 #define FLOAT_EPSILON 0.0001
55 dump_array (void *data, void *ref_data, OilType type, int pre_n, int stride,
59 int s2 = oil_type_sizeof (type);
62 #define DUMP(type, format, int) do { \
63 for(i=0;i<post_n;i++){ \
64 float epsilon = (int) ? INT_EPSILON : FLOAT_EPSILON; \
66 for(j=0;j<pre_n;j++){ \
67 x = fabs(OIL_GET(data, i*stride + j*s2, type) - \
68 OIL_GET(ref_data, i*stride + j*s2, type)); \
70 printf("*" format "* (" format ") ", \
71 OIL_GET(data, i*stride + j*s2, type), \
72 OIL_GET(ref_data, i*stride + j*s2, type)); \
74 printf(" " format " ", OIL_GET(data, i*stride + j*s2, type)); \
84 DUMP(int8_t, "0x%02" PRIx8, 1);
88 DUMP(uint16_t, "0x%04" PRIx16, 1);
92 DUMP(uint32_t, "0x%08" PRIx32, 1);
99 DUMP(uint64_t, "0x%016" PRIx64, 1);
102 DUMP(double, "%g", 0);
110 dump_source (OilTest *test)
113 for(i=0;i<OIL_ARG_LAST;i++){
114 OilParameter *p = &test->params[i];
116 if (p->direction == 'i' || p->direction == 's') {
117 printf (" %s:\n", p->parameter_name);
118 dump_array (p->src_data + p->test_header,
119 p->src_data + p->test_header,
120 p->type, p->pre_n, p->stride, p->post_n);
127 dump_dest_ref (OilTest *test)
130 for(i=0;i<OIL_ARG_LAST;i++){
131 OilParameter *p = &test->params[i];
133 if (p->direction == 'd') {
134 printf (" %s:\n", p->parameter_name);
135 dump_array (p->ref_data + p->test_header,
136 p->ref_data + p->test_header,
137 p->type, p->pre_n, p->stride, p->post_n);
144 test_difference (void *data, void *ref_data, OilType type, int pre_n, int stride,
148 int s2 = oil_type_sizeof (type);
151 #define CHECK(type, is_int) do { \
152 float epsilon = (is_int) ? INT_EPSILON : FLOAT_EPSILON; \
153 for(i=0;i<post_n;i++){ \
154 for(j=0;j<pre_n;j++){ \
155 x = fabs(OIL_GET(data, i*stride + j*s2, type) - \
156 OIL_GET(ref_data, i*stride + j*s2, type)); \
202 check_test (OilTest *test)
205 for(i=0;i<OIL_ARG_LAST;i++){
206 OilParameter *p = &test->params[i];
208 if (p->direction == 'i' || p->direction == 'd') {
209 if (!test_difference(p->test_data + p->test_header,
210 p->ref_data + p->test_header,
211 p->type, p->pre_n, p->stride, p->post_n))
213 printf (" Failure in %s (marked by *, ref in ()):\n",
215 dump_array (p->test_data + p->test_header,
216 p->ref_data + p->test_header,
217 p->type, p->pre_n, p->stride, p->post_n);
225 void print_align(void *ptr)
229 if (verbose)printf("stack addr %p\n", &i);
232 OilFunctionClass *realign_klass;
236 void realign(int align)
240 __asm__ __volatile__ (
241 " sub %%edi, %%esp\n"
242 #ifdef HAVE_SYMBOL_UNDERSCORE
243 " call _check_class_with_alignment\n"
245 " call check_class_with_alignment\n"
247 " add %%edi, %%esp\n"
252 __asm__ __volatile__ (
253 " sub %%rbx, %%rsp\n"
254 #ifdef HAVE_SYMBOL_UNDERSCORE
255 " call _check_class_with_alignment\n"
257 " call check_class_with_alignment\n"
259 " add %%rbx, %%rsp\n"
266 void check_class_with_alignment (void)
268 OilFunctionClass *klass = realign_klass;
269 int align = realign_align;
272 OilFunctionImpl *impl;
274 test = oil_test_new(klass);
276 oil_test_set_iterations(test, 1);
279 impl = klass->reference_impl;
280 oil_test_check_impl (test, impl);
282 for (impl = klass->first_impl; impl; impl = impl->next) {
283 if (impl == klass->reference_impl)
285 if (oil_impl_is_runnable (impl)) {
286 if (!oil_test_check_impl (test, impl)) {
287 printf ("impl %s with align %d\n", impl->name, align);
288 printf("dests for %s:\n", klass->name);
290 printf("sources for %s:\n", klass->name);
297 realign_return = test_failed;
300 int check_class(OilFunctionClass *klass)
307 oil_class_optimize (klass);
309 if(verbose) printf("checking class %s\n", klass->name);
311 test = oil_test_new(klass);
317 for (align = 0; align <= 32; align += step) {
318 printf(" alignment %d\n", align);
319 realign_klass = klass;
320 realign_align = align;
322 failed |= realign_return;
324 oil_test_free (test);
329 int main (int argc, char *argv[])
337 /* the dynamic loader on MacOS/X crashes if someone unaligns the stack, so it's
338 unlikely that any code gets away with doing it. Our test code doesn't get
339 away with it either, so we'll just bail out. */
343 n = oil_class_get_n_classes ();
344 for (i = 0; i < n; i++) {
345 OilFunctionClass *klass = oil_class_get_by_index(i);
346 failed |= check_class(klass);