Files
datastore/cmake/profile_optimization.cmake
Alexey Milovidov 804666f02d Demote PGO profile-mismatch warnings from -Werror in the BOLT build
`Build (BOLT)` failed on master because the BOLT-pass build, which
runs with `-fprofile-use=clickhouse-pgo.profdata`, emits
`-Wbackend-plugin` warnings of the form

    function control flow change detected (hash mismatch) <symbol>
        Hash = ... up to N count discarded

for functions whose CFG hash at use time does not match what was
recorded during the instrumented run, and the project-wide `-Werror`
makes them fatal.

  https://github.com/ClickHouse/ClickHouse/actions/runs/26198563312/job/77083370440

  Job report:
  https://s3.amazonaws.com/clickhouse-test-reports/json.html?REF=master&sha=8d1d74ce0bb6e52ff81e58af1b73a86e0b1f32be&name_0=OptimizeClickHouse&name_1=Collect%20ClickHouse%20Profiles%20%28PGO%2C%20BOLT%29%20%28aarch64%29

  Affected files in the failure: `src/Common/ConcurrencyControl.cpp`,
  `src/Common/Dwarf.cpp`, `src/Common/Exception.cpp` (the same kind of
  warning also appears for `base/glibc-compatibility/musl/exp.c`,
  `log.c`, `pow.c`, etc., but those are not under `-Werror` and so
  did not fail the build).

The instrumented build is required to disable ThinLTO (clang IR
instrumentation is incompatible with it; the cmake check enforces it),
while the BOLT build enables ThinLTO. ThinLTO can perturb individual
function bodies before profile matching, so a non-zero number of hash
mismatches is expected. The compiler simply drops the stale counts
for those functions and the rest of the profile is still applied —
which is the right behaviour for a best-effort optimisation pass.

Demote the warning to a plain warning specifically for the PGO-use
build by adding `-Wno-error=backend-plugin` alongside the
`-fprofile-use=...` flags, so mismatches stay visible in build logs
without breaking the build.
2026-05-21 02:14:17 +00:00

74 lines
3.7 KiB
CMake

# Support for Profile-Guided Optimization (PGO) and Binary Optimization and Layout Tool (BOLT)
# for the ClickHouse binary itself.
#
# PGO workflow:
# 1. Build with -DENABLE_CLICKHOUSE_PGO_GENERATE=ON (instrumented build)
# 2. Run representative workloads (performance tests)
# 3. Merge profiles: llvm-profdata merge -output=clickhouse.profdata *.profraw
# 4. Build with -DCLICKHOUSE_PGO_PROFILE_PATH=/path/to/clickhouse.profdata
#
# BOLT workflow (applied after linking):
# 1. Build with -DENABLE_CLICKHOUSE_BOLT=ON (adds --emit-relocs to linker flags)
# 2. Instrument: llvm-bolt clickhouse -instrument -o clickhouse.inst
# 3. Run workloads with instrumented binary
# 4. Merge: merge-fdata *.fdata > bolt.fdata
# 5. Optimize: llvm-bolt clickhouse -o clickhouse.bolt -data=bolt.fdata ...
# --- PGO: Profile Generation (instrumented build) ---
option(ENABLE_CLICKHOUSE_PGO_GENERATE
"Build ClickHouse with PGO instrumentation (-fprofile-generate). Incompatible with ThinLTO." OFF)
# --- PGO: Profile Use (optimized build) ---
set(CLICKHOUSE_PGO_PROFILE_PATH "" CACHE STRING
"Path to merged .profdata file for PGO-optimized build (-fprofile-use)")
# --- BOLT: Emit relocations for post-link optimization ---
option(ENABLE_CLICKHOUSE_BOLT
"Add --emit-relocs to linker flags so BOLT can post-process the binary" OFF)
# Validation
if (ENABLE_CLICKHOUSE_PGO_GENERATE AND CLICKHOUSE_PGO_PROFILE_PATH)
message(FATAL_ERROR "ENABLE_CLICKHOUSE_PGO_GENERATE and CLICKHOUSE_PGO_PROFILE_PATH are mutually exclusive")
endif()
if (ENABLE_CLICKHOUSE_PGO_GENERATE AND ENABLE_THINLTO)
message(FATAL_ERROR "ENABLE_CLICKHOUSE_PGO_GENERATE requires ENABLE_THINLTO=OFF (IR instrumentation is incompatible with ThinLTO)")
endif()
# Apply PGO generation flags
if (ENABLE_CLICKHOUSE_PGO_GENERATE)
message(STATUS "ClickHouse PGO: instrumented build enabled (-fprofile-generate)")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-generate")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-generate")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-generate")
endif()
# Apply PGO use flags
if (CLICKHOUSE_PGO_PROFILE_PATH)
if (NOT EXISTS "${CLICKHOUSE_PGO_PROFILE_PATH}")
message(FATAL_ERROR "PGO profile not found: ${CLICKHOUSE_PGO_PROFILE_PATH}")
endif()
message(STATUS "ClickHouse PGO: using profile ${CLICKHOUSE_PGO_PROFILE_PATH}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-use=${CLICKHOUSE_PGO_PROFILE_PATH}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-use=${CLICKHOUSE_PGO_PROFILE_PATH}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-use=${CLICKHOUSE_PGO_PROFILE_PATH}")
# When a function's CFG hash at use time does not match what was recorded
# in the profile, clang's PGO backend emits `-Wbackend-plugin` with text
# like "function control flow change detected (hash mismatch)" and
# discards the stale counts for that function. This is expected to
# happen for some functions because the instrumented build runs without
# ThinLTO (required by IR instrumentation) while the use build enables
# ThinLTO, which can perturb individual function bodies before profile
# matching. Under the project-wide `-Werror` policy these informational
# warnings would otherwise abort the whole build, so demote them to
# plain warnings here.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=backend-plugin")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=backend-plugin")
endif()
# Apply BOLT linker flags
if (ENABLE_CLICKHOUSE_BOLT)
message(STATUS "ClickHouse BOLT: adding --emit-relocs for post-link optimization")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--emit-relocs")
endif()