Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang][CMake] Add CSSPGO support to LLVM_BUILD_INSTRUMENTED #79942

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions clang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -744,11 +744,22 @@ if (CLANG_ENABLE_BOOTSTRAP)
if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
add_dependencies(clang-bootstrap-deps llvm-profdata)
set(PGO_OPT -DLLVM_PROFDATA=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profdata)
string(TOUPPER "${BOOTSTRAP_LLVM_BUILD_INSTRUMENTED}" BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
if (BOOTSTRAP_LLVM_BUILD_INSTRUMENTED STREQUAL "CSSPGO")
add_dependencies(clang-bootstrap-deps llvm-profgen)
list(APPEND PGO_OPT -DLLVM_PROFGEN=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profgen)
endif()
endif()

if(LLVM_BUILD_INSTRUMENTED)
add_dependencies(clang-bootstrap-deps generate-profdata)
set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata)
string(TOUPPER "${LLVM_BUILD_INSTRUMENTED}" LLVM_BUILD_INSTRUMENTED)
if (LLVM_BUILD_INSTRUMENTED STREQUAL "CSSPGO")
add_dependencies(clang-bootstrap-deps generate-sprofdata)
set(PGO_OPT -DLLVM_SPROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.sprofdata)
else()
add_dependencies(clang-bootstrap-deps generate-profdata)
set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata)
endif()
# Use the current tools for LTO instead of the instrumented ones
list(APPEND _BOOTSTRAP_DEFAULT_PASSTHROUGH
CMAKE_CXX_COMPILER
Expand Down
3 changes: 3 additions & 0 deletions clang/cmake/caches/BOLT-CSSPGO.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
set(BOLT_PGO_CMAKE_CACHE "CSSPGO" CACHE STRING "")
set(BOOTSTRAP_CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
include(${CMAKE_CURRENT_LIST_DIR}/BOLT-PGO.cmake)
3 changes: 2 additions & 1 deletion clang/cmake/caches/BOLT-PGO.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
set(BOLT_PGO_CMAKE_CACHE "PGO" CACHE STRING "")
set(LLVM_ENABLE_PROJECTS "bolt;clang;lld" CACHE STRING "")

set(CLANG_BOOTSTRAP_TARGETS
Expand All @@ -14,4 +15,4 @@ set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS
set(PGO_BUILD_CONFIGURATION
${CMAKE_CURRENT_LIST_DIR}/BOLT.cmake
CACHE STRING "")
include(${CMAKE_CURRENT_LIST_DIR}/PGO.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/${BOLT_PGO_CMAKE_CACHE}.cmake)
2 changes: 2 additions & 0 deletions clang/cmake/caches/CSSPGO.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED "CSSPGO" CACHE STRING "")
include(${CMAKE_CURRENT_LIST_DIR}/PGO.cmake)
36 changes: 31 additions & 5 deletions clang/utils/perf-training/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ set(CLANG_PGO_TRAINING_DATA "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH
set(CLANG_PGO_TRAINING_DATA_SOURCE_DIR OFF CACHE STRING "Path to source directory containing cmake project with source files to use for generating pgo data")
set(CLANG_PGO_TRAINING_DEPS "" CACHE STRING "Extra dependencies needed to build the PGO training data.")

add_custom_target(clear-perf-data
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} perf.data
COMMENT "Clearing old perf data")

if(LLVM_BUILD_INSTRUMENTED)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
Expand All @@ -15,7 +19,7 @@ if(LLVM_BUILD_INSTRUMENTED)
add_lit_testsuite(generate-profraw "Generating clang PGO data"
${CMAKE_CURRENT_BINARY_DIR}/pgo-data/
EXCLUDE_FROM_CHECK_ALL
DEPENDS clear-profraw
DEPENDS clear-profraw clang
)

add_custom_target(clear-profraw
Expand Down Expand Up @@ -49,6 +53,32 @@ if(LLVM_BUILD_INSTRUMENTED)
USE_TOOLCHAIN EXLUDE_FROM_ALL NO_INSTALL DEPENDS generate-profraw)
add_dependencies(generate-profdata generate-profraw-external)
endif()

if(NOT LLVM_PROFGEN)
find_program(LLVM_PROFGEN llvm-profgen)
endif()

if(NOT LLVM_PROFGEN)
message(STATUS "To enable converting CSSPGO samples LLVM_PROFGEN has to point to llvm-profgen")
elseif(NOT CLANG_PGO_TRAINING_DATA_SOURCE_DIR)
message(STATUS "CLANG_PGO_TRAINING_DATA_SOURCE_DIR must be set to collect CSSPGO samples")
else()
set(PERF_HELPER "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py)
set(CLANG_SPROFDATA ${CMAKE_CURRENT_BINARY_DIR}/clang.sprofdata)
add_custom_command(
OUTPUT ${CLANG_SPROFDATA}
# Execute generate-profraw-external under perf
COMMAND ${PERF_HELPER} perf --csspgo -- ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target generate-profraw-external
# Convert perf profile into profraw
COMMAND ${PERF_HELPER} perf2prof ${LLVM_PROFGEN} $<TARGET_FILE:clang> ${CMAKE_CURRENT_BINARY_DIR}
# Merge profdata
COMMAND ${PERF_HELPER} merge --sample ${LLVM_PROFDATA} ${CLANG_SPROFDATA} ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS clang ${CLANG_PGO_TRAINING_DEPS} clear-perf-data generate-profraw-external-clean
VERBATIM
USES_TERMINAL
)
add_custom_target(generate-sprofdata DEPENDS ${CLANG_SPROFDATA})
endif()
endif()
endif()

Expand Down Expand Up @@ -100,10 +130,6 @@ if(CLANG_BOLT AND NOT LLVM_BUILD_INSTRUMENTED)
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} fdata
COMMENT "Clearing old BOLT fdata")

add_custom_target(clear-perf-data
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} perf.data
COMMENT "Clearing old perf data")

string(TOUPPER "${CLANG_BOLT}" CLANG_BOLT)
if (CLANG_BOLT STREQUAL "LBR")
set(BOLT_LBR "--lbr")
Expand Down
58 changes: 46 additions & 12 deletions clang/utils/perf-training/perf-helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,29 @@ def clean(args):
+ "\tRemoves all files with extension from <path>."
)
return 1
for path in args[1:-1]:
for path in args[:-1]:
for filename in findFilesWithExtension(path, args[-1]):
os.remove(filename)
return 0


def merge(args):
if len(args) < 3:
print(
"Usage: %s merge <llvm-profdata> <output> <paths>\n" % __file__
+ "\tMerges all profraw files from path into output."
)
return 1
cmd = [args[0], "merge", "-o", args[1]]
for path in args[2:]:
parser = argparse.ArgumentParser(
prog="perf-helper merge",
description="Merges all profraw files from path(s) into output",
)
parser.add_argument("profdata", help="Path to llvm-profdata tool")
parser.add_argument("output", help="Output filename")
parser.add_argument(
"paths", nargs="+", help="Folder(s) containing input profraw files"
)
parser.add_argument("--sample", action="store_true", help="Sample profile")
opts = parser.parse_args(args)

cmd = [opts.profdata, "merge", "-o", opts.output]
if opts.sample:
cmd += ["--sample"]
for path in opts.paths:
cmd.extend(findFilesWithExtension(path, "profraw"))
subprocess.check_call(cmd)
return 0
Expand All @@ -71,25 +79,30 @@ def merge_fdata(args):

def perf(args):
parser = argparse.ArgumentParser(
prog="perf-helper perf", description="perf wrapper for BOLT profile collection"
prog="perf-helper perf",
description="perf wrapper for BOLT/CSSPGO profile collection",
)
parser.add_argument(
"--lbr", action="store_true", help="Use perf with branch stacks"
)
parser.add_argument("--csspgo", action="store_true", help="Enable CSSPGO flags")
parser.add_argument("cmd", nargs=argparse.REMAINDER, help="")

opts = parser.parse_args(args)
cmd = opts.cmd[1:]

event = "br_inst_retired.near_taken:uppp" if opts.csspgo else "cycles:u"
perf_args = [
"perf",
"record",
"--event=cycles:u",
f"--event={event}",
"--freq=max",
"--output=%d.perf.data" % os.getpid(),
]
if opts.lbr:
if opts.lbr or opts.csspgo:
perf_args += ["--branch-filter=any,u"]
if opts.csspgo:
perf_args += ["-g", "--call-graph=fp"]
perf_args.extend(cmd)

start_time = time.time()
Expand Down Expand Up @@ -125,6 +138,26 @@ def perf2bolt(args):
return 0


def perf2prof(args):
parser = argparse.ArgumentParser(
prog="perf-helper perf2prof",
description="perf to CSSPGO prof conversion wrapper",
)
parser.add_argument("profgen", help="Path to llvm-profgen binary")
parser.add_argument("binary", help="Input binary")
parser.add_argument("paths", nargs="+", help="Path containing perf.data files")
opts = parser.parse_args(args)

profgen_args = [opts.profgen, f"--binary={opts.binary}"]
for path in opts.paths:
for filename in findFilesWithExtension(path, "perf.data"):
subprocess.check_call(
profgen_args
+ [f"--perfdata={filename}", f"--output={filename}.profraw"]
)
return 0


def dtrace(args):
parser = argparse.ArgumentParser(
prog="perf-helper dtrace",
Expand Down Expand Up @@ -567,6 +600,7 @@ def genOrderFile(args):
"merge-fdata": merge_fdata,
"perf": perf,
"perf2bolt": perf2bolt,
"perf2prof": perf2prof,
}


Expand Down
3 changes: 3 additions & 0 deletions llvm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,9 @@ set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ${LLVM_ENABLE_PER_TARGET_RUNTIME_DIR_defa
set(LLVM_PROFDATA_FILE "" CACHE FILEPATH
"Profiling data file to use when compiling in order to improve runtime performance.")

set(LLVM_SPROFDATA_FILE "" CACHE FILEPATH
"Sampling profiling data file to use when compiling in order to improve runtime performance.")

if(LLVM_INCLUDE_TESTS)
# All LLVM Python files should be compatible down to this minimum version.
set(LLVM_MINIMUM_PYTHON_VERSION 3.8)
Expand Down
26 changes: 25 additions & 1 deletion llvm/cmake/modules/HandleLLVMOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ endif()
option(LLVM_ENABLE_IR_PGO "Build LLVM and tools with IR PGO instrumentation (deprecated)" Off)
mark_as_advanced(LLVM_ENABLE_IR_PGO)

set(LLVM_BUILD_INSTRUMENTED OFF CACHE STRING "Build LLVM and tools with PGO instrumentation. May be specified as IR or Frontend")
set(LLVM_BUILD_INSTRUMENTED OFF CACHE STRING "Build LLVM and tools with PGO instrumentation. May be specified as IR, Frontend, CSIR, CSSPGO")
set(LLVM_VP_COUNTERS_PER_SITE "1.5" CACHE STRING "Value profile counters to use per site for IR PGO with Clang")
mark_as_advanced(LLVM_BUILD_INSTRUMENTED LLVM_VP_COUNTERS_PER_SITE)
string(TOUPPER "${LLVM_BUILD_INSTRUMENTED}" uppercase_LLVM_BUILD_INSTRUMENTED)
Expand Down Expand Up @@ -1167,6 +1167,15 @@ if (LLVM_BUILD_INSTRUMENTED)
CMAKE_EXE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS)
endif()
elseif(uppercase_LLVM_BUILD_INSTRUMENTED STREQUAL "CSSPGO")
append("-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-optimize-sibling-calls -fpseudo-probe-for-profiling"
CMAKE_CXX_FLAGS
CMAKE_C_FLAGS)
if(NOT LINKER_IS_LLD_LINK)
append("-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-optimize-sibling-calls -fpseudo-probe-for-profiling"
CMAKE_EXE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS)
endif()
else()
append("-fprofile-instr-generate=\"${LLVM_PROFILE_FILE_PATTERN}\""
CMAKE_CXX_FLAGS
Expand Down Expand Up @@ -1217,6 +1226,21 @@ if(LLVM_PROFDATA_FILE AND EXISTS ${LLVM_PROFDATA_FILE})
endif()
endif()

if(LLVM_SPROFDATA_FILE AND EXISTS ${LLVM_SPROFDATA_FILE})
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
append("-fpseudo-probe-for-profiling -fprofile-sample-use=\"${LLVM_SPROFDATA_FILE}\""
CMAKE_CXX_FLAGS
CMAKE_C_FLAGS)
if(NOT LINKER_IS_LLD_LINK)
append("-fpseudo-probe-for-profiling -fprofile-sample-use=\"${LLVM_SPROFDATA_FILE}\""
CMAKE_EXE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS)
endif()
else()
message(FATAL_ERROR "LLVM_SPROFDATA_FILE can only be specified when compiling with clang")
endif()
endif()

option(LLVM_BUILD_INSTRUMENTED_COVERAGE "Build LLVM and tools with Code Coverage instrumentation" Off)
option(LLVM_INDIVIDUAL_TEST_COVERAGE "Emit individual coverage file for each test case." OFF)
mark_as_advanced(LLVM_BUILD_INSTRUMENTED_COVERAGE)
Expand Down
Loading