diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -852,99 +852,28 @@ endif() if (CLANG_BOLT_INSTRUMENT AND NOT LLVM_BUILD_INSTRUMENTED) - set(CLANG_PATH ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang) - set(CLANGXX_PATH ${CLANG_PATH}++) - set(CLANG_INSTRUMENTED ${CLANG_PATH}-bolt.inst) - set(CLANGXX_INSTRUMENTED ${CLANGXX_PATH}-bolt.inst) + set(CLANG_BOLT_INSTRUMENTED ${CMAKE_CURRENT_BINARY_DIR}/clang-bolt.inst) # Instrument clang with BOLT - add_custom_target(clang-instrumented - DEPENDS ${CLANG_INSTRUMENTED} - ) - add_custom_command(OUTPUT ${CLANG_INSTRUMENTED} + add_custom_target(clang-bolt-instrumented DEPENDS clang llvm-bolt - COMMAND llvm-bolt ${CLANG_PATH} -o ${CLANG_INSTRUMENTED} + COMMAND llvm-bolt $ -o ${CLANG_BOLT_INSTRUMENTED} -instrument --instrumentation-file-append-pid --instrumentation-file=${CMAKE_CURRENT_BINARY_DIR}/prof.fdata COMMENT "Instrumenting clang binary with BOLT" VERBATIM ) - # Make a symlink from clang-bolt.inst to clang++-bolt.inst - add_custom_target(clang++-instrumented - DEPENDS ${CLANGXX_INSTRUMENTED} - ) - add_custom_command(OUTPUT ${CLANGXX_INSTRUMENTED} - DEPENDS clang-instrumented - COMMAND ${CMAKE_COMMAND} -E create_symlink - ${CLANG_INSTRUMENTED} - ${CLANGXX_INSTRUMENTED} - COMMENT "Creating symlink from BOLT instrumented clang to clang++" - VERBATIM - ) - - # Build specified targets with instrumented Clang to collect the profile - set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/bolt-instrumented-clang-stamps/) - set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/bolt-instrumented-clang-bins/) - set(build_configuration "$") - include(ExternalProject) - ExternalProject_Add(bolt-instrumentation-profile - DEPENDS clang++-instrumented - PREFIX bolt-instrumentation-profile - SOURCE_DIR ${CMAKE_SOURCE_DIR} - STAMP_DIR ${STAMP_DIR} - BINARY_DIR ${BINARY_DIR} - EXCLUDE_FROM_ALL 1 - CMAKE_ARGS - ${CLANG_BOLT_INSTRUMENT_EXTRA_CMAKE_FLAGS} - # We shouldn't need to set this here, but INSTALL_DIR doesn't - # seem to work, so instead I'm passing this through - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} - -DCMAKE_C_COMPILER=${CLANG_INSTRUMENTED} - -DCMAKE_CXX_COMPILER=${CLANGXX_INSTRUMENTED} - -DCMAKE_ASM_COMPILER=${CLANG_INSTRUMENTED} - -DCMAKE_ASM_COMPILER_ID=Clang - -DCMAKE_BUILD_TYPE=Release - -DLLVM_ENABLE_PROJECTS=${CLANG_BOLT_INSTRUMENT_PROJECTS} - -DLLVM_TARGETS_TO_BUILD=${LLVM_TARGETS_TO_BUILD} - BUILD_COMMAND ${CMAKE_COMMAND} --build ${BINARY_DIR} - --config ${build_configuration} - --target ${CLANG_BOLT_INSTRUMENT_TARGETS} - INSTALL_COMMAND "" - STEP_TARGETS configure build - USES_TERMINAL_CONFIGURE 1 - USES_TERMINAL_BUILD 1 - USES_TERMINAL_INSTALL 1 - ) - - # Merge profiles into one using merge-fdata - add_custom_target(clang-bolt-profile - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata - ) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata - DEPENDS merge-fdata bolt-instrumentation-profile-build - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${Python3_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/utils/perf-training/perf-helper.py merge-fdata - $ ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata - ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Preparing BOLT profile" - VERBATIM - ) - # Optimize original (pre-bolt) Clang using the collected profile - set(CLANG_OPTIMIZED ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt) + set(BOLT_FDATA ${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/prof.fdata) add_custom_target(clang-bolt - DEPENDS ${CLANG_OPTIMIZED} - ) - add_custom_command(OUTPUT ${CLANG_OPTIMIZED} - DEPENDS clang-bolt-profile - COMMAND llvm-bolt ${CLANG_PATH} - -o ${CLANG_OPTIMIZED} - -data ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata + DEPENDS merge-bolt-fdata + COMMAND llvm-bolt $ + -o ${CMAKE_CURRENT_BINARY_DIR}/clang-bolt + -data ${BOLT_FDATA} -reorder-blocks=ext-tsp -reorder-functions=hfsort+ -split-functions -split-all-cold -split-eh -dyno-stats -icf=1 -use-gnu-stack - COMMAND ${CMAKE_COMMAND} -E rename ${CLANG_OPTIMIZED} $ + COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/clang-bolt $ COMMENT "Optimizing Clang with BOLT" VERBATIM ) diff --git a/clang/utils/perf-training/CMakeLists.txt b/clang/utils/perf-training/CMakeLists.txt --- a/clang/utils/perf-training/CMakeLists.txt +++ b/clang/utils/perf-training/CMakeLists.txt @@ -59,3 +59,30 @@ COMMENT "Generating order file" DEPENDS generate-dtrace-logs) endif() + +if(CLANG_BOLT_INSTRUMENT) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/bolt.lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/bolt-fdata/lit.site.cfg + ) + + add_lit_testsuite(generate-bolt-fdata "Generating BOLT profile for Clang" + ${CMAKE_CURRENT_BINARY_DIR}/bolt-fdata/ + EXCLUDE_FROM_CHECK_ALL + DEPENDS clang-bolt-instrumented clear-bolt-fdata + ) + + add_custom_target(clear-bolt-fdata + COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} fdata + COMMENT "Clearing old BOLT fdata") + + if(NOT MERGE_FDATA) + find_program(MERGE_FDATA merge-fdata) + endif() + + # Merge profiles into one using merge-fdata + add_custom_target(merge-bolt-fdata + COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py merge-fdata ${MERGE_FDATA} ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Merging BOLT fdata" + DEPENDS generate-bolt-fdata) +endif() diff --git a/clang/utils/perf-training/bolt.lit.cfg b/clang/utils/perf-training/bolt.lit.cfg new file mode 100644 --- /dev/null +++ b/clang/utils/perf-training/bolt.lit.cfg @@ -0,0 +1,20 @@ +# -*- Python -*- + +from lit import Test +import lit.formats +import lit.util +import os +import subprocess + +config.clang = os.path.realpath(lit.util.which('clang-bolt.inst', config.clang_tools_dir)).replace('\\', '/') + +config.name = 'Clang Perf Training' +config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap', '.test'] + +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 --driver-mode=g++ %s ' % (config.clang, sysroot_flags))) +config.substitutions.append( ('%clang_cpp', ' %s --driver-mode=g++ %s ' % (config.clang, sysroot_flags))) +config.substitutions.append( ('%clang_skip_driver', ' %s %s ' % (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/clang/utils/perf-training/bolt.lit.site.cfg.in b/clang/utils/perf-training/bolt.lit.site.cfg.in new file mode 100644 --- /dev/null +++ b/clang/utils/perf-training/bolt.lit.site.cfg.in @@ -0,0 +1,13 @@ +@LIT_SITE_CFG_IN_HEADER@ + +import sys + +config.clang_tools_dir = lit_config.substitute("@CURRENT_TOOLS_DIR@") +config.perf_helper_dir = "@CMAKE_CURRENT_SOURCE_DIR@" +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" +config.test_source_root = "@CLANG_PGO_TRAINING_DATA@" +config.target_triple = "@LLVM_TARGET_TRIPLE@" +config.python_exe = "@Python3_EXECUTABLE@" + +# Let the main config do the real work. +lit_config.load_config(config, "@CLANG_SOURCE_DIR@/utils/perf-training/bolt.lit.cfg")