forked from OSchip/llvm-project
[Perf-training] Adding support for tests to skip the clang driver
This patch adds a new set of substitutions to the lit run lines for order files and PGO generation which run the clang driver to get the cc1 command, then execute the cc1 command directly. This allows the scripts to bypass profiling the clang driver over and over again. The approach in this patch was discussed via IRC with Sean Silvas. Special thanks to Daniel Dunbar whose out-of-tree code I liberally plagiarized. llvm-svn: 263997
This commit is contained in:
parent
e9b02d68f4
commit
12fd02db6b
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clang_cpp -c %s
|
||||
// RUN: %clang_cpp_skip_driver -Wall -pedantic -c %s
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char**) {
|
||||
|
|
|
@ -26,10 +26,13 @@ config.clang = lit.util.which('clang', config.clang_tools_dir).replace('\\', '/'
|
|||
config.name = 'Clang Perf Training'
|
||||
config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap']
|
||||
|
||||
cc1_wrapper = '%s %s/perf-helper.py cc1' % (config.python_exe, config.test_source_root)
|
||||
|
||||
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
|
||||
config.test_format = lit.formats.ShTest(use_lit_shell == "0")
|
||||
config.substitutions.append( ('%clang_cpp_skip_driver', ' %s %s %s ' % (cc1_wrapper, config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang_cpp', ' %s --driver-mode=cpp %s ' % (config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang_cc1', ' %s -cc1 %s ' % (config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang_skip_driver', ' %s %s %s ' % (cc1_wrapper, config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang', ' %s %s ' % (config.clang, sysroot_flags) ) )
|
||||
config.substitutions.append( ('%test_root', config.test_exec_root ) )
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ config.clang_tools_dir = "@CLANG_TOOLS_DIR@"
|
|||
config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@"
|
||||
config.test_source_root = "@CMAKE_CURRENT_SOURCE_DIR@"
|
||||
config.target_triple = "@TARGET_TRIPLE@"
|
||||
config.python_exe = "@PYTHON_EXECUTABLE@"
|
||||
|
||||
# Support substitution of the tools and libs dirs with user parameters. This is
|
||||
# used when we can't determine the tool dir at configuration time.
|
||||
|
|
|
@ -28,11 +28,13 @@ config.name = 'Clang Perf Training'
|
|||
config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap']
|
||||
|
||||
dtrace_wrapper = '%s %s/perf-helper.py dtrace' % (config.python_exe, config.test_source_root)
|
||||
dtrace_wrapper_cc1 = '%s %s/perf-helper.py dtrace --cc1' % (config.python_exe, config.test_source_root)
|
||||
|
||||
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
|
||||
config.test_format = lit.formats.ShTest(use_lit_shell == "0")
|
||||
config.substitutions.append( ('%clang_cpp_skip_driver', ' %s %s --driver-mode=cpp %s ' % (dtrace_wrapper_cc1, config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang_cpp', ' %s %s --driver-mode=cpp %s ' % (dtrace_wrapper, config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang_cc1', ' %s %s -cc1 %s ' % (dtrace_wrapper, config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang_skip_driver', ' %s %s %s ' % (dtrace_wrapper_cc1, config.clang, sysroot_flags)))
|
||||
config.substitutions.append( ('%clang', ' %s %s %s ' % (dtrace_wrapper, config.clang, sysroot_flags) ) )
|
||||
config.substitutions.append( ('%test_root', config.test_exec_root ) )
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ import subprocess
|
|||
import argparse
|
||||
import time
|
||||
import bisect
|
||||
import shlex
|
||||
|
||||
test_env = { 'PATH' : os.environ['PATH'] }
|
||||
|
||||
def findFilesWithExtension(path, extension):
|
||||
filenames = []
|
||||
|
@ -52,6 +55,8 @@ def dtrace(args):
|
|||
help='Use dtrace\'s oneshot probes')
|
||||
parser.add_argument('--use-ustack', required=False, action='store_true',
|
||||
help='Use dtrace\'s ustack to print function names')
|
||||
parser.add_argument('--cc1', required=False, action='store_true',
|
||||
help='Execute cc1 directly (don\'t profile the driver)')
|
||||
parser.add_argument('cmd', nargs='*', help='')
|
||||
|
||||
# Use python's arg parser to handle all leading option arguments, but pass
|
||||
|
@ -62,6 +67,9 @@ def dtrace(args):
|
|||
opts = parser.parse_args(args[:last_arg_idx])
|
||||
cmd = args[last_arg_idx:]
|
||||
|
||||
if opts.cc1:
|
||||
cmd = get_cc1_command_for_args(cmd, test_env)
|
||||
|
||||
if opts.use_oneshot:
|
||||
target = "oneshot$target:::entry"
|
||||
else:
|
||||
|
@ -98,6 +106,57 @@ def dtrace(args):
|
|||
|
||||
return 0
|
||||
|
||||
def get_cc1_command_for_args(cmd, env):
|
||||
# Find the cc1 command used by the compiler. To do this we execute the
|
||||
# compiler with '-###' to figure out what it wants to do.
|
||||
cmd = cmd + ['-###']
|
||||
cc_output = check_output(cmd, stderr=subprocess.STDOUT, env=env).strip()
|
||||
cc_commands = []
|
||||
for ln in cc_output.split('\n'):
|
||||
# Filter out known garbage.
|
||||
if (ln == 'Using built-in specs.' or
|
||||
ln.startswith('Configured with:') or
|
||||
ln.startswith('Target:') or
|
||||
ln.startswith('Thread model:') or
|
||||
ln.startswith('InstalledDir:') or
|
||||
' version ' in ln):
|
||||
continue
|
||||
cc_commands.append(ln)
|
||||
|
||||
if len(cc_commands) != 1:
|
||||
print('Fatal error: unable to determine cc1 command: %r' % cc_output)
|
||||
exit(1)
|
||||
|
||||
cc1_cmd = shlex.split(cc_commands[0])
|
||||
if not cc1_cmd:
|
||||
print('Fatal error: unable to determine cc1 command: %r' % cc_output)
|
||||
exit(1)
|
||||
|
||||
return cc1_cmd
|
||||
|
||||
def cc1(args):
|
||||
parser = argparse.ArgumentParser(prog='perf-helper cc1',
|
||||
description='cc1 wrapper for order file generation')
|
||||
parser.add_argument('cmd', nargs='*', help='')
|
||||
|
||||
# Use python's arg parser to handle all leading option arguments, but pass
|
||||
# everything else through to dtrace
|
||||
first_cmd = next(arg for arg in args if not arg.startswith("--"))
|
||||
last_arg_idx = args.index(first_cmd)
|
||||
|
||||
opts = parser.parse_args(args[:last_arg_idx])
|
||||
cmd = args[last_arg_idx:]
|
||||
|
||||
# clear the profile file env, so that we don't generate profdata
|
||||
# when capturing the cc1 command
|
||||
cc1_env = test_env
|
||||
cc1_env["LLVM_PROFILE_FILE"] = "driver.prfraw"
|
||||
cc1_cmd = get_cc1_command_for_args(cmd, cc1_env)
|
||||
os.remove("driver.prfraw")
|
||||
|
||||
subprocess.check_call(cc1_cmd)
|
||||
return 0;
|
||||
|
||||
def parse_dtrace_symbol_file(path, all_symbols, all_symbols_set,
|
||||
missing_symbols, opts):
|
||||
def fix_mangling(symbol):
|
||||
|
@ -341,6 +400,7 @@ def genOrderFile(args):
|
|||
commands = {'clean' : clean,
|
||||
'merge' : merge,
|
||||
'dtrace' : dtrace,
|
||||
'cc1' : cc1,
|
||||
'gen-order-file' : genOrderFile}
|
||||
|
||||
def main():
|
||||
|
|
Loading…
Reference in New Issue