Commit 1dd251b8 authored by Ben Gamari's avatar Ben Gamari 🐢

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
parent 3cbee255
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())
......@@ -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")
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment