Update starch to upstream commit f76162205fa082d4c9a75b89eb4295e03f5f68fd
This commit is contained in:
parent
270c629515
commit
fa80e7c917
|
|
@ -425,15 +425,15 @@ static void starch_benchmark_usage(const char *argv0)
|
|||
" (default: benchmark all functions)\n"
|
||||
"\n"
|
||||
"Supported flavors: "
|
||||
#ifdef STARCH_FLAVOR_GENERIC
|
||||
"generic "
|
||||
#endif
|
||||
#ifdef STARCH_FLAVOR_ARMV7A_VFPV3
|
||||
"armv7a_vfpv3 "
|
||||
#endif
|
||||
#ifdef STARCH_FLAVOR_ARMV7A_VFPV4
|
||||
"armv7a_vfpv4 "
|
||||
#endif
|
||||
#ifdef STARCH_FLAVOR_GENERIC
|
||||
"generic "
|
||||
#endif
|
||||
#ifdef STARCH_FLAVOR_X86_64_AVX
|
||||
"x86_64_avx "
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -73,12 +73,6 @@ void starch_subtract_n_set_wisdom (const char * const * received_wisdom)
|
|||
|
||||
starch_subtract_n_regentry starch_subtract_n_registry[] = {
|
||||
|
||||
#ifdef STARCH_MIX_GENERIC
|
||||
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
|
||||
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
|
||||
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
|
||||
#endif /* STARCH_MIX_GENERIC */
|
||||
|
||||
#ifdef STARCH_MIX_ARM
|
||||
{ 0, "neon_intrinsics_armv7a_vfpv4", "armv7a_vfpv4", starch_subtract_n_neon_intrinsics_armv7a_vfpv4, supports_neon_vfpv4 },
|
||||
{ 1, "neon_intrinsics_armv7a_vfpv3", "armv7a_vfpv3", starch_subtract_n_neon_intrinsics_armv7a_vfpv3, supports_neon_vfpv3 },
|
||||
|
|
@ -93,6 +87,12 @@ starch_subtract_n_regentry starch_subtract_n_registry[] = {
|
|||
{ 10, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
|
||||
#endif /* STARCH_MIX_ARM */
|
||||
|
||||
#ifdef STARCH_MIX_GENERIC
|
||||
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
|
||||
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
|
||||
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
|
||||
#endif /* STARCH_MIX_GENERIC */
|
||||
|
||||
#ifdef STARCH_MIX_X86_64
|
||||
{ 0, "generic_x86_64_avx2", "x86_64_avx2", starch_subtract_n_generic_x86_64_avx2, supports_x86_avx2 },
|
||||
{ 1, "generic_x86_64_avx", "x86_64_avx", starch_subtract_n_generic_x86_64_avx, supports_x86_avx },
|
||||
|
|
@ -161,12 +161,6 @@ void starch_subtract_n_aligned_set_wisdom (const char * const * received_wisdom)
|
|||
|
||||
starch_subtract_n_aligned_regentry starch_subtract_n_aligned_registry[] = {
|
||||
|
||||
#ifdef STARCH_MIX_GENERIC
|
||||
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
|
||||
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
|
||||
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
|
||||
#endif /* STARCH_MIX_GENERIC */
|
||||
|
||||
#ifdef STARCH_MIX_ARM
|
||||
{ 0, "generic_armv7a_vfpv4_aligned", "armv7a_vfpv4", starch_subtract_n_aligned_generic_armv7a_vfpv4, supports_neon_vfpv4 },
|
||||
{ 1, "unroll_4_armv7a_vfpv4_aligned", "armv7a_vfpv4", starch_subtract_n_aligned_unroll_4_armv7a_vfpv4, supports_neon_vfpv4 },
|
||||
|
|
@ -189,6 +183,12 @@ starch_subtract_n_aligned_regentry starch_subtract_n_aligned_registry[] = {
|
|||
{ 18, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
|
||||
#endif /* STARCH_MIX_ARM */
|
||||
|
||||
#ifdef STARCH_MIX_GENERIC
|
||||
{ 0, "generic_generic", "generic", starch_subtract_n_generic_generic, NULL },
|
||||
{ 1, "unroll_4_generic", "generic", starch_subtract_n_unroll_4_generic, NULL },
|
||||
{ 2, "bad_implementation_generic", "generic", starch_subtract_n_bad_implementation_generic, NULL },
|
||||
#endif /* STARCH_MIX_GENERIC */
|
||||
|
||||
#ifdef STARCH_MIX_X86_64
|
||||
{ 0, "generic_x86_64_avx2_aligned", "x86_64_avx2", starch_subtract_n_aligned_generic_x86_64_avx2, supports_x86_avx2 },
|
||||
{ 1, "unroll_4_x86_64_avx2_aligned", "x86_64_avx2", starch_subtract_n_aligned_unroll_4_x86_64_avx2, supports_x86_avx2 },
|
||||
|
|
|
|||
|
|
@ -5,12 +5,6 @@
|
|||
|
||||
/* mixes */
|
||||
|
||||
/* Generic build, compiler defaults only */
|
||||
#ifdef STARCH_MIX_GENERIC
|
||||
#define STARCH_FLAVOR_GENERIC
|
||||
#define STARCH_MIX_ALIGNMENT 1
|
||||
#endif /* STARCH_MIX_GENERIC */
|
||||
|
||||
/* ARM */
|
||||
#ifdef STARCH_MIX_ARM
|
||||
#define STARCH_FLAVOR_ARMV7A_VFPV4
|
||||
|
|
@ -19,6 +13,12 @@
|
|||
#define STARCH_MIX_ALIGNMENT 16
|
||||
#endif /* STARCH_MIX_ARM */
|
||||
|
||||
/* Generic build, compiler defaults only */
|
||||
#ifdef STARCH_MIX_GENERIC
|
||||
#define STARCH_FLAVOR_GENERIC
|
||||
#define STARCH_MIX_ALIGNMENT 1
|
||||
#endif /* STARCH_MIX_GENERIC */
|
||||
|
||||
/* x64-64 */
|
||||
#ifdef STARCH_MIX_X86_64
|
||||
#define STARCH_FLAVOR_X86_64_AVX2
|
||||
|
|
@ -71,14 +71,6 @@ void starch_subtract_n_aligned_set_wisdom( const char * const * received_wisdom
|
|||
|
||||
/* flavors and prototypes */
|
||||
|
||||
#ifdef STARCH_FLAVOR_GENERIC
|
||||
void starch_subtract_n_generic_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
void starch_subtract_n_unroll_4_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
void starch_subtract_n_bad_implementation_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
#endif /* STARCH_FLAVOR_GENERIC */
|
||||
|
||||
int starch_read_wisdom (const char * path);
|
||||
|
||||
#ifdef STARCH_FLAVOR_ARMV7A_VFPV3
|
||||
int supports_neon_vfpv3 (void);
|
||||
void starch_subtract_n_generic_armv7a_vfpv3 ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
|
|
@ -107,6 +99,14 @@ void starch_subtract_n_aligned_neon_intrinsics_armv7a_vfpv4 ( const uint16_t * a
|
|||
|
||||
int starch_read_wisdom (const char * path);
|
||||
|
||||
#ifdef STARCH_FLAVOR_GENERIC
|
||||
void starch_subtract_n_generic_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
void starch_subtract_n_unroll_4_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
void starch_subtract_n_bad_implementation_generic ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
#endif /* STARCH_FLAVOR_GENERIC */
|
||||
|
||||
int starch_read_wisdom (const char * path);
|
||||
|
||||
#ifdef STARCH_FLAVOR_X86_64_AVX
|
||||
int supports_x86_avx (void);
|
||||
void starch_subtract_n_generic_x86_64_avx ( const uint16_t * arg0, unsigned arg1, uint16_t arg2, uint16_t * arg3 );
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ import sys
|
|||
import re
|
||||
import os
|
||||
import mako.lookup
|
||||
from functools import total_ordering
|
||||
|
||||
from typing import Optional, Union, Iterable, Sequence, MutableSequence, Mapping, MutableMapping, FrozenSet
|
||||
from typing import Optional, Union, Iterable, Sequence, MutableSequence, Mapping, MutableMapping, FrozenSet, Dict, List
|
||||
|
||||
class Feature(object):
|
||||
"""Feature represents a type of code that can only be built with
|
||||
|
|
@ -35,7 +36,7 @@ themselves using the STARCH_IMPL_REQUIRES macro."""
|
|||
def macro(self) -> str:
|
||||
return 'STARCH_FEATURE_' + self.name.upper()
|
||||
|
||||
|
||||
@total_ordering
|
||||
class BuildFlavor(object):
|
||||
"""BuildFlavor models code built with specific compiler flags.
|
||||
Shared implementation code will be built multiple times, once per flavor.
|
||||
|
|
@ -89,7 +90,13 @@ intrinsics)"""
|
|||
def cflags(self) -> str:
|
||||
return ' '.join(self.compile_flags)
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if not isinstance(other, BuildFlavor):
|
||||
return NotImplemented
|
||||
return self.name < other.name
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Function(object):
|
||||
"""A user-callable function that will be dispatched to
|
||||
one of the many possible implementations based on runtime feature
|
||||
|
|
@ -175,6 +182,11 @@ support."""
|
|||
def benchmark_verify_symbol(self) -> str:
|
||||
return self.gen.sym(self.name + '_benchmark_verify')
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if not isinstance(other, Function):
|
||||
return NotImplemented
|
||||
return self.name < other.name
|
||||
|
||||
|
||||
class FunctionImpl(object):
|
||||
"""A possible implementation of a function, not built in any particular way yet."""
|
||||
|
|
@ -210,6 +222,7 @@ class FunctionImpl(object):
|
|||
return self.gen.sym(self.function.name + '_' + self.name + '_' + flavor.name)
|
||||
|
||||
|
||||
@total_ordering
|
||||
class SourceFile(object):
|
||||
"""A scanned source file that contains implementation code."""
|
||||
|
||||
|
|
@ -220,7 +233,13 @@ class SourceFile(object):
|
|||
self.path = path
|
||||
self.impls = []
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if not isinstance(other, SourceFile):
|
||||
return NotImplemented
|
||||
return self.path < other.path
|
||||
|
||||
|
||||
@total_ordering
|
||||
class BuildMix(object):
|
||||
"""A combination of build flavors that make up one possible way of building all
|
||||
the code. The output of a mix is a library that dispatches functions within the
|
||||
|
|
@ -254,6 +273,12 @@ specified first."""
|
|||
def function_wisdom(self, function) -> Sequence[str]:
|
||||
return self.wisdom.get(function, [])
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if not isinstance(other, BuildMix):
|
||||
return NotImplemented
|
||||
return self.name < other.name
|
||||
|
||||
|
||||
class Generator(object):
|
||||
functions: MutableMapping[str, Function]
|
||||
features: MutableMapping[str, Feature]
|
||||
|
|
@ -380,8 +405,8 @@ class Generator(object):
|
|||
return key
|
||||
return self.flavors[key]
|
||||
|
||||
def load_wisdom(self, path: str) -> Mapping[str,Sequence[str]]:
|
||||
results: Mapping[Function,Sequence[str]] = {}
|
||||
def load_wisdom(self, path: str) -> Mapping[Function,Sequence[str]]:
|
||||
results: Dict[Function,List[str]] = {}
|
||||
|
||||
try:
|
||||
f = open(path, 'r')
|
||||
|
|
@ -420,7 +445,7 @@ class Generator(object):
|
|||
if wisdom_file:
|
||||
resolved_wisdom = self.load_wisdom(wisdom_file)
|
||||
else:
|
||||
resolved_wisdom = dict( (self.get_function(name), values) for name,values in wisdom.items() )
|
||||
resolved_wisdom = dict( (self.get_function(name), list(values)) for name,values in wisdom.items() )
|
||||
self.mixes[name] = BuildMix(name, description, resolved_flavors, resolved_wisdom)
|
||||
|
||||
def sym(self, symbol: str) -> str:
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ static bool starch_benchmark_flavor_in_list(const char *flavor, const starch_ben
|
|||
}
|
||||
|
||||
<% functions_to_benchmark = [f for f in gen.functions.values() if f.benchmark] %>
|
||||
% for function in functions_to_benchmark:
|
||||
% for function in sorted(functions_to_benchmark):
|
||||
/* prototypes for benchmark helpers provided by user code */
|
||||
void ${function.benchmark_symbol} (void);
|
||||
% if function.benchmark_verify:
|
||||
|
|
@ -252,7 +252,7 @@ static void starch_benchmark_run_${function.name}( ${function.declaration_arglis
|
|||
#define STARCH_BENCHMARK_ALLOC(_count, _type) ((_type *) starch_benchmark_aligned_alloc(1, alignof(_type), (_count) * sizeof(_type)))
|
||||
#define STARCH_BENCHMARK_FREE(_ptr) starch_benchmark_aligned_free(_ptr)
|
||||
|
||||
% for source in gen.benchmark_files:
|
||||
% for source in sorted(gen.benchmark_files):
|
||||
#include "${os.path.relpath(source.path, current_dir)}"
|
||||
% endfor
|
||||
|
||||
|
|
@ -278,13 +278,13 @@ static void starch_benchmark_run_${function.name}( ${function.declaration_arglis
|
|||
#define STARCH_BENCHMARK_ALLOC(_count, _type) ((_type *) starch_benchmark_aligned_alloc(STARCH_MIX_ALIGNMENT, alignof(_type), (_count) * sizeof(_type)))
|
||||
#define STARCH_BENCHMARK_FREE(_ptr) starch_benchmark_aligned_free(_ptr)
|
||||
|
||||
% for source in gen.benchmark_files:
|
||||
% for source in sorted(gen.benchmark_files):
|
||||
% if any( (function.aligned and function.benchmark == source) for function in gen.functions.values() ):
|
||||
#include "${os.path.relpath(source.path, current_dir)}"
|
||||
% endif
|
||||
% endfor
|
||||
|
||||
% for function in functions_to_benchmark:
|
||||
% for function in sorted(functions_to_benchmark):
|
||||
static void starch_benchmark_all_${function.name}(void)
|
||||
{
|
||||
fprintf(stderr, "==== ${function.name} ===\n");
|
||||
|
|
@ -330,14 +330,14 @@ static void starch_benchmark_usage(const char *argv0)
|
|||
" (default: benchmark all functions)\n"
|
||||
"\n"
|
||||
"Supported flavors: "
|
||||
% for flavor in gen.flavors.values():
|
||||
% for flavor in sorted(gen.flavors.values()):
|
||||
#ifdef ${flavor.macro}
|
||||
"${flavor.name} "
|
||||
#endif
|
||||
% endfor
|
||||
"\n"
|
||||
"Supported functions: "
|
||||
% for function in gen.functions.values():
|
||||
% for function in sorted(gen.functions.values()):
|
||||
"${function.name} "
|
||||
% endfor
|
||||
"\n", argv0);
|
||||
|
|
@ -425,7 +425,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
for (int i = optind; i < argc; ++i) {
|
||||
% for function in gen.functions.values():
|
||||
% for function in sorted(gen.functions.values()):
|
||||
if (!strcmp(argv[i], "${function.name}")) {
|
||||
specific = 1;
|
||||
% if function.benchmark:
|
||||
|
|
@ -443,7 +443,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (!specific) {
|
||||
% for function in gen.functions.values():
|
||||
% for function in sorted(gen.functions.values()):
|
||||
% if function.benchmark:
|
||||
starch_benchmark_all_${function.name}();
|
||||
% else:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ static int starch_regentry_rank_compare (const void *l, const void *r)
|
|||
return left->rank - right->rank;
|
||||
}
|
||||
|
||||
% for function in gen.functions.values():
|
||||
% for function in sorted(gen.functions.values()):
|
||||
/* dispatcher / registry for ${function.name} */
|
||||
|
||||
${function.regentry_type} * ${function.select_symbol}() {
|
||||
|
|
@ -80,7 +80,7 @@ void ${function.set_wisdom_symbol} (const char * const * received_wisdom)
|
|||
}
|
||||
|
||||
${function.regentry_type} ${function.registry_symbol}[] = {
|
||||
% for mix in gen.mixes.values():
|
||||
% for mix in sorted(gen.mixes.values()):
|
||||
<%
|
||||
# gather all implementations for this mix, sort by wisdom
|
||||
def rank_key(value, wisdom=mix.function_wisdom(function)):
|
||||
|
|
@ -128,7 +128,7 @@ int ${gen.sym("read_wisdom")} (const char * path)
|
|||
return -1;
|
||||
|
||||
/* reset all ranks to identify entries not listed in the wisdom file; we'll assign ranks at the end to produce a stable sort */
|
||||
% for function in gen.functions.values():
|
||||
% for function in sorted(gen.functions.values()):
|
||||
int rank_${function.name} = 0;
|
||||
for (${function.regentry_type} *entry = ${function.registry_symbol}; entry->name; ++entry) {
|
||||
entry->rank = 0;
|
||||
|
|
@ -167,7 +167,7 @@ int ${gen.sym("read_wisdom")} (const char * path)
|
|||
*end = 0;
|
||||
|
||||
/* try to find a matching registry entry */
|
||||
% for function in gen.functions.values():
|
||||
% for function in sorted(gen.functions.values()):
|
||||
if (!strcmp(name, "${function.name}")) {
|
||||
for (${function.regentry_type} *entry = ${function.registry_symbol}; entry->name; ++entry) {
|
||||
if (!strcmp(impl, entry->name)) {
|
||||
|
|
@ -188,7 +188,7 @@ int ${gen.sym("read_wisdom")} (const char * path)
|
|||
fclose(fp);
|
||||
|
||||
/* assign ranks to unmatched items to (stable) sort them last; re-sort everything */
|
||||
% for function in gen.functions.values():
|
||||
% for function in sorted(gen.functions.values()):
|
||||
{
|
||||
${function.regentry_type} *entry;
|
||||
for (entry = ${function.registry_symbol}; entry->name; ++entry) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#define STARCH_IMPL(_function,_impl) ${gen.symbol_prefix} ## _function ## _ ## _impl ## _ ## ${flavor.name}
|
||||
#define STARCH_IMPL_REQUIRES(_function,_impl,_feature) STARCH_IMPL(_function,_impl)
|
||||
|
||||
% for source in gen.impl_files:
|
||||
% for source in sorted(gen.impl_files):
|
||||
% if any( ((impl.feature is None or impl.feature in flavor.features) and not impl.function.aligned) for impl in source.impls):
|
||||
#include "${os.path.relpath(source.path, current_dir)}"
|
||||
% endif
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
#define STARCH_IMPL(_function,_impl) ${gen.symbol_prefix} ## _function ## _aligned_ ## _impl ## _ ## ${flavor.name}
|
||||
#define STARCH_IMPL_REQUIRES(_function,_impl,_feature) STARCH_IMPL(_function,_impl)
|
||||
|
||||
% for source in gen.impl_files:
|
||||
% for source in sorted(gen.impl_files):
|
||||
% if any( ((impl.feature is None or impl.feature in flavor.features) and impl.function.aligned) for impl in source.impls):
|
||||
#include "${os.path.relpath(source.path, current_dir)}"
|
||||
% endif
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
/* mixes */
|
||||
|
||||
% for mix in gen.mixes.values():
|
||||
% for mix in sorted(gen.mixes.values()):
|
||||
/* ${mix.description} */
|
||||
#ifdef ${mix.macro}
|
||||
% for flavor in mix.flavors:
|
||||
|
|
@ -51,7 +51,7 @@ void ${function.set_wisdom_symbol}( const char * const * received_wisdom );
|
|||
% endfor
|
||||
/* flavors and prototypes */
|
||||
|
||||
% for flavor in gen.flavors.values():
|
||||
% for flavor in sorted(gen.flavors.values()):
|
||||
#ifdef ${flavor.macro}
|
||||
% if flavor.test_function is not None:
|
||||
int ${flavor.test_function} (void);
|
||||
|
|
|
|||
Loading…
Reference in New Issue