[llvm] [clang] [CMake][PGO] Build Sema.cpp to generate profdata for PGO builds (PR #77347)

Tom Stellard via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 11 16:44:59 PST 2024


https://github.com/tstellar updated https://github.com/llvm/llvm-project/pull/77347

>From 127e2ae83f33843cfb9c5cca314afa2fc9844239 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Sat, 6 Jan 2024 07:46:01 +0000
Subject: [PATCH 1/5] [CMake][PGO] Use check-clang target to generate profdata
 for PGO builds

When doing a multi-stage PGO build of clang, run the check-clang and
check-llvm targets using the instrumented clang and use that profile
data for building the final stage2 clang.  This is what is recommended
by our official documentation: https://llvm.org/docs/HowToBuildWithPGO.html#building-clang-with-pgo

I benchmarked this change by compiling the SemaChecking.cpp file from
clang.  Using check-clang/check-llvm to generate the profile data gives a 25% speedup
in the PGO+LTO stage2 clang when compared to the stage1 clang (no-LTO).

Prior to this change, I was only seeing ~5% speedup when comparing the
stage2 and stage1 builds.
---
 clang/utils/perf-training/CMakeLists.txt |  6 +++---
 clang/utils/perf-training/perf-helper.py | 16 +++++++++-------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/clang/utils/perf-training/CMakeLists.txt b/clang/utils/perf-training/CMakeLists.txt
index c6d51863fb1b5c..95ff8115aa538b 100644
--- a/clang/utils/perf-training/CMakeLists.txt
+++ b/clang/utils/perf-training/CMakeLists.txt
@@ -15,7 +15,7 @@ if(LLVM_BUILD_INSTRUMENTED)
     )
 
   add_custom_target(clear-profraw
-    COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} profraw
+    COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/profiles/ profraw
     COMMENT "Clearing old profraw data")
 
   if(NOT LLVM_PROFDATA)
@@ -26,9 +26,9 @@ if(LLVM_BUILD_INSTRUMENTED)
     message(STATUS "To enable merging PGO data LLVM_PROFDATA has to point to llvm-profdata")
   else()
     add_custom_target(generate-profdata
-      COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py merge ${LLVM_PROFDATA} ${CMAKE_CURRENT_BINARY_DIR}/clang.profdata ${CMAKE_CURRENT_BINARY_DIR}
+      COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py merge ${LLVM_PROFDATA} ${CMAKE_CURRENT_BINARY_DIR}/clang.profdata ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/profiles/
       COMMENT "Merging profdata"
-      DEPENDS generate-profraw)
+      DEPENDS generate-profraw check-clang check-llvm)
   endif()
 endif()
 
diff --git a/clang/utils/perf-training/perf-helper.py b/clang/utils/perf-training/perf-helper.py
index 99d6a3333b6ef0..bd8f74c9c2e129 100644
--- a/clang/utils/perf-training/perf-helper.py
+++ b/clang/utils/perf-training/perf-helper.py
@@ -30,26 +30,28 @@ def findFilesWithExtension(path, extension):
 
 
 def clean(args):
-    if len(args) != 2:
+    if len(args) < 2:
         print(
-            "Usage: %s clean <path> <extension>\n" % __file__
+            "Usage: %s clean <paths> <extension>\n" % __file__
             + "\tRemoves all files with extension from <path>."
         )
         return 1
-    for filename in findFilesWithExtension(args[0], args[1]):
-        os.remove(filename)
+    for path in args[1:-1]:
+       for filename in findFilesWithExtension(path, args[-1]):
+           os.remove(filename)
     return 0
 
 
 def merge(args):
-    if len(args) != 3:
+    if len(args) < 3:
         print(
-            "Usage: %s merge <llvm-profdata> <output> <path>\n" % __file__
+            "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]]
-    cmd.extend(findFilesWithExtension(args[2], "profraw"))
+    for i in range(2, len(args)):
+      cmd.extend(findFilesWithExtension(args[i], "profraw"))
     subprocess.check_call(cmd)
     return 0
 

>From 4f7734584af3aa9a18bde17349ceccbef3658c53 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Mon, 8 Jan 2024 18:07:31 +0000
Subject: [PATCH 2/5] Fix python formatting

---
 clang/utils/perf-training/perf-helper.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/utils/perf-training/perf-helper.py b/clang/utils/perf-training/perf-helper.py
index bd8f74c9c2e129..844aa274f049aa 100644
--- a/clang/utils/perf-training/perf-helper.py
+++ b/clang/utils/perf-training/perf-helper.py
@@ -37,8 +37,8 @@ def clean(args):
         )
         return 1
     for path in args[1:-1]:
-       for filename in findFilesWithExtension(path, args[-1]):
-           os.remove(filename)
+        for filename in findFilesWithExtension(path, args[-1]):
+            os.remove(filename)
     return 0
 
 
@@ -51,7 +51,7 @@ def merge(args):
         return 1
     cmd = [args[0], "merge", "-o", args[1]]
     for i in range(2, len(args)):
-      cmd.extend(findFilesWithExtension(args[i], "profraw"))
+        cmd.extend(findFilesWithExtension(args[i], "profraw"))
     subprocess.check_call(cmd)
     return 0
 

>From d330bfffc47c23b1e02602591b7ff02cd5a31c2d Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 11 Jan 2024 23:37:19 +0000
Subject: [PATCH 3/5] Build Sema.cpp to generate profile data instead of using
 check-clang and check-llvm

Also add an option to supply a cmake project to use to generate profile
data.
---
 clang/utils/perf-training/CMakeLists.txt | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/clang/utils/perf-training/CMakeLists.txt b/clang/utils/perf-training/CMakeLists.txt
index 95ff8115aa538b..75e6278191c2c2 100644
--- a/clang/utils/perf-training/CMakeLists.txt
+++ b/clang/utils/perf-training/CMakeLists.txt
@@ -1,6 +1,10 @@
+include(LLVMExternalProjectUtils)
+
 set(CLANG_PGO_TRAINING_DATA "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH
   "The path to a lit testsuite containing samples for PGO and order file generation"
   )
+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_PERF_TRAINING_DEPS "" CACHE STRING "Extra dependencies needed to build the PGO training data.")
 
 if(LLVM_BUILD_INSTRUMENTED)
   configure_lit_site_cfg(
@@ -28,7 +32,21 @@ if(LLVM_BUILD_INSTRUMENTED)
     add_custom_target(generate-profdata
       COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py merge ${LLVM_PROFDATA} ${CMAKE_CURRENT_BINARY_DIR}/clang.profdata ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/profiles/
       COMMENT "Merging profdata"
-      DEPENDS generate-profraw check-clang check-llvm)
+      DEPENDS generate-profraw)
+    if (CLANG_PGO_TRAINING_DATA_SOURCE_DIR)
+      llvm_ExternalProject_Add(generate-profraw-external ${CLANG_PGO_TRAINING_DATA_SOURCE_DIR}
+              USE_TOOLCHAIN EXLUDE_FROM_ALL NO_INSTALL DEPENDS generate-profraw)
+      add_dependencies(generate-profdata generate-profraw-external)
+    else()
+      # Default to compiling a file from clang. This also builds all the
+      # dependencies needed to build this file, like TableGen.
+      set(generate_profraw_clang_sema tools/clang/lib/Sema/CMakeFiles/obj.clangSema.dir/Sema.cpp.o)
+      llvm_ExternalProject_Add(generate-profraw-clang ${CMAKE_CURRENT_SOURCE_DIR}/../../../llvm
+              USE_TOOLCHAIN EXLUDE_FROM_ALL NO_INSTALL DEPENDS generate-profraw
+              EXTRA_TARGETS generate_profraw_clang_sema
+              CMAKE_ARGS -DLLVM_ENABLE_PROJECTS=clang)
+      add_dependencies(generate-profdata generate_profraw_clang_sema)
+    endif()
   endif()
 endif()
 

>From 9b6543de1af17ec4c2ac1c540f2361e3d193363d Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 11 Jan 2024 23:57:51 +0000
Subject: [PATCH 4/5] Update documentatin

---
 llvm/docs/AdvancedBuilds.rst | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/llvm/docs/AdvancedBuilds.rst b/llvm/docs/AdvancedBuilds.rst
index 960b19fa5317f3..7d8a8718f6867c 100644
--- a/llvm/docs/AdvancedBuilds.rst
+++ b/llvm/docs/AdvancedBuilds.rst
@@ -145,6 +145,28 @@ that also enables ThinTLO, use the following command:
       -DPGO_INSTRUMENT_LTO=Thin \
       <path to source>/llvm
 
+By default, clang will generate profile data by compiling the Sema.cpp
+file (and all its dependencies, e.g. TableGen).  However, you can also
+tell clang use 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 CLANG_PERF_TRAINING_DATA_SOURCE_DIR option).
+
+For example, If you wanted to use the
+`LLVM Test Suite <https://github.com/llvm/llvm-test-suite/>`_ to generate
+profile data you would use the following command:
+
+.. code-block:: console
+  $ cmake -G Ninja -C <path to source>/clang/cmake/caches/PGO.cmake \
+       -DBOOTSTRAP_CLANG_PGO_TRAINING_DATA_SOURCE_DIR=/home/fedora/llvm-test-suite/ \
+       -DBOOTSTRAP_CLANG_PERF_TRAINING_DEPS=runtimes
+
+The BOOTSTRAP_ prefixes tells CMake to pass the variables on to the instrumented
+stage two build.  And the CLANG_PERF_TRAINING_DEPS option let's you specify
+additional build targets to build before building the external project.  The
+LLVM Test Suite requires compiler-rt to build, so we need to add the
+`runtimes` target as a dependency.
+
 After configuration, building the stage2-instrumented-generate-profdata target
 will automatically build the stage1 compiler, build the instrumented compiler
 with the stage1 compiler, and then run the instrumented compiler against the

>From adcbfc043d7a1ca24b008e79c834193ad776ff2a Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 12 Jan 2024 00:42:10 +0000
Subject: [PATCH 5/5] Fix documentation build

---
 llvm/docs/AdvancedBuilds.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/docs/AdvancedBuilds.rst b/llvm/docs/AdvancedBuilds.rst
index 7d8a8718f6867c..bfe3455a9a26c2 100644
--- a/llvm/docs/AdvancedBuilds.rst
+++ b/llvm/docs/AdvancedBuilds.rst
@@ -157,6 +157,7 @@ For example, If you wanted to use the
 profile data you would use the following command:
 
 .. code-block:: console
+
   $ cmake -G Ninja -C <path to source>/clang/cmake/caches/PGO.cmake \
        -DBOOTSTRAP_CLANG_PGO_TRAINING_DATA_SOURCE_DIR=/home/fedora/llvm-test-suite/ \
        -DBOOTSTRAP_CLANG_PERF_TRAINING_DEPS=runtimes



More information about the cfe-commits mailing list