Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1374 from mesonbuild/simd
Add support for SIMD detection
- Loading branch information
Showing
25 changed files
with
879 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Unstable SIMD module | ||
|
||
This module provides helper functionality to build code with SIMD instructions. | ||
Available since 0.42.0. | ||
|
||
**Note**: this module is unstable. It is only provided as a technology preview. | ||
Its API may change in arbitrary ways between releases or it might be removed | ||
from Meson altogether. | ||
|
||
## Usage | ||
|
||
This module is designed for the use case where you have an algorithm with one | ||
or more SIMD implementation and you choose which one to use at runtime. | ||
|
||
The module provides one method, `check`, which is used like this: | ||
|
||
rval = simd.check('mysimds', | ||
mmx : 'simd_mmx.c', | ||
sse : 'simd_sse.c', | ||
sse2 : 'simd_sse2.c', | ||
sse3 : 'simd_sse3.c', | ||
ssse3 : 'simd_ssse3.c', | ||
sse41 : 'simd_sse41.c', | ||
sse42 : 'simd_sse42.c', | ||
avx : 'simd_avx.c', | ||
avx2 : 'simd_avx2.c', | ||
neon : 'simd_neon.c', | ||
compiler : cc) | ||
|
||
Here the individual files contain the accelerated versions of the functions | ||
in question. The `compiler` keyword argument takes the compiler you are | ||
going to use to compile them. The function returns an array with two values. | ||
The first value is a bunch of libraries that contain the compiled code. Any | ||
SIMD code that the compiler can't compile (for example, Neon instructions on | ||
an x86 machine) are ignored. You should pass this value to the desired target | ||
using `link_with`. The second value is a `configuration_data` object that | ||
contains true for all the values that were supported. For example if the | ||
compiler did support sse2 instructions, then the object would have `HAVE_SSE2` | ||
set to 1. | ||
|
||
Generating code to detect the proper instruction set at runtime is | ||
straightforward. First you create a header with the configuration object and | ||
then a chooser function that looks like this: | ||
|
||
void (*fptr)(type_of_function_here) = NULL; | ||
|
||
#if HAVE_NEON | ||
if(fptr == NULL && neon_available()) { | ||
fptr = neon_accelerated_function; | ||
} | ||
#endif | ||
#if HAVE_AVX2 | ||
if(fptr == NULL && avx2_available()) { | ||
fptr = avx_accelerated_function; | ||
} | ||
#endif | ||
|
||
... | ||
|
||
if(fptr == NULL) { | ||
fptr = default_function; | ||
} | ||
|
||
Each source file provides two functions, the `xxx_available` function to query | ||
whether the CPU currently in use supports the instruction set and | ||
`xxx_accelerated_function` that is the corresponding accelerated | ||
implementation. | ||
|
||
At the end of this function the function pointer points to the fastest | ||
available implementation and can be invoked to do the computation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Copyright 2017 The Meson development team | ||
|
||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
|
||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from .. import mesonlib, compilers, mlog | ||
|
||
from . import ExtensionModule | ||
|
||
class SimdModule(ExtensionModule): | ||
|
||
def __init__(self): | ||
super().__init__() | ||
self.snippets.add('check') | ||
# FIXME add Altivec and AVX512. | ||
self.isets = ('mmx', | ||
'sse', | ||
'sse2', | ||
'sse3', | ||
'ssse3', | ||
'sse41', | ||
'sse42', | ||
'avx', | ||
'avx2', | ||
'neon', | ||
) | ||
|
||
def check(self, interpreter, state, args, kwargs): | ||
result = [] | ||
if len(args) != 1: | ||
raise mesonlib.MesonException('Check requires one argument, a name prefix for checks.') | ||
prefix = args[0] | ||
if not isinstance(prefix, str): | ||
raise mesonlib.MesonException('Argument must be a string.') | ||
if 'compiler' not in kwargs: | ||
raise mesonlib.MesonException('Must specify compiler keyword') | ||
compiler = kwargs['compiler'].compiler | ||
if not isinstance(compiler, compilers.compilers.Compiler): | ||
raise mesonlib.MesonException('Compiler argument must be a compiler object.') | ||
cdata = interpreter.func_configuration_data(None, [], {}) | ||
conf = cdata.held_object | ||
for iset in self.isets: | ||
if iset not in kwargs: | ||
continue | ||
iset_fname = kwargs[iset] # Migth also be an array or Files. static_library will validate. | ||
args = compiler.get_instruction_set_args(iset) | ||
if args is None: | ||
mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) | ||
continue | ||
if len(args) > 0: | ||
if not compiler.has_multi_arguments(args, state.environment): | ||
mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) | ||
continue | ||
mlog.log('Compiler supports %s:' % iset, mlog.green('YES')) | ||
conf.values['HAVE_' + iset.upper()] = ('1', 'Compiler supports %s.' % iset) | ||
libname = prefix + '_' + iset | ||
lib_kwargs = {'sources': iset_fname, | ||
compiler.get_language() + '_args': args} | ||
result.append(interpreter.func_static_lib(None, [libname], lib_kwargs)) | ||
return [result, cdata] | ||
|
||
def initialize(): | ||
return SimdModule() |
Oops, something went wrong.