diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2017-07-19 15:50:04 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-19 15:50:04 +0300 |
commit | e89b6cdd1037d4c7cfdcb37555f2cbaf66f6ae05 (patch) | |
tree | e812ee63ecf54b37d17611e8514c5223ff058e47 /mesonbuild | |
parent | acb7e3aaa0a006b36ad8fb86527e46c3b17ff70c (diff) | |
parent | c8981ff111ccb2419c8689dadc567760e0a20750 (diff) | |
download | meson-e89b6cdd1037d4c7cfdcb37555f2cbaf66f6ae05.zip meson-e89b6cdd1037d4c7cfdcb37555f2cbaf66f6ae05.tar.gz meson-e89b6cdd1037d4c7cfdcb37555f2cbaf66f6ae05.tar.bz2 |
Merge pull request #1374 from mesonbuild/simd
Add support for SIMD detection
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/compilers/c.py | 17 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 52 | ||||
-rw-r--r-- | mesonbuild/compilers/cpp.py | 4 | ||||
-rw-r--r-- | mesonbuild/environment.py | 6 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 15 | ||||
-rw-r--r-- | mesonbuild/modules/unstable_simd.py | 72 |
6 files changed, 161 insertions, 5 deletions
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index cf9d1ee..593366a 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -25,6 +25,8 @@ from .compilers import ( msvc_buildtype_args, msvc_buildtype_linker_args, msvc_winlibs, + vs32_instruction_set_args, + vs64_instruction_set_args, ClangCompiler, Compiler, CompilerArgs, @@ -810,7 +812,7 @@ class VisualStudioCCompiler(CCompiler): std_warn_args = ['/W3'] std_opt_args = ['/O2'] - def __init__(self, exelist, version, is_cross, exe_wrap): + def __init__(self, exelist, version, is_cross, exe_wrap, is_64): CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) self.id = 'msvc' # /showIncludes is needed for build dependency tracking in Ninja @@ -820,6 +822,7 @@ class VisualStudioCCompiler(CCompiler): '2': ['/W3'], '3': ['/W4']} self.base_options = ['b_pch'] # FIXME add lto, pgo and the like + self.is_64 = is_64 # Override CCompiler.get_always_args def get_always_args(self): @@ -1005,3 +1008,15 @@ class VisualStudioCCompiler(CCompiler): if not isinstance(args, list): args = [args] return ['/WHOLEARCHIVE:' + x for x in args] + + def get_instruction_set_args(self, instruction_set): + if self.is_64: + return vs64_instruction_set_args.get(instruction_set, None) + if self.version.split('.')[0] == '16' and instruction_set == 'avx': + # VS documentation says that this exists and should work, but + # it does not. The headers do not contain AVX intrinsics + # and the can not be called. + return None + return vs32_instruction_set_args.get(instruction_set, None) + + diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index a8ec5e3..0be3908 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -228,6 +228,43 @@ base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled he True), } +gnulike_instruction_set_args = {'mmx': ['-mmmx'], + 'sse': ['-msse'], + 'sse2': ['-msse2'], + 'sse3': ['-msse3'], + 'ssse3': ['-mssse3'], + 'sse41': ['-msse4.1'], + 'sse42': ['-msse4.2'], + 'avx': ['-mavx'], + 'avx2': ['-mavx2'], + 'neon': ['-mfpu=neon'], + } + +vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX + 'sse': ['/arch:SSE'], + 'sse2': ['/arch:SSE2'], + 'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX. + 'sse41': ['/arch:AVX'], + 'sse42': ['/arch:AVX'], + 'avx': ['/arch:AVX'], + 'avx2': ['/arch:AVX2'], + 'neon': None, +} + +# The 64 bit compiler defaults to /arch:avx. +vs64_instruction_set_args = {'mmx': ['/arch:AVX'], + 'sse': ['/arch:AVX'], + 'sse2': ['/arch:AVX'], + 'sse3': ['/arch:AVX'], + 'ssse3': ['/arch:AVX'], + 'sse41': ['/arch:AVX'], + 'sse42': ['/arch:AVX'], + 'avx': ['/arch:AVX'], + 'avx2': ['/arch:AVX2'], + 'neon': None, + } + + def sanitizer_compile_args(value): if value == 'none': return [] @@ -755,6 +792,12 @@ class Compiler: return [] raise EnvironmentException('Language %s does not support linking whole archives.' % self.get_display_language()) + # Compiler arguments needed to enable the given instruction set. + # May be [] meaning nothing needed or None meaning the given set + # is not supported. + def get_instruction_set_args(self, instruction_set): + return None + def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): if not rpath_paths and not install_rpath: return [] @@ -933,6 +976,10 @@ class GnuCompiler: return ['-mwindows'] return [] + def get_instruction_set_args(self, instruction_set): + return gnulike_instruction_set_args.get(instruction_set, None) + + class ClangCompiler: def __init__(self, clang_type): self.id = 'clang' @@ -983,7 +1030,7 @@ class ClangCompiler: def has_multi_arguments(self, args, env): return super().has_multi_arguments( - ['-Werror=unknown-warning-option'] + args, + ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'] + args, env) def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None): @@ -1010,6 +1057,9 @@ class ClangCompiler: return result return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive'] + def get_instruction_set_args(self, instruction_set): + return gnulike_instruction_set_args.get(instruction_set, None) + # Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1 class IntelCompiler: diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 01525b0..a8fc8a3 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -173,10 +173,10 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler): class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): - def __init__(self, exelist, version, is_cross, exe_wrap): + def __init__(self, exelist, version, is_cross, exe_wrap, is_64): self.language = 'cpp' CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) - VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap, is_64) self.base_options = ['b_pch'] # FIXME add lto, pgo and the like def get_options(self): diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index a6da3f9..dd9f56e 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -534,8 +534,12 @@ class Environment: # Visual Studio prints version number to stderr but # everything else to stdout. Why? Lord only knows. version = search_version(err) + if not err or not err.split('\n')[0]: + m = 'Failed to detect MSVC compiler arch: stderr was\n{!r}' + raise EnvironmentException(m.format(err)) + is_64 = err.split('\n')[0].endswith(' x64') cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler - return cls(compiler, version, is_cross, exe_wrap) + return cls(compiler, version, is_cross, exe_wrap, is_64) if '(ICC)' in out: # TODO: add microsoft add check OSX inteltype = ICC_STANDARD diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 63cdf9e..359dd17 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -161,6 +161,7 @@ class ConfigurationDataHolder(MutableInterpreterObject): 'set_quoted': self.set_quoted_method, 'has': self.has_method, 'get': self.get_method, + 'merge_from': self.merge_from_method, }) def is_used(self): @@ -221,6 +222,16 @@ class ConfigurationDataHolder(MutableInterpreterObject): def keys(self): return self.held_object.values.keys() + def merge_from_method(self, args, kwargs): + if len(args) != 1: + raise InterpreterException('Merge_from takes one positional argument.') + from_object = args[0] + if not isinstance(from_object, ConfigurationDataHolder): + raise InterpreterException('Merge_from argument must be a configuration data object.') + from_object = from_object.held_object + for k, v in from_object.values.items(): + self.held_object.values[k] = v + # Interpreter objects can not be pickled so we must have # these wrappers. @@ -1479,6 +1490,10 @@ class Interpreter(InterpreterBase): if len(args) != 1: raise InvalidCode('Import takes one argument.') modname = args[0] + if modname.startswith('unstable-'): + plainname = modname.split('-', 1)[1] + mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname) + modname = 'unstable_' + plainname if modname not in self.environment.coredata.modules: try: module = importlib.import_module('mesonbuild.modules.' + modname) diff --git a/mesonbuild/modules/unstable_simd.py b/mesonbuild/modules/unstable_simd.py new file mode 100644 index 0000000..4aebc02 --- /dev/null +++ b/mesonbuild/modules/unstable_simd.py @@ -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() |