Update starch to upstream commit f76162205fa082d4c9a75b89eb4295e03f5f68fd

This commit is contained in:
Oliver Jowett 2021-02-09 14:05:05 +08:00
parent 270c629515
commit fa80e7c917
8 changed files with 76 additions and 51 deletions

View File

@ -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

View File

@ -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 },

View File

@ -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 );

View File

@ -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:

View File

@ -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:

View File

@ -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) {

View File

@ -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

View File

@ -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);