diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -878,6 +878,56 @@ endforeach() endif() +if (CLANG_BOLT_INSTRUMENT) + find_program(LLVM_BOLT llvm-bolt) + find_program(MERGE_FDATA merge-fdata) + + # Instrument clang with BOLT + add_custom_target(clang-instrumented + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt.inst + ) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt.inst + DEPENDS clang + COMMAND ${LLVM_BOLT} ${CMAKE_BINARY_DIR}/clang -o + ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt.inst + -instrument --instrumentation-file-append-pid + --instrumentation-file=${CMAKE_CURRENT_BINARY_DIR}/prof.fdata + COMMENT "Instrumenting clang binary with BOLT" + ) + # Make a symlink from clang.bolt.inst to clang++.bolt.inst + add_clang_symlink(${CMAKE_CURRENT_BINARY_DIR}/clang++.bolt.inst + ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt.inst) + + # Configure and build Clang with instrumented Clang to collect the profile + include(ExternalProject) + ExternalProject_Add(bolt-instrumentation-profile + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt.inst + PREFIX bolt-instrumentation-profile + SOURCE_DIR ${CMAKE_SOURCE_DIR} + CMAKE_ARGS + # 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_CXX_COMPILER=${CMAKE_CURRENT_BINARY_DIR}/clang++.bolt.inst + -DCMAKE_C_COMPILER=${CMAKE_CURRENT_BINARY_DIR}/clang.bolt.inst + STEP_TARGETS configure build install + ) + # Merge profiles into one using merge-fdata + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata + COMMAND ${MERGE_FDATA} ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata.* + -o ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata + ) + # Optimize original (pre-bolt) Clang using the collected profile + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata clang + COMMAND ${LLVM_BOLT} ${CMAKE_BINARY_DIR}/clang + -o ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt -data ${CMAKE_CURRENT_BINARY_DIR}/prof.fdata + ) + add_custom_target(clang-bolt + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang.bolt + ) +endif() + if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) add_subdirectory(utils/ClangVisualizers) endif() diff --git a/clang/cmake/caches/BOLT.cmake b/clang/cmake/caches/BOLT.cmake new file mode 100644 --- /dev/null +++ b/clang/cmake/caches/BOLT.cmake @@ -0,0 +1,12 @@ +set(CMAKE_BUILD_TYPE Release CACHE STRING "") +set(CLANG_BOLT_INSTRUMENT ON CACHE BOOL "") +set(CMAKE_EXE_LINKER_FLAGS "-Wl,--emit-relocs,-znow" CACHE STRING "") + +set(LLVM_ENABLE_PROJECTS "bolt;clang;lld" CACHE STRING "") +set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "") + +# Disable function splitting enabled by default in GCC8+ +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-reorder-blocks-and-partition") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-reorder-blocks-and-partition") +endif()