diff options
author | Ben Gamari <ben@smart-cactus.org> | 2018-12-27 14:41:01 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2019-01-27 08:32:12 -0500 |
commit | 1dd251b861c98c7b42a117b820afef5020745585 (patch) | |
tree | 7b96692309adbb772a971996d7881b29f4b6aeab /testsuite/driver | |
parent | 3cbee255cd550e49e3265257fd2955ce8e6a351a (diff) | |
download | haskell-1dd251b861c98c7b42a117b820afef5020745585.tar.gz |
testsuite: Add predicate for CPU feature availability
Previously testing code-generation for ISA extensions was nearly impossible
since we had no ability to determine whether the host supports the needed
extension. Here we fix this by introducing a simple /proc/cpuinfo-based
testsuite predicate. We really ought to
Diffstat (limited to 'testsuite/driver')
-rw-r--r-- | testsuite/driver/cpu_features.py | 71 | ||||
-rw-r--r-- | testsuite/driver/runtests.py | 7 | ||||
-rw-r--r-- | testsuite/driver/testlib.py | 1 |
3 files changed, 79 insertions, 0 deletions
diff --git a/testsuite/driver/cpu_features.py b/testsuite/driver/cpu_features.py new file mode 100644 index 0000000000..7716306bd6 --- /dev/null +++ b/testsuite/driver/cpu_features.py @@ -0,0 +1,71 @@ +import os +from testglobals import config +import subprocess +import re + +# Feature names generally follow the naming used by Linux's /proc/cpuinfo. +SUPPORTED_CPU_FEATURES = { + # These aren't comprehensive; they are only CPU features that we care about + + # x86: + 'sse', 'sse2', 'sse3', 'ssse3', 'sse4_1', 'sse4_2', + 'avx1', 'avx2', + 'popcnt', 'bmi1', 'bmi2' +} + +cpu_feature_cache = None + +def get_cpu_features(): + if config.os in ['mingw32', 'linux'] and os.path.exists('/proc/cpuinfo'): + f = open('/proc/cpuinfo').read() + flags = re.search(r'flags\s*:\s*.*$', f, re.M) + if flags is None: + print('get_cpu_features: failed to find cpu features') + return {} + flags = set(flags.group(0).split()) + if 'pni' in flags: + flags.add('sse3') + flags.remove('pni') + return flags + + elif config.os == 'darwin': + out = subprocess.check_output(['sysctl', 'hw']).decode('UTF-8') + features = set() + def check_feature(darwin_name, our_name=None): + if re.search(r'hw\.optional.%s:\s*1' % darwin_name, out) is not None: + features.add(darwin_name if our_name is None else our_name) + + for feature in SUPPORTED_CPU_FEATURES: + check_feature(feature) + + # A few annoying cases + check_feature('avx1_0', 'avx1') + check_feature('avx2_0', 'avx2') + return features + + else: + # TODO: Add {Open,Free}BSD support + print('get_cpu_features: Lacking support for your platform') + + return {} + +def have_cpu_feature(feature): + """ + A testsuite predicate for testing the availability of CPU features. + """ + assert feature in SUPPORTED_CPU_FEATURES + if cpu_feature_cache is None: + cpu_feature_cache = get_cpu_features() + print('Found CPU features:', ' '.join(cpu_feature_cache)) + # Sanity checking + assert all(feat in SUPPORTED_CPU_FEATURES + for feat in cpu_feature_cache) + + return feature in cpu_feature_cache + + +if __name__ == '__main__': + import sys + config.os = sys.argv[1] + print(get_cpu_features()) + diff --git a/testsuite/driver/runtests.py b/testsuite/driver/runtests.py index 55b13df2bc..247a5cc330 100644 --- a/testsuite/driver/runtests.py +++ b/testsuite/driver/runtests.py @@ -27,6 +27,7 @@ from testutil import getStdout, Watcher, str_warn, str_info from testglobals import getConfig, ghc_env, getTestRun, TestOptions, brokens from perf_notes import MetricChange, inside_git_repo, is_worktree_dirty from junit import junit +import cpu_features # Readline sometimes spews out ANSI escapes for some values of TERM, # which result in test failures. Thus set TERM to a nice, simple, safe @@ -274,6 +275,12 @@ t.start_time = time.localtime() print('Beginning test run at', time.strftime("%c %Z",t.start_time)) +# For reference +try: + print('Detected CPU features: ', cpu_features.get_cpu_features()) +except Exception as e: + print('Failed to detect CPU features: ', e) + sys.stdout.flush() # we output text, which cannot be unbuffered sys.stdout = os.fdopen(sys.__stdout__.fileno(), "w") diff --git a/testsuite/driver/testlib.py b/testsuite/driver/testlib.py index c09d02aab2..ba4f6a5a47 100644 --- a/testsuite/driver/testlib.py +++ b/testsuite/driver/testlib.py @@ -20,6 +20,7 @@ import subprocess from testglobals import config, ghc_env, default_testopts, brokens, t from testutil import strip_quotes, lndir, link_or_copy_file, passed, failBecause, str_fail, str_pass +from cpu_features import have_cpu_feature import perf_notes as Perf from perf_notes import MetricChange extra_src_files = {'T4198': ['exitminus1.c']} # TODO: See #12223 |