blob: 98fe331384205446e42903875fcaeebea8f406a0 [file] [log] [blame]
#!/usr/bin/env python
# -*- Python -*-
from __future__ import print_function
import os
import shutil
import stat
# We import test functionity from LNT.
from lnt.tests import nt
from lnt.testing import TestSamples, PASS, FAIL, XFAIL
from lnt.testing.util import commands
# Implement cp -rf such that src can be both a file or a directory and if
# the dst exists create the file/dir under dst rather than rename on the
# fly.
def cp_rf(src, dst):
if os.path.isfile(src):
shutil.copy(src, dst)
else:
newdst = dst
if os.path.exists(dst):
newdst = os.path.join(dst, os.path.basename(src))
shutil.copytree(src, newdst)
# Test module classes are currently required to subclass 'nt.TestModule'.
class TestModule(nt.TestModule):
timeout = 5000
def __init__(self):
# The subdirectory name under externals E.g. CINT2006
self.suite = 'C' + self.category.upper() + str(self.year)
# Name to identify this LNT test, e.g. nts.LNT/CINT2006_ref/456.hmmer
self.testname = "nts.LNT/%s_ref/%s" % (self.suite, self.benchmark)
# Executable name, e.g. 456.hmmer.simple
self.exe = self.benchmark + '.simple'
def configure_test_suite(self, working_dir):
args = [os.path.realpath(os.path.join(self.config.test_suite_root,
'configure'))]
if self.config.without_llvm:
args.extend(['--without-llvmsrc', '--without-llvmobj'])
else:
args.extend(['--with-llvmsrc=%s' % self.config.llvm_src_root,
'--with-llvmobj=%s' % self.config.llvm_obj_root])
if self.config.test_suite_externals:
args.append('--with-externals=%s' %
os.path.realpath(self.config.test_suite_externals))
return self.call(args, cwd=working_dir)
def fail(self):
return [TestSamples(self.testname + '.compile.status', [FAIL])]
def copy_input_set(self, dest_dir, size):
if size == 'train':
input_set = self.train_input_set
elif size == 'ref':
input_set = self.ref_input_set
else:
fatal('only train and ref are supported for now')
for f in input_set:
cp_rf(os.path.join(self.datadir, f), dest_dir)
def copy_output_set(self, dest_dir, size):
if size == 'train':
output_set = self.train_output_set
else:
output_set = self.ref_output_set
for f in output_set:
cp_rf(os.path.join(self.datadir, f), dest_dir)
def run_safely(self, args, **kwargs):
if kwargs.get('shell', False):
argstr = args
else:
argstr = ' '.join(args)
kwargs['shell'] = True
if 'file_index' in kwargs:
file_index = kwargs['file_index']
# Remove so that it can be forwarded to self.call.
del kwargs['file_index']
else:
file_index = 0
# Generate a unique file for each training run (if requested)
timeit = ['LLVM_PROFILE_FILE=run_%d.profraw' % file_index,
os.path.join(self.OBJROOT, 'tools', 'timeit-target')]
cwd = kwargs.get('cwd', os.getcwd())
summary_file = os.path.join(cwd, 'summary_%d.time' % file_index)
timeit.extend(['--limit-core', '0',
'--limit-cpu', str(self.timeout),
'--timeout', str(self.timeout),
'--limit-file-size', '104857600',
'--limit-rss-size', '838860800',
'--summary', summary_file])
timeit.append(argstr)
cmdstr = ' '.join(timeit)
if self.config.remote:
command_file = os.path.join(cwd, 'command_%d' % file_index)
with open(command_file, 'w') as f:
# Chdir here so that the redirects are put into CWD as well.
remote_command = 'cd %s\n%s\n' % (cwd, cmdstr)
print("command:", remote_command, file=self.log, end=' ')
f.write(remote_command)
st = os.stat(command_file)
os.chmod(command_file, st.st_mode | stat.S_IEXEC)
res = self.call([self.config.remote_client,
'-l', self.config.remote_user,
self.config.remote_host,
'-p', str(self.config.remote_port),
command_file])
else:
kwargs['shell'] = True
res = self.call(cmdstr, **kwargs)
if res != 0:
return (res, 0)
summary = open(summary_file, 'r').readlines()
status = [line.split()[1] for line in summary if line.startswith('exit')]
assert len(status) == 1, 'incorrect exit status'
time = [line.split()[1] for line in summary
if line.startswith(self.config.test_time_stat)]
assert len(time) == 1, 'incorrect ellapsed time'
return (int(status[0]), float(time[0]))
def execute_test(self, options, make_variables, config):
MODULENAME = options['MODULENAME']
self.SRCROOT = options['SRCROOT']
self.config = config
self.OBJROOT = options['OBJROOT']
CC = options['CC']
CFLAGS = options['CFLAGS']
TEST_SUITE_EXTERNALS = config.test_suite_externals
# test-suite-externals//speccpu2006/benchspec/CPU2006/400.perlbench vs
# test-suite-externals//speccpu2000/benchspec/CINT2000/164.gzip
suitedir = os.path.join(TEST_SUITE_EXTERNALS, 'speccpu' + str(self.year), 'benchspec')
if self.year == '2000':
suitedir = os.path.join(suitedir, 'C%s2000' % self.category.upper())
else:
suitedir = os.path.join(suitedir, 'CPU' + self.year)
self.datadir = os.path.join(suitedir, self.benchmark, 'data')
print("%s\n options: %s\n\nmake variables: %s\n\n" % (self.testname, str(options), str(make_variables)), file=self.log)
if not os.path.exists(self.datadir):
print("skipping, no source under externals", file=self.log)
return []
res = self.configure_test_suite(self.OBJROOT)
if res != 0:
return self.fail()
make_cmd = ['make', '-k']
make_cmd.extend('%s=%s' % (k,v) for k,v in make_variables.items())
# RunSafely.sh requires timeit, build it.
res = self.call(make_cmd + ['tools'], cwd=self.OBJROOT)
if res != 0:
return self.fail()
make_cmd.append('USE_SPEC_TEST_MODULE=1')
# Run make clean to create the benchmark directories.
external_obj = os.path.join(self.OBJROOT, 'External', 'SPEC', self.suite, self.benchmark)
clean_cmd = make_cmd
external_spec_obj = os.path.split(external_obj)[0]
result = self.call(make_cmd + ['-C', external_spec_obj, 'clean'])
if result != 0:
return self.fail()
# From this on, we are operating in the 456.hmmer directory.
make_cmd.extend(['-C', external_obj])
exe_file = os.path.join('Output', self.exe)
if config.spec_with_pgo:
pgo_dir = os.path.join(self.OBJROOT, 'pgo')
os.mkdir(pgo_dir)
target_flags = make_variables['TARGET_FLAGS'] + ' -fprofile-instr-generate'
pgo_make_cmd = make_cmd[:]
pgo_make_cmd.append("TARGET_FLAGS=%s" % target_flags)
result = self.call(pgo_make_cmd + [ exe_file ])
exe = os.path.join(external_obj, exe_file)
if result != 0 or not os.path.exists(exe):
return self.fail()
shutil.copy(exe, pgo_dir)
self.copy_input_set(pgo_dir, 'train')
for (i, args) in enumerate(self.train_args):
pgo_cmd = './%s %s' % (self.exe, args)
(result, time) = self.run_safely(pgo_cmd, cwd=pgo_dir, shell=True, env=os.environ, file_index=i)
if result != 0:
return self.fail()
if not os.path.exists(os.path.join(pgo_dir, 'run_%d.profraw' % i)):
print('Failed to create PGO output', file=self.log)
return self.fail()
llvm_profdata = os.path.join(os.path.dirname(CC), 'llvm-profdata')
result = self.call(llvm_profdata + ' merge -output=code.profdata pgo/run_*.profraw', shell=True, cwd=self.OBJROOT)
if result != 0:
return self.fail()
target_flags = make_variables['TARGET_FLAGS'] + ' -fprofile-instr-use=' + os.path.join(self.OBJROOT, 'code.profdata')
make_cmd.append("TARGET_FLAGS=%s" % target_flags)
result = self.call(make_cmd + ['-C', external_spec_obj, 'clean'])
if result != 0:
return self.fail()
start_time = self.get_time()
result = self.call(make_cmd + [ exe_file ])
compile_time = self.get_time() - start_time
exe = os.path.join(external_obj, exe_file)
if result != 0 or not os.path.exists(exe):
return self.fail()
shutil.copy(exe, self.OBJROOT)
self.copy_input_set(self.OBJROOT, 'ref')
self.copy_output_set(self.OBJROOT, 'ref')
run_cmds = ['./%s %s' % (self.exe, args) for args in self.ref_args]
status = PASS
exec_time = 0
for (file_index, cmd) in enumerate(run_cmds):
(result, time) = self.run_safely(cmd, cwd=self.OBJROOT, shell=True, file_index=file_index)
if result != 0:
status = FAIL
exec_time += time
os.environ['PATH'] += ':' + os.path.join(self.OBJROOT, 'tools')
for cmd in self.ref_cmp_cmds:
if self.call(cmd, cwd=self.OBJROOT, shell=True, env=os.environ) != 0:
status = FAIL
result = [
TestSamples(self.testname + '.compile', [compile_time]),
TestSamples(self.testname + '.exec', [exec_time])]
if status == FAIL:
result.append(TestSamples(self.testname + '.exec.status', [status]))
return result