Skip to content

Commit a3a8054

Browse files
committed
[Clang][CMake] Add CSSPGO support to LLVM_BUILD_INSTRUMENTED
Build on Clang-BOLT infrastructure to collect sample profiles for CSSPGO. Add clang/cmake/caches/CSSPGO.cmake to automate CSSPGO Clang build. Differential Revision: https://reviews.llvm.org/D155419
1 parent bbca451 commit a3a8054

File tree

8 files changed

+127
-21
lines changed

8 files changed

+127
-21
lines changed

clang/CMakeLists.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,11 +744,22 @@ if (CLANG_ENABLE_BOOTSTRAP)
744744
if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
745745
add_dependencies(clang-bootstrap-deps llvm-profdata)
746746
set(PGO_OPT -DLLVM_PROFDATA=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profdata)
747+
string(TOUPPER "${BOOTSTRAP_LLVM_BUILD_INSTRUMENTED}" BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
748+
if (BOOTSTRAP_LLVM_BUILD_INSTRUMENTED STREQUAL "CSSPGO")
749+
add_dependencies(clang-bootstrap-deps llvm-profgen)
750+
list(APPEND PGO_OPT -DLLVM_PROFGEN=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profgen)
751+
endif()
747752
endif()
748753

749754
if(LLVM_BUILD_INSTRUMENTED)
750-
add_dependencies(clang-bootstrap-deps generate-profdata)
751-
set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata)
755+
string(TOUPPER "${LLVM_BUILD_INSTRUMENTED}" LLVM_BUILD_INSTRUMENTED)
756+
if (LLVM_BUILD_INSTRUMENTED STREQUAL "CSSPGO")
757+
add_dependencies(clang-bootstrap-deps generate-sprofdata)
758+
set(PGO_OPT -DLLVM_SPROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.sprofdata)
759+
else()
760+
add_dependencies(clang-bootstrap-deps generate-profdata)
761+
set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata)
762+
endif()
752763
# Use the current tools for LTO instead of the instrumented ones
753764
list(APPEND _BOOTSTRAP_DEFAULT_PASSTHROUGH
754765
CMAKE_CXX_COMPILER

clang/cmake/caches/BOLT-CSSPGO.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
set(BOLT_PGO_CMAKE_CACHE "CSSPGO" CACHE STRING "")
2+
set(BOOTSTRAP_CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
3+
include(${CMAKE_CURRENT_LIST_DIR}/BOLT-PGO.cmake)

clang/cmake/caches/BOLT-PGO.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
set(BOLT_PGO_CMAKE_CACHE "PGO" CACHE STRING "")
12
set(LLVM_ENABLE_PROJECTS "bolt;clang;lld" CACHE STRING "")
23

34
set(CLANG_BOOTSTRAP_TARGETS
@@ -14,4 +15,4 @@ set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS
1415
set(PGO_BUILD_CONFIGURATION
1516
${CMAKE_CURRENT_LIST_DIR}/BOLT.cmake
1617
CACHE STRING "")
17-
include(${CMAKE_CURRENT_LIST_DIR}/PGO.cmake)
18+
include(${CMAKE_CURRENT_LIST_DIR}/${BOLT_PGO_CMAKE_CACHE}.cmake)

clang/cmake/caches/CSSPGO.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED "CSSPGO" CACHE STRING "")
2+
include(${CMAKE_CURRENT_LIST_DIR}/PGO.cmake)

clang/utils/perf-training/CMakeLists.txt

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ set(CLANG_PGO_TRAINING_DATA "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH
66
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")
77
set(CLANG_PGO_TRAINING_DEPS "" CACHE STRING "Extra dependencies needed to build the PGO training data.")
88

9+
add_custom_target(clear-perf-data
10+
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} perf.data
11+
COMMENT "Clearing old perf data")
12+
913
if(LLVM_BUILD_INSTRUMENTED)
1014
configure_lit_site_cfg(
1115
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
@@ -15,7 +19,7 @@ if(LLVM_BUILD_INSTRUMENTED)
1519
add_lit_testsuite(generate-profraw "Generating clang PGO data"
1620
${CMAKE_CURRENT_BINARY_DIR}/pgo-data/
1721
EXCLUDE_FROM_CHECK_ALL
18-
DEPENDS clear-profraw
22+
DEPENDS clear-profraw clang
1923
)
2024

2125
add_custom_target(clear-profraw
@@ -49,6 +53,32 @@ if(LLVM_BUILD_INSTRUMENTED)
4953
USE_TOOLCHAIN EXLUDE_FROM_ALL NO_INSTALL DEPENDS generate-profraw)
5054
add_dependencies(generate-profdata generate-profraw-external)
5155
endif()
56+
57+
if(NOT LLVM_PROFGEN)
58+
find_program(LLVM_PROFGEN llvm-profgen)
59+
endif()
60+
61+
if(NOT LLVM_PROFGEN)
62+
message(STATUS "To enable converting CSSPGO samples LLVM_PROFGEN has to point to llvm-profgen")
63+
elseif(NOT CLANG_PGO_TRAINING_DATA_SOURCE_DIR)
64+
message(STATUS "CLANG_PGO_TRAINING_DATA_SOURCE_DIR must be set to collect CSSPGO samples")
65+
else()
66+
set(PERF_HELPER "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py)
67+
set(CLANG_SPROFDATA ${CMAKE_CURRENT_BINARY_DIR}/clang.sprofdata)
68+
add_custom_command(
69+
OUTPUT ${CLANG_SPROFDATA}
70+
# Execute generate-profraw-external under perf
71+
COMMAND ${PERF_HELPER} perf --csspgo -- ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target generate-profraw-external
72+
# Convert perf profile into profraw
73+
COMMAND ${PERF_HELPER} perf2prof ${LLVM_PROFGEN} $<TARGET_FILE:clang> ${CMAKE_CURRENT_BINARY_DIR}
74+
# Merge profdata
75+
COMMAND ${PERF_HELPER} merge --sample ${LLVM_PROFDATA} ${CLANG_SPROFDATA} ${CMAKE_CURRENT_BINARY_DIR}
76+
DEPENDS clang ${CLANG_PGO_TRAINING_DEPS} clear-perf-data generate-profraw-external-clean
77+
VERBATIM
78+
USES_TERMINAL
79+
)
80+
add_custom_target(generate-sprofdata DEPENDS ${CLANG_SPROFDATA})
81+
endif()
5282
endif()
5383
endif()
5484

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

103-
add_custom_target(clear-perf-data
104-
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} perf.data
105-
COMMENT "Clearing old perf data")
106-
107133
string(TOUPPER "${CLANG_BOLT}" CLANG_BOLT)
108134
if (CLANG_BOLT STREQUAL "LBR")
109135
set(BOLT_LBR "--lbr")

clang/utils/perf-training/perf-helper.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,29 @@ def clean(args):
3636
+ "\tRemoves all files with extension from <path>."
3737
)
3838
return 1
39-
for path in args[1:-1]:
39+
for path in args[:-1]:
4040
for filename in findFilesWithExtension(path, args[-1]):
4141
os.remove(filename)
4242
return 0
4343

4444

4545
def merge(args):
46-
if len(args) < 3:
47-
print(
48-
"Usage: %s merge <llvm-profdata> <output> <paths>\n" % __file__
49-
+ "\tMerges all profraw files from path into output."
50-
)
51-
return 1
52-
cmd = [args[0], "merge", "-o", args[1]]
53-
for path in args[2:]:
46+
parser = argparse.ArgumentParser(
47+
prog="perf-helper merge",
48+
description="Merges all profraw files from path(s) into output",
49+
)
50+
parser.add_argument("profdata", help="Path to llvm-profdata tool")
51+
parser.add_argument("output", help="Output filename")
52+
parser.add_argument(
53+
"paths", nargs="+", help="Folder(s) containing input profraw files"
54+
)
55+
parser.add_argument("--sample", action="store_true", help="Sample profile")
56+
opts = parser.parse_args(args)
57+
58+
cmd = [opts.profdata, "merge", "-o", opts.output]
59+
if opts.sample:
60+
cmd += ["--sample"]
61+
for path in opts.paths:
5462
cmd.extend(findFilesWithExtension(path, "profraw"))
5563
subprocess.check_call(cmd)
5664
return 0
@@ -71,25 +79,32 @@ def merge_fdata(args):
7179

7280
def perf(args):
7381
parser = argparse.ArgumentParser(
74-
prog="perf-helper perf", description="perf wrapper for BOLT profile collection"
82+
prog="perf-helper perf",
83+
description="perf wrapper for BOLT/CSSPGO profile collection",
7584
)
7685
parser.add_argument(
7786
"--lbr", action="store_true", help="Use perf with branch stacks"
7887
)
88+
parser.add_argument(
89+
"--csspgo", action="store_true", help="Enable CSSPGO flags"
90+
)
7991
parser.add_argument("cmd", nargs=argparse.REMAINDER, help="")
8092

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

96+
event = "br_inst_retired.near_taken:uppp" if opts.csspgo else "cycles:u"
8497
perf_args = [
8598
"perf",
8699
"record",
87-
"--event=cycles:u",
100+
f"--event={event}",
88101
"--freq=max",
89102
"--output=%d.perf.data" % os.getpid(),
90103
]
91-
if opts.lbr:
104+
if opts.lbr or opts.csspgo:
92105
perf_args += ["--branch-filter=any,u"]
106+
if opts.csspgo:
107+
perf_args += ["-g", "--call-graph=fp"]
93108
perf_args.extend(cmd)
94109

95110
start_time = time.time()
@@ -125,6 +140,26 @@ def perf2bolt(args):
125140
return 0
126141

127142

143+
def perf2prof(args):
144+
parser = argparse.ArgumentParser(
145+
prog="perf-helper perf2prof",
146+
description="perf to CSSPGO prof conversion wrapper",
147+
)
148+
parser.add_argument("profgen", help="Path to llvm-profgen binary")
149+
parser.add_argument("binary", help="Input binary")
150+
parser.add_argument("paths", nargs="+", help="Path containing perf.data files")
151+
opts = parser.parse_args(args)
152+
153+
profgen_args = [opts.profgen, f"--binary={opts.binary}"]
154+
for path in opts.paths:
155+
for filename in findFilesWithExtension(path, "perf.data"):
156+
subprocess.check_call(
157+
profgen_args
158+
+ [f"--perfdata={filename}", f"--output={filename}.profraw"]
159+
)
160+
return 0
161+
162+
128163
def dtrace(args):
129164
parser = argparse.ArgumentParser(
130165
prog="perf-helper dtrace",
@@ -567,6 +602,7 @@ def genOrderFile(args):
567602
"merge-fdata": merge_fdata,
568603
"perf": perf,
569604
"perf2bolt": perf2bolt,
605+
"perf2prof": perf2prof,
570606
}
571607

572608

llvm/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,9 @@ set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ${LLVM_ENABLE_PER_TARGET_RUNTIME_DIR_defa
948948
set(LLVM_PROFDATA_FILE "" CACHE FILEPATH
949949
"Profiling data file to use when compiling in order to improve runtime performance.")
950950

951+
set(LLVM_SPROFDATA_FILE "" CACHE FILEPATH
952+
"Sampling profiling data file to use when compiling in order to improve runtime performance.")
953+
951954
if(LLVM_INCLUDE_TESTS)
952955
# All LLVM Python files should be compatible down to this minimum version.
953956
set(LLVM_MINIMUM_PYTHON_VERSION 3.8)

llvm/cmake/modules/HandleLLVMOptions.cmake

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ endif()
11341134
option(LLVM_ENABLE_IR_PGO "Build LLVM and tools with IR PGO instrumentation (deprecated)" Off)
11351135
mark_as_advanced(LLVM_ENABLE_IR_PGO)
11361136

1137-
set(LLVM_BUILD_INSTRUMENTED OFF CACHE STRING "Build LLVM and tools with PGO instrumentation. May be specified as IR or Frontend")
1137+
set(LLVM_BUILD_INSTRUMENTED OFF CACHE STRING "Build LLVM and tools with PGO instrumentation. May be specified as IR, Frontend, CSIR, CSSPGO")
11381138
set(LLVM_VP_COUNTERS_PER_SITE "1.5" CACHE STRING "Value profile counters to use per site for IR PGO with Clang")
11391139
mark_as_advanced(LLVM_BUILD_INSTRUMENTED LLVM_VP_COUNTERS_PER_SITE)
11401140
string(TOUPPER "${LLVM_BUILD_INSTRUMENTED}" uppercase_LLVM_BUILD_INSTRUMENTED)
@@ -1167,6 +1167,15 @@ if (LLVM_BUILD_INSTRUMENTED)
11671167
CMAKE_EXE_LINKER_FLAGS
11681168
CMAKE_SHARED_LINKER_FLAGS)
11691169
endif()
1170+
elseif(uppercase_LLVM_BUILD_INSTRUMENTED STREQUAL "CSSPGO")
1171+
append("-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-optimize-sibling-calls -fpseudo-probe-for-profiling"
1172+
CMAKE_CXX_FLAGS
1173+
CMAKE_C_FLAGS)
1174+
if(NOT LINKER_IS_LLD_LINK)
1175+
append("-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-optimize-sibling-calls -fpseudo-probe-for-profiling"
1176+
CMAKE_EXE_LINKER_FLAGS
1177+
CMAKE_SHARED_LINKER_FLAGS)
1178+
endif()
11701179
else()
11711180
append("-fprofile-instr-generate=\"${LLVM_PROFILE_FILE_PATTERN}\""
11721181
CMAKE_CXX_FLAGS
@@ -1217,6 +1226,21 @@ if(LLVM_PROFDATA_FILE AND EXISTS ${LLVM_PROFDATA_FILE})
12171226
endif()
12181227
endif()
12191228

1229+
if(LLVM_SPROFDATA_FILE AND EXISTS ${LLVM_SPROFDATA_FILE})
1230+
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
1231+
append("-fpseudo-probe-for-profiling -fprofile-sample-use=\"${LLVM_SPROFDATA_FILE}\""
1232+
CMAKE_CXX_FLAGS
1233+
CMAKE_C_FLAGS)
1234+
if(NOT LINKER_IS_LLD_LINK)
1235+
append("-fpseudo-probe-for-profiling -fprofile-sample-use=\"${LLVM_SPROFDATA_FILE}\""
1236+
CMAKE_EXE_LINKER_FLAGS
1237+
CMAKE_SHARED_LINKER_FLAGS)
1238+
endif()
1239+
else()
1240+
message(FATAL_ERROR "LLVM_SPROFDATA_FILE can only be specified when compiling with clang")
1241+
endif()
1242+
endif()
1243+
12201244
option(LLVM_BUILD_INSTRUMENTED_COVERAGE "Build LLVM and tools with Code Coverage instrumentation" Off)
12211245
option(LLVM_INDIVIDUAL_TEST_COVERAGE "Emit individual coverage file for each test case." OFF)
12221246
mark_as_advanced(LLVM_BUILD_INSTRUMENTED_COVERAGE)

0 commit comments

Comments
 (0)