https://github.com/pawosm-arm updated 
https://github.com/llvm/llvm-project/pull/198863

>From 1c68cfd7a80770015fb66dd622a62bcf9936214a Mon Sep 17 00:00:00 2001
From: Paul Osmialowski <[email protected]>
Date: Mon, 11 May 2026 08:11:25 +0000
Subject: [PATCH] [flang][cmake][perf-training] Optimize flang with PGO and
 BOLT

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 flang/cmake/caches/README.txt 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.
---
 bolt/runtime/common.h                         |   2 +-
 clang/CMakeLists.txt                          |  12 +-
 flang/cmake/caches/BOLT-PGO.cmake             |  20 ++
 flang/cmake/caches/BOLT.cmake                 |  17 ++
 .../caches/PGO-stage2-instrumented.cmake      |  26 +++
 flang/cmake/caches/PGO-stage2.cmake           |   2 +
 flang/cmake/caches/PGO.cmake                  |  35 +++
 flang/cmake/caches/README.txt                 | 100 ++++++++
 flang/test/CMakeLists.txt                     | 213 ++++++++++++++++++
 flang/test/Driver/compiler-options.f90        |   2 +-
 flang/test/bolt.lit.cfg                       |  72 ++++++
 flang/test/lit.cfg.py                         |  69 ++----
 flang/test/lit.site.cfg.py.in                 |  11 +-
 flang/test/pgo.lit.cfg                        |  53 +++++
 flang/test/test.lit.cfg                       |  57 +++++
 15 files changed, 628 insertions(+), 63 deletions(-)
 create mode 100644 flang/cmake/caches/BOLT-PGO.cmake
 create mode 100644 flang/cmake/caches/BOLT.cmake
 create mode 100644 flang/cmake/caches/PGO-stage2-instrumented.cmake
 create mode 100644 flang/cmake/caches/PGO-stage2.cmake
 create mode 100644 flang/cmake/caches/PGO.cmake
 create mode 100644 flang/cmake/caches/README.txt
 create mode 100644 flang/test/bolt.lit.cfg
 create mode 100644 flang/test/pgo.lit.cfg
 create mode 100644 flang/test/test.lit.cfg

diff --git a/bolt/runtime/common.h b/bolt/runtime/common.h
index 8689bc8b72041..47ff189f64af9 100644
--- a/bolt/runtime/common.h
+++ b/bolt/runtime/common.h
@@ -162,7 +162,7 @@ struct timespec {
 #error "For AArch64/ARM64,X86_64 AND RISCV64 only."
 #endif
 
-constexpr uint32_t BufSize = 10240;
+constexpr uint32_t BufSize = 20480U;
 
 // Helper functions for writing strings to the .fdata file. We intentionally
 // avoid using libc names to make it clear it is our impl.
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index 40506fc8a1546..022899cf67fe4 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -806,11 +806,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
diff --git a/flang/cmake/caches/BOLT-PGO.cmake 
b/flang/cmake/caches/BOLT-PGO.cmake
new file mode 100644
index 0000000000000..a709171591741
--- /dev/null
+++ b/flang/cmake/caches/BOLT-PGO.cmake
@@ -0,0 +1,20 @@
+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-distribution
+  stage2-install-distribution
+  CACHE STRING "")
+set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS
+  clang-bolt
+  flang-bolt
+  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)
diff --git a/flang/cmake/caches/BOLT.cmake b/flang/cmake/caches/BOLT.cmake
new file mode 100644
index 0000000000000..b767daab287e8
--- /dev/null
+++ b/flang/cmake/caches/BOLT.cmake
@@ -0,0 +1,17 @@
+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 "")
diff --git a/flang/cmake/caches/PGO-stage2-instrumented.cmake 
b/flang/cmake/caches/PGO-stage2-instrumented.cmake
new file mode 100644
index 0000000000000..334ab4a0e188d
--- /dev/null
+++ b/flang/cmake/caches/PGO-stage2-instrumented.cmake
@@ -0,0 +1,26 @@
+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()
diff --git a/flang/cmake/caches/PGO-stage2.cmake 
b/flang/cmake/caches/PGO-stage2.cmake
new file mode 100644
index 0000000000000..8792d811563b8
--- /dev/null
+++ b/flang/cmake/caches/PGO-stage2.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "")
+set(LLVM_ENABLE_PROJECTS "clang;flang;lld" CACHE STRING "")
diff --git a/flang/cmake/caches/PGO.cmake b/flang/cmake/caches/PGO.cmake
new file mode 100644
index 0000000000000..d72bcf6ce9c74
--- /dev/null
+++ b/flang/cmake/caches/PGO.cmake
@@ -0,0 +1,35 @@
+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 "")
diff --git a/flang/cmake/caches/README.txt b/flang/cmake/caches/README.txt
new file mode 100644
index 0000000000000..1a4f24d60ca73
--- /dev/null
+++ b/flang/cmake/caches/README.txt
@@ -0,0 +1,100 @@
+CMake Caches
+============
+
+This directory contains CMake cache scripts that pre-populate the CMakeCache in
+a build directory with commonly used settings.
+
+You can use the caches files with the following CMake invocation:
+
+cmake -G <build system>
+  -C <path to cache file>
+  [additional CMake options (i.e. -DCMAKE_INSTALL_PREFIX=<install path>)]
+  <path to llvm>
+
+Options specified on the command line will override options in the cache files.
+
+The following cache files exist.
+
+BOLT
+----
+
+The post-link binaries optimization using runtime profiling. Note that the
+dependencies for optimizing flang were deliberately set to optimize clang too.
+You can configure your build directory with the following invocation of CMake:
+
+cmake -G <generator> -C <path_to_flang>/cmake/caches/BOLT.cmake <source dir>
+
+After configuration the following additional targets will be generated:
+
+clang-bolt:
+After building clang, it will be executed over the training test suite and
+optimized with BOLT.
+
+flang-bolt:
+After building clang and flang, they will be executed over the training test
+suite and optimized with BOLT.
+
+PGO
+---
+
+The PGO CMake cache can be used to generate a multi-stage instrumented 
compiler.
+You can configure your build directory with the following invocation of CMake:
+
+cmake -G <generator> -C <path_to_clang>/cmake/caches/PGO.cmake <source dir>
+
+After configuration the following additional targets will be generated:
+
+stage2-instrumented:
+Builds a stage1 compiler, runtime, and required tools (llvm-config,
+llvm-profdata) then uses that compiler to build an instrumented stage2 
compiler.
+
+stage2-instrumented-generate-profdata:
+Depends on "stage2-instrumented" and will use the instrumented compiler to
+generate profdata based on the training files.
+
+stage2:
+Depends on "stage2-instrumented-generate-profdata" and will use the stage1
+compiler with the stage2 profdata to build a PGO-optimized compiler.
+
+BOLT-PGO
+--------
+
+This combines both BOLT and PGO for better optimization. Note that the
+dependencies for optimizing flang were deliberately set to optimize clang too.
+You can configure your build directory with the following invocation of CMake:
+
+cmake -G <generator> <source dir> \
+    -C <path_to_flang>/cmake/caches/BOLT-PGO.cmake \
+    -DBOOTSTRAP_LLVM_ENABLE_LLD=ON \
+    -DBOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LLD=ON \
+    -DPGO_INSTRUMENT_LTO=Thin
+
+After configuration the following additional targets will be generated:
+
+stage2-clang-bolt:
+After doing PGO optimization, the PGO-optimized clang binary is being bolted.
+
+stage2-flang-bolt:
+After doing PGO optimization, the PGO-optimized clang and flang binaries are
+being bolted.
+
+Using an external test suite
+----------------------------
+
+An external test suite (namely, llvm-test-suite) can be used in order to 
provide
+a larger set of training data. It can be configured for training clang, flang,
+or both. For example:
+
+$ cmake -G Ninja $HOME/llvm-project/llvm \
+    -C $HOME/llvm-project/flang/cmake/caches/BOLT-PGO.cmake \
+    -DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt;libunwind;openmp" \
+    -DBOOTSTRAP_LLVM_ENABLE_LLD=ON \
+    -DBOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LLD=ON \
+    -DBOOTSTRAP_CLANG_PGO_TRAINING_DATA_SOURCE_DIR=$HOME/llvm-test-suite \
+    -DBOOTSTRAP_CLANG_PGO_TRAINING_DEPS=llvm-size \
+    -DBOOTSTRAP_FLANG_PGO_TRAINING_DATA_SOURCE_DIR=$HOME/llvm-test-suite \
+    
-DBOOTSTRAP_FLANG_PGO_TRAINING_DATA_SOURCE_CMAKE_ARGS="-DTEST_SUITE_SUBDIRS=Fortran"
 \
+    -DBOOTSTRAP_FLANG_PGO_TRAINING_DEPS=llvm-size \
+    -DPGO_INSTRUMENT_LTO=Thin
+
+$ ninja stage2-flang-bolt
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index d3da00c755cf8..48ed450a7d66c 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -1,9 +1,27 @@
+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)
 
 llvm_canonicalize_cmake_booleans(
   FLANG_STANDALONE_BUILD
+  FLANG_PGO_TRAINING_USE_LLVM_BUILD
   LLVM_BYE_LINK_INTO_TOOLS
   LLVM_ENABLE_PLUGINS
   LLVM_INCLUDE_EXAMPLES
@@ -31,6 +49,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
@@ -105,6 +124,25 @@ if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES AND NOT 
FLANG_STANDALONE_BUILD)
   list(APPEND FLANG_TEST_DEPENDS "libomp-mod")
 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.")
+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)
+  if (NOT FLANG_BOLT STREQUAL "INSTRUMENT")
+    list(APPEND FLANG_BOLT_DEPS clear-flang-perf-data)
+  endif()
+endif()
+
 add_custom_target(flang-test-depends DEPENDS ${FLANG_TEST_DEPENDS})
 set_target_properties(flang-test-depends PROPERTIES FOLDER "Flang/Meta")
 
@@ -133,3 +171,178 @@ 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}" 
${LLVM_MAIN_SRC_DIR}/../clang/utils/perf-training/perf-helper.py
+             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()
diff --git a/flang/test/Driver/compiler-options.f90 
b/flang/test/Driver/compiler-options.f90
index b9ecbbda227d1..7d133730da4c9 100644
--- a/flang/test/Driver/compiler-options.f90
+++ b/flang/test/Driver/compiler-options.f90
@@ -1,6 +1,6 @@
 ! RUN: %flang -S -emit-llvm -o - %s | FileCheck %s
 ! Test communication of COMPILER_OPTIONS from flang to flang -fc1.
-! CHECK: [[OPTSVAR:@_QQclX[0-9a-f]+]] = {{[a-z]+}} constant 
[[[OPTSLEN:[0-9]+]] x i8] c"{{.*}}flang{{(\.exe)?}} {{.*}}-S -emit-llvm -o - 
{{.*}}compiler-options.f90"
+! CHECK: [[OPTSVAR:@_QQclX[0-9a-f]+]] = {{[a-z]+}} constant 
[[[OPTSLEN:[0-9]+]] x i8] c"{{.*}}flang{{(-bolt\.inst)?}}{{(\.exe)?}} {{.*}}-S 
-emit-llvm -o - {{.*}}compiler-options.f90"
 program main
     use ISO_FORTRAN_ENV, only: compiler_options
     implicit none
diff --git a/flang/test/bolt.lit.cfg b/flang/test/bolt.lit.cfg
new file mode 100644
index 0000000000000..0e0774f530c95
--- /dev/null
+++ b/flang/test/bolt.lit.cfg
@@ -0,0 +1,72 @@
+# -*- Python -*-
+
+import os
+
+import lit.util
+
+from lit.llvm.subst import ToolSubst
+
+flang_bolt_mode = config.flang_bolt_mode.lower()
+flang_binary = "flang"
+perf_wrapper = f"{config.python3_exe} {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.flang = perf_wrapper + flang_nowrapper
+
+config.name = "Flang BOLT Training"
+config.suffixes = [
+    ".f",
+    ".F",
+    ".ff",
+    ".FOR",
+    ".for",
+    ".f77",
+    ".f90",
+    ".F90",
+    ".ff90",
+    ".f95",
+    ".F95",
+    ".ff95",
+    ".fpp",
+    ".FPP",
+    ".cuf",
+    ".CUF",
+    ".f18",
+    ".F18",
+    ".f03",
+    ".F03",
+    ".f08",
+    ".F08",
+    ".fir",
+    ".mlir",
+]
+
+config.llvm_profile_file = ''
+
+# For each occurrence of a flang tool name, replace it with the full path to
+# the build directory holding that tool.
+config.tools = [
+    ToolSubst(
+        "%flang",
+        command=config.flang,
+        unresolved="fatal",
+    ),
+    ToolSubst(
+        "%flang_fc1",
+        command=config.flang,
+        extra_args=["-fc1"],
+        unresolved="fatal",
+    ),
+]
diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 3a87f9ea06803..7af9fe072d8fe 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -15,9 +15,6 @@
 
 # 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.
 #
@@ -35,38 +32,6 @@
 # the test runner updated.
 config.test_format = lit.formats.ShTest(execute_external=not use_lit_shell)
 
-# suffixes: A list of file extensions to treat as test files.
-config.suffixes = [
-    ".c",
-    ".cpp",
-    ".f",
-    ".F",
-    ".ff",
-    ".FOR",
-    ".for",
-    ".f77",
-    ".f90",
-    ".F90",
-    ".ff90",
-    ".f95",
-    ".F95",
-    ".ff95",
-    ".fpp",
-    ".FPP",
-    ".cuf",
-    ".CUF",
-    ".f18",
-    ".F18",
-    ".f03",
-    ".F03",
-    ".f08",
-    ".F08",
-    ".ll",
-    ".fir",
-    ".mlir",
-    ".s",
-]
-
 config.substitutions.append(("%PATH%", config.environment["PATH"]))
 config.substitutions.append(("%llvmshlibdir", config.llvm_shlib_dir))
 config.substitutions.append(("%pluginext", config.llvm_plugin_ext))
@@ -121,6 +86,12 @@
 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 != "":
@@ -140,29 +111,15 @@
 if config.default_sysroot:
     config.available_features.add("default_sysroot")
 
-# For each occurrence of a flang tool name, replace it with the full path to
-# the build directory holding that tool.
-tools = [
-    ToolSubst(
-        "%flang",
-        command=FindTool("flang"),
-        unresolved="fatal",
-    ),
-    ToolSubst(
-        "%flang_fc1",
-        command=FindTool("flang"),
-        extra_args=["-fc1"],
-        unresolved="fatal",
-    ),
-]
-
 # Flang has several unimplemented features. TODO messages are used to mark
 # and fail if these features are exercised. Some TODOs exit with a non-zero
 # exit code, but others abort the execution in assert builds.
 # To catch aborts, the `--crash` option for the `not` command has to be used.
-tools.append(ToolSubst("%not_todo_cmd", command=FindTool("not"), 
unresolved="fatal"))
+config.tools.append(
+    ToolSubst("%not_todo_cmd", command=FindTool("not"), unresolved="fatal")
+)
 if "asserts" in config.available_features:
-    tools.append(
+    config.tools.append(
         ToolSubst(
             "%not_todo_abort_cmd",
             command=FindTool("not"),
@@ -171,7 +128,7 @@
         )
     )
 else:
-    tools.append(
+    config.tools.append(
         ToolSubst("%not_todo_abort_cmd", command=FindTool("not"), 
unresolved="fatal")
     )
 
@@ -179,10 +136,10 @@
 # finding the tools.
 if config.flang_standalone_build:
     llvm_config.add_tool_substitutions(
-        tools, [config.flang_llvm_tools_dir, config.llvm_tools_dir]
+        config.tools, [config.flang_llvm_tools_dir, config.llvm_tools_dir]
     )
 else:
-    llvm_config.add_tool_substitutions(tools, config.llvm_tools_dir)
+    llvm_config.add_tool_substitutions(config.tools, config.llvm_tools_dir)
 
 llvm_config.use_clang(required=False)
 
diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index 2b66dd64b8c13..e8cc4b3dcf81b 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -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_intrinsic_modules_dir = "@FLANG_INTRINSIC_MODULES_DIR@"
 config.flang_headers_dir = "@HEADER_BINARY_DIR@"
@@ -33,8 +33,17 @@ else:
 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.python3_exe = "@Python3_EXECUTABLE@"
+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")
diff --git a/flang/test/pgo.lit.cfg b/flang/test/pgo.lit.cfg
new file mode 100644
index 0000000000000..16dd9966ae9a3
--- /dev/null
+++ b/flang/test/pgo.lit.cfg
@@ -0,0 +1,53 @@
+# -*- Python -*-
+
+import lit.util
+
+from lit.llvm.subst import ToolSubst
+
+config.flang = lit.util.which('flang', 
config.flang_opt_tools_dir).replace('\\', '/')
+
+config.name = 'Flang PGO Training'
+config.suffixes = [
+    ".f",
+    ".F",
+    ".ff",
+    ".FOR",
+    ".for",
+    ".f77",
+    ".f90",
+    ".F90",
+    ".ff90",
+    ".f95",
+    ".F95",
+    ".ff95",
+    ".fpp",
+    ".FPP",
+    ".cuf",
+    ".CUF",
+    ".f18",
+    ".F18",
+    ".f03",
+    ".F03",
+    ".f08",
+    ".F08",
+    ".fir",
+    ".mlir",
+]
+
+config.llvm_profile_file = '../perf-training-%4m.profraw'
+
+# For each occurrence of a flang tool name, replace it with the full path to
+# the build directory holding that tool.
+config.tools = [
+    ToolSubst(
+        "%flang",
+        command=config.flang,
+        unresolved="fatal",
+    ),
+    ToolSubst(
+        "%flang_fc1",
+        command=config.flang,
+        extra_args=["-fc1"],
+        unresolved="fatal",
+    ),
+]
diff --git a/flang/test/test.lit.cfg b/flang/test/test.lit.cfg
new file mode 100644
index 0000000000000..9c10ca51d106b
--- /dev/null
+++ b/flang/test/test.lit.cfg
@@ -0,0 +1,57 @@
+# -*- Python -*-
+
+from lit.llvm.subst import FindTool
+from lit.llvm.subst import ToolSubst
+
+# name: The name of this test suite.
+config.name = "Flang"
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = [
+    ".c",
+    ".cpp",
+    ".f",
+    ".F",
+    ".ff",
+    ".FOR",
+    ".for",
+    ".f77",
+    ".f90",
+    ".F90",
+    ".ff90",
+    ".f95",
+    ".F95",
+    ".ff95",
+    ".fpp",
+    ".FPP",
+    ".cuf",
+    ".CUF",
+    ".f18",
+    ".F18",
+    ".f03",
+    ".F03",
+    ".f08",
+    ".F08",
+    ".ll",
+    ".fir",
+    ".mlir",
+    ".s",
+]
+
+config.llvm_profile_file = ''
+
+# For each occurrence of a flang tool name, replace it with the full path to
+# the build directory holding that tool.
+config.tools = [
+    ToolSubst(
+        "%flang",
+        command=FindTool("flang"),
+        unresolved="fatal",
+    ),
+    ToolSubst(
+        "%flang_fc1",
+        command=FindTool("flang"),
+        extra_args=["-fc1"],
+        unresolved="fatal",
+    ),
+]

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to