[flang][cmake][perf-training] Optimize flang with PGO and BOLT (#198863)

This is an attempt to replicate similar fearture already available to
clang. The changes in this patch were made with an intent to reuse as
much of existing infrastructure as possible. Namely, two-stage build
arrangement, perf-helper.py script and the means for building of the
instrumented binaries have all been incorporated into this approach.

It was deliberately chosen to optimize clang along with flang as they
are mostly working together in the final toolchain.

See the `llvm/docs/AdvancedBuilds.rst` documentation for more details.

Note that the attempt to optimize flang has exceeded one of the BOLT
limitations. The size of one of the statically allocated buffers needed
to be extended in this patch.
This commit is contained in:
Paul Osmialowski 2026-06-24 18:01:07 +01:00 committed by GitHub
parent 55b45709a8
commit 44409a06cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 496 additions and 24 deletions

View file

@ -813,11 +813,15 @@ if (CLANG_ENABLE_BOOTSTRAP)
if(LLVM_BUILD_INSTRUMENTED)
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)
set(PGO_OPT_SPROFDATA "${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.sprofdata" CACHE STRING "")
set(PGO_OPT_SPROFDATA_PROVIDER generate-sprofdata CACHE STRING "")
add_dependencies(clang-bootstrap-deps ${PGO_OPT_SPROFDATA_PROVIDER})
set(PGO_OPT -DLLVM_SPROFDATA_FILE=${PGO_OPT_SPROFDATA})
else()
add_dependencies(clang-bootstrap-deps generate-profdata)
set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata)
set(PGO_OPT_PROFDATA "${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata" CACHE STRING "")
set(PGO_OPT_PROFDATA_PROVIDER generate-profdata CACHE STRING "")
add_dependencies(clang-bootstrap-deps ${PGO_OPT_PROFDATA_PROVIDER})
set(PGO_OPT -DLLVM_PROFDATA_FILE=${PGO_OPT_PROFDATA})
endif()
# Use the current tools for LTO instead of the instrumented ones
list(APPEND _BOOTSTRAP_DEFAULT_PASSTHROUGH

View file

@ -0,0 +1,26 @@
# Two-stage build of Flang with the 2nd stage optimized using BOLT and PGO
set(BOLT_PGO_CMAKE_CACHE "PGO" CACHE STRING "")
set(LLVM_ENABLE_PROJECTS "bolt;clang;flang;lld" CACHE STRING "")
set(CLANG_BOOTSTRAP_TARGETS
stage2-clang-bolt
stage2-flang-bolt
stage2-check-clang
stage2-check-flang
stage2-distribution
stage2-install-distribution
CACHE STRING "")
set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS
clang-bolt
flang-bolt
check-clang
check-flang
distribution
install-distribution
CACHE STRING "")
set(PGO_BUILD_CONFIGURATION
${CMAKE_CURRENT_LIST_DIR}/BOLT.cmake
CACHE STRING "")
include(${CMAKE_CURRENT_LIST_DIR}/${BOLT_PGO_CMAKE_CACHE}.cmake)

View file

@ -0,0 +1,19 @@
# Two-stage build of Flang with the 2nd stage optimized using BOLT
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "")
set(CLANG_BOLT "INSTRUMENT" CACHE STRING "")
set(FLANG_BOLT ${CLANG_BOLT} CACHE STRING "")
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--emit-relocs,-znow" CACHE STRING "")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--emit-relocs,-znow" CACHE STRING "")
set(LLVM_ENABLE_PROJECTS "bolt;clang;flang" CACHE STRING "")
set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
# setup toolchain
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_DISTRIBUTION_COMPONENTS
clang
clang-resource-headers
flang
runtimes
CACHE STRING "")

View file

@ -0,0 +1,28 @@
# Second stage instrumentation (used by PGO.cmake)
set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
set(CLANG_BOOTSTRAP_TARGETS
distribution
install-distribution
install-distribution-toolchain
check-all
check-llvm
check-clang
check-flang
test-suite CACHE STRING "")
set(FLANG_PGO_TRAINING_CLANG_COUPLING ON CACHE BOOL "")
set(PGO_OPT_PROFDATA "${CMAKE_BINARY_DIR}/flang.profdata" CACHE STRING "")
set(PGO_OPT_PROFDATA_PROVIDER generate-flang-profdata CACHE STRING "")
if(PGO_BUILD_CONFIGURATION)
include(${PGO_BUILD_CONFIGURATION})
set(CLANG_BOOTSTRAP_CMAKE_ARGS
-C ${PGO_BUILD_CONFIGURATION}
CACHE STRING "")
else()
include(${CMAKE_CURRENT_LIST_DIR}/PGO-stage2.cmake)
set(CLANG_BOOTSTRAP_CMAKE_ARGS
-C ${CMAKE_CURRENT_LIST_DIR}/PGO-stage2.cmake
CACHE STRING "")
endif()

View file

@ -0,0 +1,4 @@
# Second stage of PGO (used by PGO-stage2-instrumented.cmake)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "")
set(LLVM_ENABLE_PROJECTS "clang;flang;lld" CACHE STRING "")

View file

@ -0,0 +1,37 @@
# Two-stage build of Flang with the 2nd stage optimized using PGO
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "")
set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
set(LLVM_ENABLE_PROJECTS "clang;flang;lld" CACHE STRING "")
set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED IR CACHE BOOL "")
set(CLANG_BOOTSTRAP_TARGETS
generate-flang-profdata
stage2
stage2-distribution
stage2-install-distribution
stage2-install-distribution-toolchain
stage2-check-all
stage2-check-llvm
stage2-check-clang
stage2-check-flang
stage2-test-suite CACHE STRING "")
set(FLANG_PGO_TRAINING_CLANG_COUPLING ON CACHE BOOL "")
set(PGO_OPT_PROFDATA "${CMAKE_BINARY_DIR}/flang.profdata" CACHE STRING "")
set(PGO_OPT_PROFDATA_PROVIDER generate-flang-profdata CACHE STRING "")
if(PGO_INSTRUMENT_LTO)
set(BOOTSTRAP_LLVM_ENABLE_LTO ${PGO_INSTRUMENT_LTO} CACHE BOOL "")
set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LTO ${PGO_INSTRUMENT_LTO} CACHE BOOL "")
endif()
if(PGO_BUILD_CONFIGURATION)
set(EXTRA_ARGS -DPGO_BUILD_CONFIGURATION=${PGO_BUILD_CONFIGURATION})
endif()
set(CLANG_BOOTSTRAP_CMAKE_ARGS
${EXTRA_ARGS}
-C ${CMAKE_CURRENT_LIST_DIR}/PGO-stage2-instrumented.cmake
CACHE STRING "")

View file

@ -1,3 +1,20 @@
set(FLANG_PGO_TRAINING_DATA_SOURCE_DIR OFF CACHE STRING "Path to source directory containing cmake project with source files to use for generating flang pgo data")
set(FLANG_PGO_TRAINING_DATA_SOURCE_CMAKE_ARGS "" CACHE STRING "Extra CMake flags to pass to the cmake project with source files to use for generating flang pgo data")
set(FLANG_PGO_TRAINING_DEPS "" CACHE STRING "Extra dependencies needed to build the PGO training data.")
set(FLANG_PGO_TRAINING_CLANG_COUPLING ON CACHE BOOL "Train clang and flang together")
if(FLANG_PGO_TRAINING_CLANG_COUPLING)
set(CLANG_PGO_TRAINING_DATA_SOURCE_DIR OFF CACHE STRING "Path to source directory containing cmake project with source files to use for generating clang pgo data")
set(CLANG_PGO_TRAINING_DATA_SOURCE_CMAKE_ARGS "" CACHE STRING "Extra CMake flags to pass to the cmake project with source files to use for generating clang pgo data")
endif()
set(PERF_HELPER "${LLVM_MAIN_SRC_DIR}/../clang/utils/perf-training/perf-helper.py")
add_custom_target(clear-flang-perf-data
COMMAND "${Python3_EXECUTABLE}" "${PERF_HELPER}" clean "${CMAKE_CURRENT_BINARY_DIR}" perf.data
COMMENT "Clearing old flang perf data")
option(FLANG_PGO_TRAINING_USE_LLVM_BUILD "Use LLVM build for generating PGO data" ON)
# Test runner infrastructure for Flang. This configures the Flang test trees
# for use by Lit, and delegates to LLVM's lit test handlers.
add_subdirectory(lib)
@ -22,6 +39,7 @@ option(FLANG_TEST_ENABLE_OPENMP "Force-enable tests that require modules from Op
llvm_canonicalize_cmake_booleans(
FLANG_STANDALONE_BUILD
FLANG_PGO_TRAINING_USE_LLVM_BUILD
LLVM_BYE_LINK_INTO_TOOLS
LLVM_ENABLE_PLUGINS
LLVM_INCLUDE_EXAMPLES
@ -51,6 +69,7 @@ else ()
set(PATHS_FOR_PLUGINS "SHLIBDIR")
endif ()
set(LIT_LOAD_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/test.lit.cfg")
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
@ -126,6 +145,23 @@ if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES AND NOT FLANG_STANDALONE_BUILD)
list(APPEND FLANG_TEST_DEPENDS flang-rt-test-deps)
endif ()
set(FLANG_BOLT_ALLOWLIST INSTRUMENT PERF LBR)
set(FLANG_BOLT OFF CACHE STRING "Apply BOLT optimization to flang. \
May be specified as one of ${FLANG_BOLT_ALLOWLIST} to use a particular profiling \
mechanism.")
set_property(CACHE FLANG_BOLT PROPERTY STRINGS OFF ${FLANG_BOLT_ALLOWLIST})
string(TOUPPER "${FLANG_BOLT}" FLANG_BOLT)
if (FLANG_BOLT AND NOT FLANG_BOLT IN_LIST FLANG_BOLT_ALLOWLIST)
message(FATAL_ERROR "Specified FLANG_BOLT value '${FLANG_BOLT}' is not one of ${FLANG_BOLT_ALLOWLIST}.")
endif()
if (FLANG_BOLT AND NOT LLVM_BUILD_INSTRUMENTED)
list(APPEND FLANG_TEST_DEPENDS
clear-flang-bolt-fdata
llvm-bolt
clang-bolt)
endif()
add_custom_target(flang-test-depends DEPENDS ${FLANG_TEST_DEPENDS})
set_target_properties(flang-test-depends PROPERTIES FOLDER "Flang/Meta")
@ -154,3 +190,177 @@ if (DEFINED FLANG_TEST_TARGET_TRIPLE)
"to use FLANG_TEST_TARGET_TRIPLE.")
endif()
endif()
include(LLVMExternalProjectUtils)
if(LLVM_BUILD_INSTRUMENTED)
set(CLANG_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/../../clang/utils/perf-training")
set(LIT_LOAD_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/pgo.lit.cfg")
configure_lit_site_cfg(
"${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in"
"${CMAKE_CURRENT_BINARY_DIR}/pgo-data/lit.site.cfg"
MAIN_CONFIG
"${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py"
)
add_lit_testsuite(generate-flang-profraw "Generating flang PGO data"
"${CMAKE_CURRENT_BINARY_DIR}/pgo-data/"
EXCLUDE_FROM_CHECK_ALL
DEPENDS ${FLANG_TEST_DEPENDS}
)
if(FLANG_PGO_TRAINING_CLANG_COUPLING)
add_lit_testsuite(generate-clang-profraw "Generating clang PGO data"
"${CLANG_CURRENT_BINARY_DIR}/pgo-data/"
EXCLUDE_FROM_CHECK_ALL
DEPENDS clang
)
endif()
add_custom_target(clear-flang-profraw
COMMAND "${Python3_EXECUTABLE}" "${PERF_HELPER}" clean "${CMAKE_CURRENT_BINARY_DIR}/.." "${CMAKE_BINARY_DIR}/profiles/" profraw
COMMENT "Clearing old flang profraw data")
if (FLANG_PGO_TRAINING_CLANG_COUPLING)
add_dependencies(clear-flang-profraw clear-profraw)
endif()
if(NOT LLVM_PROFDATA)
find_program(LLVM_PROFDATA llvm-profdata)
endif()
if(NOT LLVM_PROFDATA)
message(STATUS "To enable merging PGO data LLVM_PROFDATA has to point to llvm-profdata")
else()
set(PROFDATA "${CMAKE_BINARY_DIR}/flang.profdata")
set(PROFRAW_TARGETS "")
set(PROFRAW_DIRS "")
set(PROFRAW_DEPS "")
if(FLANG_PGO_TRAINING_CLANG_COUPLING)
list(APPEND PROFRAW_TARGETS generate-clang-profraw)
list(APPEND PROFRAW_DIRS "${CLANG_CURRENT_BINARY_DIR}")
list(APPEND PROFRAW_DEPS clang)
if (CLANG_PGO_TRAINING_DATA_SOURCE_DIR)
llvm_ExternalProject_Add(generate-clang-profraw-external
"${CLANG_PGO_TRAINING_DATA_SOURCE_DIR}"
USE_TOOLCHAIN
EXCLUDE_FROM_ALL
NO_INSTALL
CMAKE_ARGS "${CLANG_PGO_TRAINING_DATA_SOURCE_CMAKE_ARGS}")
list(APPEND PROFRAW_TARGETS generate-clang-profraw-external)
endif()
endif()
list(APPEND PROFRAW_TARGETS generate-flang-profraw)
list(APPEND PROFRAW_DIRS
"${CMAKE_CURRENT_BINARY_DIR}/.."
"${CMAKE_BINARY_DIR}/profiles/")
list(APPEND PROFRAW_DEPS
flang
flang-rt)
if (FLANG_PGO_TRAINING_DATA_SOURCE_DIR)
llvm_ExternalProject_Add(generate-flang-profraw-external
"${FLANG_PGO_TRAINING_DATA_SOURCE_DIR}"
USE_TOOLCHAIN
ENABLE_FORTRAN
EXCLUDE_FROM_ALL
NO_INSTALL
CMAKE_ARGS "${FLANG_PGO_TRAINING_DATA_SOURCE_CMAKE_ARGS}")
list(APPEND PROFRAW_TARGETS generate-flang-profraw-external)
endif()
add_custom_command(
OUTPUT "${PROFDATA}"
# PROFRAW_TARGETS are custom targets which are always considered stale.
# If we add them here to 'DEPENDS', then it will always execute and running
# ninja install && ninja check-all will result in the profile data being
# generated twice, and cause the ninja check-all build to fail with errors like:
# `ld.lld: error: Function Import: link error: linking module flags 'ProfileSummary': IDs have conflicting values in`
# Therefore we call these targets manually as part of this custom command,
# which will only run if flang or ${FLANG_PGO_TRAINING_DEPS} are updated.
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target ${PROFRAW_TARGETS}
COMMAND "${Python3_EXECUTABLE}" "${PERF_HELPER}" merge "${LLVM_PROFDATA}" "${PROFDATA}" ${PROFRAW_DIRS}
COMMENT "Merging flang profdata"
DEPENDS ${PROFRAW_DEPS} ${FLANG_PGO_TRAINING_DEPS} clear-flang-profraw
)
add_custom_target(generate-flang-profdata DEPENDS "${PROFDATA}")
if(FLANG_PGO_TRAINING_CLANG_COUPLING)
string(TOUPPER "${LLVM_BUILD_INSTRUMENTED}" LLVM_BUILD_UPPER_INSTRUMENTED)
if (LLVM_BUILD_UPPER_INSTRUMENTED STREQUAL "CSSPGO")
message(STATUS "CSSPGO of flang is not supported")
else()
add_dependencies(clang-bootstrap-deps generate-flang-profdata)
endif()
endif()
endif()
endif()
if (FLANG_BOLT AND NOT LLVM_BUILD_INSTRUMENTED)
# Add a flang-bolt target for backwards compatibility.
add_custom_target(flang-bolt DEPENDS flang-test-depends)
set(FLANG_BOLT_INSTRUMENTED "flang-bolt.inst" CACHE STRING
"Name of BOLT-instrumented flang binary")
set(FLANG_INSTRUMENTED "${LLVM_RUNTIME_OUTPUT_INTDIR}/${FLANG_BOLT_INSTRUMENTED}")
set(PERF_TRAINING_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(FLANG_BOLT_FDATA "${PERF_TRAINING_BINARY_DIR}/flang-prof.fdata")
get_llvm_lit_path(
lit_base_dir
lit_file_name
ALLOW_EXTERNAL
)
set(LIT_COMMAND "${lit_base_dir}/${lit_file_name}")
set(FLANG_BOLT_INPUTS "$<TARGET_FILE:flang>")
set(FLANG_INSTRUMENTED_OUTPUTS "${FLANG_INSTRUMENTED}")
# Add in dynamically linked libraries, if needs be. Currently only supported
# on Linux because it relies on LD_PRELOAD for instrumentation.
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
if (LLVM_LINK_LLVM_DYLIB)
set(LLVM_BOLT_INSTRUMENTED "LLVM-bolt.inst" CACHE STRING
"Name of BOLT-instrumented LLVM library")
set(LLVM_INSTRUMENTED "${LLVM_RUNTIME_OUTPUT_INTDIR}/${LLVM_BOLT_INSTRUMENTED}")
list(APPEND FLANG_BOLT_INPUTS "$<TARGET_FILE:LLVM>")
list(APPEND FLANG_INSTRUMENTED_OUTPUTS "${LLVM_INSTRUMENTED}")
endif()
endif()
# This POST_BUILD command is executed unconditionally even if the flang target
# is already built. We need to wrap the whole bolt optimization process in
# a single python wrapper, so that we can first check if the binary has
# already been optimized and then exit early with a 0 status if it has.
add_custom_command(
TARGET flang-test-depends POST_BUILD
COMMAND "${Python3_EXECUTABLE}" "${PERF_HELPER}"
bolt-optimize
--method "${FLANG_BOLT}"
--input "${FLANG_BOLT_INPUTS}"
--instrumented-output "${FLANG_INSTRUMENTED_OUTPUTS}"
--fdata "${FLANG_BOLT_FDATA}"
--perf-training-binary-dir "${PERF_TRAINING_BINARY_DIR}"
--readelf "$<TARGET_FILE:llvm-readobj>"
--bolt "$<TARGET_FILE:llvm-bolt>"
--lit "${LIT_COMMAND}"
--merge-fdata "$<TARGET_FILE:merge-fdata>"
COMMENT "Optimizing flang with BOLT"
USES_TERMINAL
VERBATIM
)
set(LIT_LOAD_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/bolt.lit.cfg")
configure_lit_site_cfg(
"${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in"
"${CMAKE_CURRENT_BINARY_DIR}/bolt-fdata/lit.site.cfg"
MAIN_CONFIG
"${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py"
)
add_lit_testsuite(generate-flang-bolt-fdata "Generating BOLT profile for flang"
"${CMAKE_CURRENT_BINARY_DIR}/bolt-fdata/"
EXCLUDE_FROM_CHECK_ALL
DEPENDS flang-test-depends clear-flang-bolt-fdata clear-flang-perf-data
)
add_custom_target(clear-flang-bolt-fdata
COMMAND "${Python3_EXECUTABLE}" "${PERF_HELPER}" clean "${CMAKE_CURRENT_BINARY_DIR}" fdata
COMMENT "Clearing old flang BOLT fdata")
endif()

View file

@ -5,18 +5,18 @@
! RUN: %flang -target aarch64-linux-gnu --no-offloadlib --offload-arch=sm_80 -xcuda %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK,CUDA
! Compiled as CUDA, device-compilation is done first
! CUDA: {{(^|[\\/])flang(-[0-9]+)?(\.exe)?}}" "-fc1" "-triple" "nvptx64-nvidia-cuda"
! CUDA: {{(^|[\\/])flang(-[0-9]+)?(-bolt\.inst)?(\.exe)?}}" "-fc1" "-triple" "nvptx64-nvidia-cuda"
! CUDA-SAME: "-foffload-device"
! Host invocation
! CHECK: {{(^|[\\/])flang(-[0-9]+)?(\.exe)?}}" "-fc1" "-triple" "aarch64-unknown-linux-gnu"
! CHECK: {{(^|[\\/])flang(-[0-9]+)?(-bolt\.inst)?(\.exe)?}}" "-fc1" "-triple" "aarch64-unknown-linux-gnu"
! CHECK-NOT: -foffload-device
! Compiled as OpenMP, device-code is compiled after host-code compilation,
! once for each --offload-arch argument
! OPENMP: {{(^|[\\/])flang(-[0-9]+)?(\.exe)?}}" "-fc1" "-triple" "amdgcn-amd-amdhsa"
! OPENMP: {{(^|[\\/])flang(-[0-9]+)?(-bolt\.inst)?(\.exe)?}}" "-fc1" "-triple" "amdgcn-amd-amdhsa"
! OPENMP-SAME: "-foffload-device"
! OPENMP: {{(^|[\\/])flang(-[0-9]+)?(\.exe)?}}" "-fc1" "-triple" "nvptx64-nvidia-cuda"
! OPENMP: {{(^|[\\/])flang(-[0-9]+)?(-bolt\.inst)?(\.exe)?}}" "-fc1" "-triple" "nvptx64-nvidia-cuda"
! OPENMP-SAME: "-foffload-device"

31
flang/test/bolt.lit.cfg Normal file
View file

@ -0,0 +1,31 @@
# -*- Python -*-
# Configuration used for performance training when optimizing flang with BOLT
import os
import lit.util
flang_bolt_mode = config.flang_bolt_mode.lower()
flang_binary = "flang"
perf_wrapper = f"{sys.executable} {config.perf_helper_dir}/perf-helper.py perf "
if flang_bolt_mode == "instrument":
perf_wrapper = ""
flang_binary = config.flang_bolt_name
elif flang_bolt_mode == "lbr":
perf_wrapper += " --lbr -- "
elif flang_bolt_mode == "perf":
perf_wrapper += " -- "
else:
assert 0, "Unsupported flang bolt mode"
flang_nowrapper = os.path.realpath(
lit.util.which(flang_binary, config.flang_opt_tools_dir)
).replace("\\", "/")
config.name = "Flang BOLT Training"
config.flang_exe = perf_wrapper + flang_nowrapper
config.llvm_profile_file = ''

View file

@ -15,9 +15,6 @@ from lit.llvm.subst import FindTool
# Configuration file for the 'lit' test runner.
# name: The name of this test suite.
config.name = "Flang"
# TODO: Consolidate the logic for turning on the internal shell by default for all LLVM test suites.
# See https://github.com/llvm/llvm-project/issues/106636 for more details.
#
@ -121,6 +118,12 @@ config.test_exec_root = os.path.join(config.flang_obj_root, "test")
llvm_config.with_environment("PATH", config.flang_tools_dir, append_path=True)
llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True)
if config.llvm_profile_file:
config.environment["LLVM_PROFILE_FILE"] = config.llvm_profile_file
llvm_config.with_environment(
"LLVM_PROFILE_FILE", config.llvm_profile_file, append_path=False
)
if config.flang_standalone_build:
# For builds with FIR, set path for tco and enable related tests
if config.flang_llvm_tools_dir != "":
@ -143,8 +146,7 @@ if config.default_sysroot:
host_triple = config.host_triple.split("-")
config.available_features.add(f"{host_triple[0]}-host")
flang_exe = lit.util.which("flang", config.flang_llvm_tools_dir)
if not flang_exe:
if not config.flang_exe:
lit_config.fatal(f"Could not identify flang executable")
# Intrinsic paths that are added implicitly by the `flang` driver, but have to be added manually when invoking the frontend `flang -fc1`.
@ -158,7 +160,11 @@ def get_resource_module_intrinsic_dir(modfile):
# Determine the intrinsic module search path that is added by the driver. If
# skipping the driver using -fc1, we need to append the path manually.
flang_intrinsics_dir = subprocess.check_output(
[flang_exe, *config.flang_test_fortran_flags, f"-print-file-name={modfile}"],
[
config.flang_exe,
*config.flang_test_fortran_flags,
f"-print-file-name={modfile}",
],
text=True,
).strip()
flang_intrinsics_dir = os.path.dirname(flang_intrinsics_dir)
@ -193,7 +199,7 @@ else:
)
lit_config.note(f"using flang: {flang_exe}")
lit_config.note(f"using flang: {config.flang_exe}")
lit_config.note(
f"using flang implicit search paths: {' '.join(flang_driver_search_args)}"
)
@ -210,13 +216,13 @@ tools = [
),
ToolSubst(
"%flang",
command=flang_exe,
command=config.flang_exe,
extra_args=flang_extra_search_args,
unresolved="fatal",
),
ToolSubst(
"%flang_fc1",
command=flang_exe,
command=config.flang_exe,
extra_args=["-fc1"] + flang_driver_search_args + flang_extra_search_args,
unresolved="fatal",
),

View file

@ -11,7 +11,7 @@ config.target_triple = "@LLVM_TARGET_TRIPLE@"
config.llvm_target_triple_env = "@LLVM_TARGET_TRIPLE_ENV@"
config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@"
config.flang_obj_root = "@FLANG_BINARY_DIR@"
config.flang_obj_root = path(r"@FLANG_BINARY_DIR@")
config.flang_tools_dir = lit_config.substitute("@FLANG_TOOLS_DIR@")
config.flang_headers_dir = "@HEADER_BINARY_DIR@"
config.flang_llvm_tools_dir = "@CMAKE_BINARY_DIR@/bin"
@ -30,8 +30,16 @@ config.default_sysroot = "@DEFAULT_SYSROOT@"
config.flang_runtime_f128_math_lib = "@FLANG_RUNTIME_F128_MATH_LIB@"
config.have_ldbl_mant_dig_113 = "@HAVE_LDBL_MANT_DIG_113@"
config.perf_helper_dir = "@LLVM_MAIN_SRC_DIR@/../clang/utils/perf-training"
config.flang_bolt_mode = "@FLANG_BOLT@"
config.flang_bolt_name = "@FLANG_BOLT_INSTRUMENTED@"
config.flang_opt_tools_dir = lit_config.substitute("@CURRENT_TOOLS_DIR@")
import lit.llvm
lit.llvm.initialize(lit_config, config)
# Let the detailed config do the details.
lit_config.load_config(config, "@LIT_LOAD_CONFIG@")
# Let the main config do the real work.
lit_config.load_config(config, "@FLANG_SOURCE_DIR@/test/lit.cfg.py")

11
flang/test/pgo.lit.cfg Normal file
View file

@ -0,0 +1,11 @@
# -*- Python -*-
# Configuration used for performance training when optimizing flang with PGO
import lit.util
config.name = 'Flang PGO Training'
config.flang_exe = lit.util.which('flang', config.flang_opt_tools_dir).replace('\\', '/')
config.llvm_profile_file = '../perf-training-%4m.profraw'

12
flang/test/test.lit.cfg Normal file
View file

@ -0,0 +1,12 @@
# -*- Python -*-
# Configuration used for running the test suite the usual way
import lit.util
# name: The name of this test suite.
config.name = "Flang"
config.flang_exe = lit.util.which("flang", config.flang_llvm_tools_dir)
config.llvm_profile_file = ''

View file

@ -21,10 +21,17 @@ generator.
Many of the build configurations mentioned on this documentation page can be
utilized by using a CMake cache. A CMake cache is essentially a configuration
file that sets the necessary flags for a specific build configuration. The caches
for Clang are located in :code:`/clang/cmake/caches` within the monorepo. They
can be passed to CMake using the :code:`-C` flag as demonstrated in the examples
below along with additional configuration flags.
file that sets the necessary flags for a specific build configuration.
The caches for Clang are located in :code:`/clang/cmake/caches` within the
monorepo. They can be passed to CMake using the :code:`-C` flag as demonstrated
in the examples below along with additional configuration flags.
The caches for Flang are located in :code:`/flang/cmake/caches` within the
monorepo. They can be passed to CMake using the :code:`-C` flag as demonstrated
in the examples below along with additional configuration flags. Due to the
Flang's heavy reliance on Clang, these caches ensure equal handling of Flang
and Clang, resulting in both being built within the same arrangement.
Bootstrap Builds
================
@ -132,6 +139,15 @@ configuration with CMake with the following command:
$ cmake -G Ninja -C <path to source>/clang/cmake/caches/PGO.cmake \
<path to source>/llvm
Similarly, to build optimized Flang (along with Clang), you can use the
following command:
.. code-block:: console
$ cmake -G Ninja -C <path to source>/flang/cmake/caches/PGO.cmake \
-DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt;libunwind;openmp" \
<path to source>/llvm
There are several additional options that the cache file also accepts to modify
the build, particularly the ``PGO_INSTRUMENT_LTO`` option. Setting this option to
Thin or Full will enable ThinLTO or full LTO respectively, further enhancing
@ -145,8 +161,8 @@ that also enables ThinLTO, use the following command:
-DPGO_INSTRUMENT_LTO=Thin \
<path to source>/llvm
By default, clang will generate profile data by compiling a simple
hello world program. You can also tell clang to use an external
By default, the compiler will generate profile data by compiling a simple
hello world program. You can also configure the use of an external
project for generating profile data that may be a better fit for your
use case. The project you specify must either be a lit test suite
(use the ``CLANG_PGO_TRAINING_DATA`` option) or a CMake project (use the
@ -162,6 +178,19 @@ profile data you would use the following command:
-DBOOTSTRAP_CLANG_PGO_TRAINING_DATA_SOURCE_DIR=<path to llvm-test-suite> \
-DBOOTSTRAP_CLANG_PGO_TRAINING_DEPS=runtimes
Similarly, to build optimized Flang (along with Clang), you can use the
following command:
.. code-block:: console
$ cmake -G Ninja -C <path to source>/clang/cmake/caches/PGO.cmake \
-DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt;libunwind;openmp" \
-DBOOTSTRAP_CLANG_PGO_TRAINING_DATA_SOURCE_DIR=<path to llvm-test-suite> \
-DBOOTSTRAP_CLANG_PGO_TRAINING_DEPS=runtimes \
-DBOOTSTRAP_FLANG_PGO_TRAINING_DATA_SOURCE_DIR=<path to llvm-test-suite> \
-DBOOTSTRAP_FLANG_PGO_TRAINING_DATA_SOURCE_CMAKE_ARGS="-DTEST_SUITE_SUBDIRS=Fortran" \
-DBOOTSTRAP_FLANG_PGO_TRAINING_DEPS=runtimes
The ``BOOTSTRAP\_`` prefix tells CMake to pass the variables on to the instrumented
stage two build. And the ``CLANG_PGO_TRAINING_DEPS`` option lets you specify
additional build targets to build before building the external project. The
@ -191,6 +220,12 @@ should be at a path something like:
<build dir>/tools/clang/stage2-instrumented-bins/utils/perf-training/clang.profdata
For Flang the profile data should be at a path something like:
.. code-block:: console
<build dir>/tools/clang/stage2-instrumented-bins/flang.profdata
You can feed that file into the ``LLVM_PROFDATA_FILE`` option when you build your
optimized compiler.
@ -202,6 +237,12 @@ variable for that purpose:
set(CLANG_PGO_TRAINING_DEPS builtins runtimes CACHE STRING "")
Similarly, for Flang you can make use of :code:`FLANG_PGO_TRAINING_DEPS`:
.. code-block:: cmake
set(FLANG_PGO_TRAINING_DEPS builtins runtimes CACHE STRING "")
The PGO cache has a slightly different stage naming scheme than other
multi-stage builds. It generates three stages: stage1, stage2-instrumented, and
stage2. Both of the stage2 builds are built using the stage1 compiler.
@ -226,6 +267,10 @@ The PGO cache generates the following additional targets:
**stage2-check-clang**
Depends on stage2 and runs check-clang using the stage2 compiler.
**stage2-check-flang**
Depends on stage2 and runs check-flang using the stage2 compiler (when using
the Flang's CMake caches)
**stage2-check-all**
Depends on stage2 and runs check-all using the stage2 compiler.
@ -256,6 +301,20 @@ Then, build the BOLT-optimized binary by running the following ninja command:
$ ninja clang-bolt
Similarly, to get both Flang and Clang optimized, use the following CMake
configuration:
.. code-block:: console
$ cmake <path to source>/llvm -C <path to source>/flang/cmake/caches/BOLT.cmake
Then, build the BOLT-optimized flang and clang binaries by running the following
ninja command:
.. code-block:: console
$ ninja flang-bolt
If you're seeing errors in the build process, try building with a recent
version of Clang/LLVM by setting the ``CMAKE_C_COMPILER`` and
``CMAKE_CXX_COMPILER`` flags to the appropriate values.
@ -279,6 +338,23 @@ Then, to build the final optimized binary, build the stage2-clang-bolt target:
$ ninja stage2-clang-bolt
Similarly, to get both Flang and Clang optimized, use the following CMake
configuration:
.. code-block:: console
$ cmake -G Ninja <path to source>/llvm \
-C <path to source>/flang/cmake/caches/BOLT-PGO.cmake \
-DBOOTSTRAP_LLVM_ENABLE_LLD=ON \
-DBOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LLD=ON \
-DPGO_INSTRUMENT_LTO=Thin
Then, to build the final optimized binaries, build the stage2-flang-bolt target:
.. code-block:: console
$ ninja stage2-flang-bolt
3-Stage Non-Determinism
=======================