summaryrefslogtreecommitdiff
path: root/utils/perf-training
diff options
context:
space:
mode:
authorChris Bieneman <beanz@apple.com>2016-03-21 22:37:14 +0000
committerChris Bieneman <beanz@apple.com>2016-03-21 22:37:14 +0000
commit2437ac71c6359192bc358b194f0df03cbecd8b2b (patch)
treeeb2637b55490e63cc187c760dc2ae0d962ea1fa2 /utils/perf-training
parente1a6d0f8326d360a68117cf5d93d21dcd43c9125 (diff)
downloadclang-2437ac71c6359192bc358b194f0df03cbecd8b2b.tar.gz
[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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@263997 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/perf-training')
-rw-r--r--utils/perf-training/cxx/hello_world.cpp1
-rw-r--r--utils/perf-training/lit.cfg5
-rw-r--r--utils/perf-training/lit.site.cfg.in1
-rw-r--r--utils/perf-training/order-files.lit.cfg4
-rw-r--r--utils/perf-training/perf-helper.py60
5 files changed, 69 insertions, 2 deletions
diff --git a/utils/perf-training/cxx/hello_world.cpp b/utils/perf-training/cxx/hello_world.cpp
index 66e00d00d2..fc9f6892eb 100644
--- a/utils/perf-training/cxx/hello_world.cpp
+++ b/utils/perf-training/cxx/hello_world.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cpp -c %s
+// RUN: %clang_cpp_skip_driver -Wall -pedantic -c %s
#include <iostream>
int main(int, char**) {
diff --git a/utils/perf-training/lit.cfg b/utils/perf-training/lit.cfg
index af4b43b78b..85d3551434 100644
--- a/utils/perf-training/lit.cfg
+++ b/utils/perf-training/lit.cfg
@@ -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 ) )
diff --git a/utils/perf-training/lit.site.cfg.in b/utils/perf-training/lit.site.cfg.in
index 9dc380242e..52c5465dc3 100644
--- a/utils/perf-training/lit.site.cfg.in
+++ b/utils/perf-training/lit.site.cfg.in
@@ -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.
diff --git a/utils/perf-training/order-files.lit.cfg b/utils/perf-training/order-files.lit.cfg
index 0e151bf1fa..75501f8c62 100644
--- a/utils/perf-training/order-files.lit.cfg
+++ b/utils/perf-training/order-files.lit.cfg
@@ -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 ) )
diff --git a/utils/perf-training/perf-helper.py b/utils/perf-training/perf-helper.py
index a4ae68c849..19f3819b30 100644
--- a/utils/perf-training/perf-helper.py
+++ b/utils/perf-training/perf-helper.py
@@ -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():