Update contrib.
2 * LIBOIL - Library of Optimized Inner Loops
3 * Copyright (c) 2003,2004 David A. Schleef <ds@schleef.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.
27 //Portions Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
32 #include <liboil/liboildebug.h>
33 #include <liboil/liboilcpu.h>
34 #include <liboil/liboilfault.h>
35 #include <liboil/liboiltest.h>
43 * SECTION:liboilclass-unstable
44 * @title:OilFunctionClass
45 * @short_description: Functions for manipulating function classes
48 * Functions operate on arrays of data. The arrays can be either source
49 * arrays (input only), destination arrays (output only), or in-place
50 * arrays (both input and output).
54 * The interpretation of a parameter can usually be determined from its
55 * name. Parameters for arrays are of the form d1_1xn, where the first
56 * character represents the direction (source, destination, or in-place),
57 * the second represents the index for that particular direction, and
58 * the characters after the underscore indicate the size of the array.
59 * In this case, "1xn" represents an array that is 1 by N. Note that
60 * the index and the size can both be omitted, giving a default of 1
61 * for the index and 1xn for the size.
65 * Parameters that represent strides are of the form "d1s". The
66 * interpretation is similar to above, except that the s indicates
71 * The exceptions to the above rule are "dest", "src", "dstr", "sstr", etc.
72 * These are aliases for "d1", "s1", "d1s", and "s1s", respectively. This
73 * form is deprecated and will be removed in the 0.4 series.
77 * Two special parameters are "n" and "m", which determine the size of
78 * the arrays in other parameters.
82 * Data arrays are laid out such that rows are separated by the number
83 * of bytes given by the corresponding stride. Elements in each row
84 * are contiguous. If there is no stride parameter corresponding to an
85 * array, the rows of the array are contiguous.
90 * SECTION:liboilimpl-unstable
91 * @title:OilFunctionImpl
92 * @short_description: Functions for manipulating function implementations.
97 extern OilFunctionClass *_oil_function_class_array[];
98 extern OilFunctionImpl *_oil_function_impl_array[];
100 extern OilFunctionClass** __oil_function_class_array(void);
101 extern OilFunctionImpl** __oil_function_impl_array(void);
102 #define _oil_function_class_array ((OilFunctionClass **)(__oil_function_class_array()))
103 #define _oil_function_impl_array ((OilFunctionImpl **)(__oil_function_impl_array()))
104 extern void init(void);
105 extern void init_impl(void);
109 static int _oil_n_function_impls;
110 static int _oil_n_function_classes;
112 static void oil_init_pointers (void);
113 static void oil_init_structs (void);
115 static char * xstrdup (const char *s);
117 void _oil_cpu_init (void);
121 * @title: Intialization
122 * @short_description: Initialization functions
125 * SECTION:liboilinit-unstable
126 * @title: Intialization
127 * @short_description: Initialization functions
132 * Initialize liboil. This function must be called before any
133 * other liboil function is used. oil_init() may be called multiple
138 static int _oil_inited = 0;
147 if (_oil_inited) return;
159 oil_init_pointers ();
164 OIL_INFO ("oil_init() finished");
168 * oil_init_no_optimize:
170 * Initialize liboil similar to oil_init(), but do not run the
171 * profiling stage. This function is mainly useful for internal
178 oil_init_no_optimize (void)
180 if (_oil_inited) return;
187 oil_init_pointers ();
194 * Optimize all function classes.
200 oil_optimize_all (void)
202 OilFunctionClass *klass;
205 oil_fault_check_enable ();
206 for (i = 0; i < _oil_n_function_classes; i++) {
207 klass = oil_class_get_by_index (i);
209 oil_class_optimize (klass);
211 OIL_INFO("%d classes, %d implementations, %d enabled",
212 _oil_n_function_classes, _oil_n_function_impls, 0);
213 oil_fault_check_disable ();
218 * @class_name: a string
220 * Optimize the function class that has the name specified by @class_name.
226 oil_optimize (const char *class_name)
228 OilFunctionClass *klass;
230 klass = oil_class_get (class_name);
232 OIL_ERROR ("could not find class %s", class_name);
236 oil_class_optimize (klass);
240 * oil_class_get_n_classes:
242 * Returns the number of function classes.
244 * Returns: the number of function classes
250 oil_class_get_n_classes (void)
252 return _oil_n_function_classes;
256 * oil_class_get_by_index:
259 * Returns a pointer to the function class with index @i.
261 * Returns: an @OilFunctionClass
268 oil_class_get_by_index (int i)
270 if (i<0 || i>=_oil_n_function_classes) return NULL;
272 return _oil_function_class_array[i];
276 * oil_impl_is_runnable:
277 * @impl: an @OilFunctionImpl
279 * Determines whether the function implementation given by @impl
280 * can be executed by the current CPU.
282 * Returns: 1 if the implementation can be executed, otherwise 0
288 oil_impl_is_runnable (OilFunctionImpl *impl)
290 unsigned int oil_cpu_flags = oil_cpu_get_flags();
292 if ((impl->flags & OIL_CPU_FLAG_MASK) & (~oil_cpu_flags))
297 //#ifdef __SYMBIAN32__
298 //EXPORT_C unsigned long _oil_cpu_flags()
300 //return &oil_cpu_flags;
305 * oil_impl_is_usable:
306 * @impl: an @OilFunctionImpl
308 * Determines whether the function implementation given by @impl
309 * is useful, that is, it can be executed on the current CPU and
312 * Returns: 1 if the implementation can be used, otherwise 0
318 oil_impl_is_usable (OilFunctionImpl *impl)
320 unsigned int oil_cpu_flags = oil_cpu_get_flags();
322 if ((impl->flags & OIL_CPU_FLAG_MASK) & (~oil_cpu_flags))
324 if (impl->flags & OIL_IMPL_FLAG_DISABLED)
330 * oil_impl_get_by_index:
333 * Returns a pointer to the function implementation with index @i.
335 * Returns: a pointer to a function implementation structure
341 oil_impl_get_by_index (int i)
343 if (i<0 || i>=_oil_n_function_impls) return NULL;
345 return _oil_function_impl_array[i];
350 * @class_name: the name of the function class
352 * Returns a pointer to the function class that has the given class
353 * name. If no such class is found, NULL is returned.
355 * Returns: a pointer to a function class
361 oil_class_get (const char *class_name)
363 OilFunctionClass *klass;
366 for (i = 0; i < _oil_n_function_classes; i++) {
367 klass = oil_class_get_by_index (i);
369 if (strcmp (klass->name, class_name) == 0)
376 * oil_class_choose_by_name:
377 * @klass: a function class
378 * @name: the name of an implementation
380 * Sets the chosen implementation for the given function class to
381 * the implementation with the given name. If no implementation
382 * having the given name is found, the chosen implementation is
389 oil_class_choose_by_name (OilFunctionClass * klass, const char *name)
391 OilFunctionImpl *impl;
393 for(impl = klass->first_impl; impl; impl = impl->next) {
394 if (impl->name && strcmp (impl->name, name) == 0) {
395 klass->chosen_impl = impl;
396 klass->func = impl->func;
403 * oil_class_optimize:
404 * @klass: a function class
406 * Tests and profiles each implementation for the given function
407 * class. Testing compares the output of running each implementation
408 * on random input against the reference implementation for the
415 oil_class_optimize (OilFunctionClass * klass)
417 OilFunctionImpl *impl;
418 OilFunctionImpl *min_impl;
422 OIL_DEBUG ("optimizing class %s", klass->name);
424 if (klass->reference_impl == NULL) {
425 OIL_ERROR ("class %s has no reference implmentation", klass->name);
428 if (klass->first_impl == NULL) {
429 OIL_ERROR ("class %s has no implmentations", klass->name);
433 test = oil_test_new (klass);
435 OIL_ERROR ("failed to test function class %s", klass->name);
440 for (impl = klass->first_impl; impl; impl = impl->next) {
441 OIL_LOG ("testing impl %s", impl->name);
442 if (!oil_impl_is_runnable (impl))
445 ret = oil_test_check_impl (test, impl);
447 impl->profile_ave = test->profile_ave;
448 impl->profile_std = test->profile_std;
449 OIL_LOG ("impl %s ave=%g std=%g", impl->name, impl->profile_ave,
451 if (min_impl == NULL) {
454 if (impl->profile_ave < min_impl->profile_ave) {
459 OIL_WARNING("disabling implementation %s", impl->name);
460 impl->profile_ave = test->profile_ave;
461 impl->profile_std = test->profile_std;
462 impl->flags |= OIL_IMPL_FLAG_DISABLED;
465 if (min_impl == NULL) {
466 OIL_ERROR ("failed to find optimal implementation for class %s",
471 OIL_DEBUG("choosing implementation %s", min_impl->name);
472 klass->chosen_impl = min_impl;
473 klass->func = min_impl->func;
475 oil_test_free (test);
479 oil_init_pointers (void)
483 for(i=0;_oil_function_class_array[i];i++) {
484 _oil_n_function_classes++;
487 for(i=0;_oil_function_impl_array[i];i++) {
488 _oil_n_function_impls++;
494 oil_init_structs (void)
497 OilFunctionImpl *impl;
499 for (i = 0; i < _oil_n_function_impls; i++) {
500 impl = oil_impl_get_by_index (i);
501 OIL_LOG ("registering impl %p (%s)", impl,
502 (impl->name != NULL) ? impl->name : "NULL");
503 if (impl->klass == NULL) {
504 OIL_ERROR ("impl->klass is NULL for impl %p (%s)", impl,
505 (impl->name != NULL) ? impl->name : "NULL");
508 impl->next = impl->klass->first_impl;
509 impl->klass->first_impl = impl;
510 if (impl->flags & OIL_IMPL_FLAG_REF) {
511 impl->klass->reference_impl = impl;
512 impl->klass->chosen_impl = impl;
513 impl->klass->func = impl->func;
519 * oil_class_register_impl_by_name:
520 * @klass_name: the name of the class
521 * @impl: an implementation
523 * Adds @impl to the list of implementations associated with
524 * the function class given by @klass_name.
530 oil_class_register_impl_by_name (const char *klass_name, OilFunctionImpl *impl)
532 OilFunctionClass *klass;
534 klass = oil_class_get (klass_name);
535 if (klass == NULL) return;
537 oil_class_register_impl (klass, impl);
541 * oil_class_register_impl:
543 * @impl: an implementation
545 * Adds @impl to the list of implementations associated with
546 * the function class given by @klass.
552 oil_class_register_impl (OilFunctionClass *klass, OilFunctionImpl *impl)
555 impl->next = impl->klass->first_impl;
556 klass->first_impl = impl;
557 if (impl->flags & OIL_IMPL_FLAG_REF) {
558 impl->klass->reference_impl = impl;
559 impl->klass->chosen_impl = impl;
560 impl->klass->func = impl->func;
565 * oil_class_register_impl_full:
567 * @func: the function
568 * @name: name of the function
571 * Adds @func to the list of implementations associated with
572 * the function class given by @klass.
578 oil_class_register_impl_full (OilFunctionClass *klass,
579 void (*func)(void), const char *name, unsigned int flags)
581 OilFunctionImpl *impl;
583 impl = malloc(sizeof(OilFunctionImpl));
584 memset (impl, 0, sizeof(OilFunctionImpl));
586 impl->func = (void*)func;
588 impl->name = xstrdup(name);
590 oil_class_register_impl(klass,impl);
594 xstrdup (const char *s)