summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2018-12-27 14:41:01 -0500
committerBen Gamari <ben@smart-cactus.org>2018-12-27 15:20:17 -0500
commit2d9bb67e0a42e1cfb0737de00a4a8fe2e9cc5636 (patch)
tree5f435f4e332d178031858809d81479bf84e52fd7
parent942b501972139ed95b49b75cb8c0523b460f6d10 (diff)
downloadhaskell-wip/testsuite-cpu-features.tar.gz
testsuite: Add predicate for CPU feature availabilitywip/testsuite-cpu-features
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
-rw-r--r--testsuite/driver/cpu_features.py71
-rw-r--r--testsuite/driver/testlib.py1
2 files changed, 72 insertions, 0 deletions
diff --git a/testsuite/driver/cpu_features.py b/testsuite/driver/cpu_features.py
new file mode 100644
index 0000000000..b9e43470da
--- /dev/null
+++ b/testsuite/driver/cpu_features.py
@@ -0,0 +1,71 @@
+import os
+from testglobals import config
+
+# 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 == 'Linux' and os.path.exists('/proc/cpuinfo'):
+ import re
+ 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[0].split())
+ if 'pni' in flags:
+ flags.add('sse3')
+ flags.remove('pni')
+ return flags
+
+ elif config.os == 'Darwin':
+ import subprocess
+ out, err = subprocess.check_output(['sysctl', 'hw'])
+ features = {}
+ def check_feature(darwin_name, our_name=None):
+ if re.find(r'hw\.optional.%s:\s*1' % darwin_name, out):
+ 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 Windows 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/testlib.py b/testsuite/driver/testlib.py
index 5f84863070..df56d1d685 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