[clang] [compiler-rt] [clang-tools-extra] [PGO] Exposing PGO's Counter Reset and File Dumping APIs (PR #76471)
Qiongsi Wu via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 27 13:14:37 PST 2023
https://github.com/qiongsiwu created https://github.com/llvm/llvm-project/pull/76471
This PR exposes three PGO functions `__llvm_profile_reset_counters`, `__llvm_profile_dump` and `__llvm_orderfile_dump` to user programs through the new header `instr_prof_interface.h` under `compiler-rt/include/profile`. This way, the user can include the header `profile/instr_prof_interface.h` to introduce these three names to their programs.
Additionally, this PR defines macro `__LLVM_INSTR_PROFILE_GENERATE` when the program is compiled with profile generation, and defines macro `__LLVM_INSTR_PROFILE_USE` when the program is compiled with profile use. `__LLVM_INSTR_PROFILE_GENERATE` together with `instr_prof_interface.h` define the three PGO functions only when the program is compiled with profile generation. When profile generation is off, these PGO functions are defined away and leave no trace in the user's program.
>From 6c9381ec324595947237bd25642b03ab40b6a4df Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Wed, 27 Dec 2023 13:05:01 -0500
Subject: [PATCH 1/4] Initial commit
---
.../ExpandModularHeadersPPCallbacks.cpp | 2 +-
clang/include/clang/Frontend/Utils.h | 4 +-
clang/lib/Frontend/CompilerInstance.cpp | 2 +-
clang/lib/Frontend/InitPreprocessor.cpp | 12 ++--
compiler-rt/include/CMakeLists.txt | 1 +
.../include/profile/instr_prof_interface.h | 66 +++++++++++++++++++
compiler-rt/lib/profile/InstrProfiling.h | 32 +--------
7 files changed, 83 insertions(+), 36 deletions(-)
create mode 100644 compiler-rt/include/profile/instr_prof_interface.h
diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
index e414ac8c770508..5ecd4fb19131e4 100644
--- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
+++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
@@ -100,7 +100,7 @@ ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks(
/*OwnsHeaderSearch=*/false);
PP->Initialize(Compiler.getTarget(), Compiler.getAuxTarget());
InitializePreprocessor(*PP, *PO, Compiler.getPCHContainerReader(),
- Compiler.getFrontendOpts());
+ Compiler.getFrontendOpts(), Compiler.getCodeGenOpts());
ApplyHeaderSearchOptions(*HeaderInfo, *HSO, LangOpts,
Compiler.getTarget().getTriple());
}
diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h
index 143cf4359f00b5..604e42067a3f1e 100644
--- a/clang/include/clang/Frontend/Utils.h
+++ b/clang/include/clang/Frontend/Utils.h
@@ -43,12 +43,14 @@ class PCHContainerReader;
class Preprocessor;
class PreprocessorOptions;
class PreprocessorOutputOptions;
+class CodeGenOptions;
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file.
void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts,
const PCHContainerReader &PCHContainerRdr,
- const FrontendOptions &FEOpts);
+ const FrontendOptions &FEOpts,
+ const CodeGenOptions &CodeGenOpts);
/// DoPrintPreprocessedInput - Implement -E mode.
void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 56bbef9697b650..ea44a26b6db7da 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -470,7 +470,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
// Predefine macros and configure the preprocessor.
InitializePreprocessor(*PP, PPOpts, getPCHContainerReader(),
- getFrontendOpts());
+ getFrontendOpts(), getCodeGenOpts());
// Initialize the header search object. In CUDA compilations, we use the aux
// triple (the host triple) to initialize our header search, since we need to
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index d83128adb511ef..009a67eea1eb52 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1366,10 +1366,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file.
-void clang::InitializePreprocessor(
- Preprocessor &PP, const PreprocessorOptions &InitOpts,
- const PCHContainerReader &PCHContainerRdr,
- const FrontendOptions &FEOpts) {
+void clang::InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorOptions &InitOpts,
+ const PCHContainerReader &PCHContainerRdr,
+ const FrontendOptions &FEOpts,
+ const CodeGenOptions &CodeGenOpts) {
const LangOptions &LangOpts = PP.getLangOpts();
std::string PredefineBuffer;
PredefineBuffer.reserve(4080);
@@ -1416,6 +1417,9 @@ void clang::InitializePreprocessor(
InitializeStandardPredefinedMacros(PP.getTargetInfo(), PP.getLangOpts(),
FEOpts, Builder);
+ if (CodeGenOpts.hasProfileIRInstr())
+ Builder.defineMacro("__LLVM_INSTR_PROFILE_GENERATE");
+
// Add on the predefines from the driver. Wrap in a #line directive to report
// that they come from the command line.
Builder.append("# 1 \"<command line>\" 1");
diff --git a/compiler-rt/include/CMakeLists.txt b/compiler-rt/include/CMakeLists.txt
index 78427beedb3cc4..7a100c66bbcfda 100644
--- a/compiler-rt/include/CMakeLists.txt
+++ b/compiler-rt/include/CMakeLists.txt
@@ -44,6 +44,7 @@ endif(COMPILER_RT_BUILD_ORC)
if (COMPILER_RT_BUILD_PROFILE)
set(PROFILE_HEADERS
profile/InstrProfData.inc
+ profile/instr_prof_interface.h
)
endif(COMPILER_RT_BUILD_PROFILE)
diff --git a/compiler-rt/include/profile/instr_prof_interface.h b/compiler-rt/include/profile/instr_prof_interface.h
new file mode 100644
index 00000000000000..6cbf6b414f3af1
--- /dev/null
+++ b/compiler-rt/include/profile/instr_prof_interface.h
@@ -0,0 +1,66 @@
+/*===---- instr_profiling.h - Instrumentation PGO User Program API ----------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ *
+ * This header provides a public interface for user programs to provide
+ * fine-grained control of profile dumping.
+ *
+\*===---------------------------------------------------------------------===*/
+
+#ifndef COMPILER_RT_INSTR_PROFILING
+#define COMPILER_RT_INSTR_PROFILING
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __LLVM_INSTR_PROFILE_GENERATE
+// Profile file reset and dump interfaces.
+// Only defined when `-fprofile-generate` is in effect.
+
+/*!
+ * \brief Interface to set all PGO counters to zero for the current process.
+ *
+ */
+void __llvm_profile_reset_counters(void);
+
+/*!
+ * \brief this is a wrapper interface to \c __llvm_profile_write_file.
+ * After this interface is invoked, an already dumped flag will be set
+ * so that profile won't be dumped again during program exit.
+ * Invocation of interface __llvm_profile_reset_counters will clear
+ * the flag. This interface is designed to be used to collect profile
+ * data from user selected hot regions. The use model is
+ * __llvm_profile_reset_counters();
+ * ... hot region 1
+ * __llvm_profile_dump();
+ * .. some other code
+ * __llvm_profile_reset_counters();
+ * ... hot region 2
+ * __llvm_profile_dump();
+ *
+ * It is expected that on-line profile merging is on with \c %m specifier
+ * used in profile filename . If merging is not turned on, user is expected
+ * to invoke __llvm_profile_set_filename to specify different profile names
+ * for different regions before dumping to avoid profile write clobbering.
+ */
+int __llvm_profile_dump(void);
+
+// Interface to dump the current process' order file to disk.
+int __llvm_orderfile_dump(void);
+
+#else
+#define __llvm_profile_reset_counters()
+#define __llvm_profile_dump()
+#define __llvm_orderfile_dump()
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h
index 137115996748ce..3f2c75b5df9064 100644
--- a/compiler-rt/lib/profile/InstrProfiling.h
+++ b/compiler-rt/lib/profile/InstrProfiling.h
@@ -12,6 +12,9 @@
#include "InstrProfilingPort.h"
#include <stdio.h>
+#define __LLVM_INSTR_PROFILE_GENERATE
+#include "profile/instr_prof_interface.h"
+
#define INSTR_PROF_VISIBILITY COMPILER_RT_VISIBILITY
#include "profile/InstrProfData.inc"
@@ -100,12 +103,6 @@ ValueProfNode *__llvm_profile_begin_vnodes();
ValueProfNode *__llvm_profile_end_vnodes();
uint32_t *__llvm_profile_begin_orderfile();
-/*!
- * \brief Clear profile counters to zero.
- *
- */
-void __llvm_profile_reset_counters(void);
-
/*!
* \brief Merge profile data from buffer.
*
@@ -156,29 +153,6 @@ void __llvm_profile_instrument_target_value(uint64_t TargetValue, void *Data,
int __llvm_profile_write_file(void);
int __llvm_orderfile_write_file(void);
-/*!
- * \brief this is a wrapper interface to \c __llvm_profile_write_file.
- * After this interface is invoked, an already dumped flag will be set
- * so that profile won't be dumped again during program exit.
- * Invocation of interface __llvm_profile_reset_counters will clear
- * the flag. This interface is designed to be used to collect profile
- * data from user selected hot regions. The use model is
- * __llvm_profile_reset_counters();
- * ... hot region 1
- * __llvm_profile_dump();
- * .. some other code
- * __llvm_profile_reset_counters();
- * ... hot region 2
- * __llvm_profile_dump();
- *
- * It is expected that on-line profile merging is on with \c %m specifier
- * used in profile filename . If merging is not turned on, user is expected
- * to invoke __llvm_profile_set_filename to specify different profile names
- * for different regions before dumping to avoid profile write clobbering.
- */
-int __llvm_profile_dump(void);
-
-int __llvm_orderfile_dump(void);
/*!
* \brief Set the filename for writing instrumentation data.
>From a6c3b4619ea93cec2be962c60181985a379f8553 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Wed, 27 Dec 2023 14:02:16 -0500
Subject: [PATCH 2/4] Frontend minor cleanup and adding a test
---
clang/include/clang/Basic/CodeGenOptions.h | 6 ++++++
clang/lib/Frontend/InitPreprocessor.cpp | 12 ++++++++++--
clang/test/Preprocessor/pgo-init.c | 5 +++++
3 files changed, 21 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Preprocessor/pgo-init.c
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 6952b48e898a81..e06f1094784caf 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -494,6 +494,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
return getProfileInstr() == ProfileCSIRInstr;
}
+ /// Check if any form of instrumentation is on.
+ bool hasProfileInstr() const {
+ return hasProfileClangInstr() || hasProfileIRInstr() ||
+ hasProfileCSIRInstr();
+ }
+
/// Check if Clang profile use is on.
bool hasProfileClangUse() const {
return getProfileUse() == ProfileClangInstr;
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 009a67eea1eb52..0386a75ac429fa 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1364,6 +1364,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
TI.getTargetDefines(LangOpts, Builder);
}
+static void InitializePGOProfileMacros(const CodeGenOptions &CodeGenOpts,
+ MacroBuilder &Builder) {
+ if (CodeGenOpts.hasProfileInstr())
+ Builder.defineMacro("__LLVM_INSTR_PROFILE_GENERATE");
+}
+
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file.
void clang::InitializePreprocessor(Preprocessor &PP,
@@ -1417,8 +1423,10 @@ void clang::InitializePreprocessor(Preprocessor &PP,
InitializeStandardPredefinedMacros(PP.getTargetInfo(), PP.getLangOpts(),
FEOpts, Builder);
- if (CodeGenOpts.hasProfileIRInstr())
- Builder.defineMacro("__LLVM_INSTR_PROFILE_GENERATE");
+ // The PGO instrumentation profile macros are driven by options
+ // -fprofile[-instr]-generate/-fcs-profile-generate/-fprofile[-instr]-use,
+ // hence they are not guarded by InitOpts.UsePredefines.
+ InitializePGOProfileMacros(CodeGenOpts, Builder);
// Add on the predefines from the driver. Wrap in a #line directive to report
// that they come from the command line.
diff --git a/clang/test/Preprocessor/pgo-init.c b/clang/test/Preprocessor/pgo-init.c
new file mode 100644
index 00000000000000..6ac28708fddf71
--- /dev/null
+++ b/clang/test/Preprocessor/pgo-init.c
@@ -0,0 +1,5 @@
+// RUN: %clang -fprofile-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGEN %s
+// RUN: %clang -fprofile-instr-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGEN %s
+// RUN: %clang -fcs-profile-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGEN %s
+//
+// PROFGEN:#define __LLVM_INSTR_PROFILE_GENERATE 1
>From 18ec4ac08a08473f146e842dbeefbe7171ce3eec Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Wed, 27 Dec 2023 16:01:22 -0500
Subject: [PATCH 3/4] Refactoring tests, adding profile-use macro
---
clang/lib/Frontend/InitPreprocessor.cpp | 3 +++
clang/test/Preprocessor/pgo-init.c | 5 -----
clang/test/Profile/c-general.c | 9 ++++++++
compiler-rt/test/profile/instrprof-api.c | 26 ++++++++++++++++++++++++
4 files changed, 38 insertions(+), 5 deletions(-)
delete mode 100644 clang/test/Preprocessor/pgo-init.c
create mode 100644 compiler-rt/test/profile/instrprof-api.c
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 0386a75ac429fa..fe0fd3614113c4 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1368,6 +1368,9 @@ static void InitializePGOProfileMacros(const CodeGenOptions &CodeGenOpts,
MacroBuilder &Builder) {
if (CodeGenOpts.hasProfileInstr())
Builder.defineMacro("__LLVM_INSTR_PROFILE_GENERATE");
+
+ if (CodeGenOpts.hasProfileIRUse() || CodeGenOpts.hasProfileClangUse())
+ Builder.defineMacro("__LLVM_INSTR_PROFILE_USE");
}
/// InitializePreprocessor - Initialize the preprocessor getting it and the
diff --git a/clang/test/Preprocessor/pgo-init.c b/clang/test/Preprocessor/pgo-init.c
deleted file mode 100644
index 6ac28708fddf71..00000000000000
--- a/clang/test/Preprocessor/pgo-init.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %clang -fprofile-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGEN %s
-// RUN: %clang -fprofile-instr-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGEN %s
-// RUN: %clang -fcs-profile-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGEN %s
-//
-// PROFGEN:#define __LLVM_INSTR_PROFILE_GENERATE 1
diff --git a/clang/test/Profile/c-general.c b/clang/test/Profile/c-general.c
index b841f9c3d2a1d1..fa9eb7ebc78274 100644
--- a/clang/test/Profile/c-general.c
+++ b/clang/test/Profile/c-general.c
@@ -9,6 +9,15 @@
// Also check compatibility with older profiles.
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v1 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s
+// RUN: %clang -fprofile-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGENMACRO %s
+// RUN: %clang -fprofile-instr-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGENMACRO %s
+// RUN: %clang -fcs-profile-generate -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFGENMACRO %s
+//
+// RUN: %clang -fprofile-use=%t.profdata -E -dM %s | FileCheck -match-full-lines -check-prefix=PROFUSEMACRO %s
+
+// PROFGENMACRO:#define __LLVM_INSTR_PROFILE_GENERATE 1
+// PROFUSEMACRO:#define __LLVM_INSTR_PROFILE_USE 1
+
// PGOGEN: @[[SLC:__profc_simple_loops]] = private global [4 x i64] zeroinitializer
// PGOGEN: @[[IFC:__profc_conditionals]] = private global [13 x i64] zeroinitializer
// PGOGEN: @[[EEC:__profc_early_exits]] = private global [9 x i64] zeroinitializer
diff --git a/compiler-rt/test/profile/instrprof-api.c b/compiler-rt/test/profile/instrprof-api.c
new file mode 100644
index 00000000000000..600fbb575feea3
--- /dev/null
+++ b/compiler-rt/test/profile/instrprof-api.c
@@ -0,0 +1,26 @@
+// RUN: %clang_profgen %s -S -emit-llvm -o - | FileCheck %s --check-prefix=PROFGEN
+// RUN: %clang_profgen -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata %s -S -emit-llvm -o - | FileCheck %s --check-prefix=PROFUSE
+#include "profile/instr_profiling.h"
+
+__attribute__((noinline)) int bar() { return 4; }
+
+int foo() {
+ __llvm_profile_reset_counters();
+ // PROFGEN: call void @__llvm_profile_reset_counters()
+ // PROFUSE-NOT: call void @__llvm_profile_reset_counters()
+ return bar();
+}
+
+int main() {
+ int z = foo() + 3;
+ __llvm_profile_dump();
+ // PROFGEN: %call1 = call signext i32 @__llvm_profile_dump()
+ // PROFUSE-NOT: %call1 = call signext i32 @__llvm_profile_dump()
+ __llvm_orderfile_dump();
+ // PROFGEN: %call2 = call signext i32 @__llvm_orderfile_dump()
+ // PROFUSE-NOT: %call2 = call signext i32 @__llvm_orderfile_dump()
+ return z + bar() - 11;
+}
>From b741a557715eb17b69fa5b4013f2efeadcb80fda Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Wed, 27 Dec 2023 16:08:25 -0500
Subject: [PATCH 4/4] Fix header comment
---
compiler-rt/include/profile/instr_prof_interface.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/compiler-rt/include/profile/instr_prof_interface.h b/compiler-rt/include/profile/instr_prof_interface.h
index 6cbf6b414f3af1..7d0516e5f6eaec 100644
--- a/compiler-rt/include/profile/instr_prof_interface.h
+++ b/compiler-rt/include/profile/instr_prof_interface.h
@@ -1,4 +1,4 @@
-/*===---- instr_profiling.h - Instrumentation PGO User Program API ----------===
+/*===---- instr_prof_interface.h - Instrumentation PGO User Program API ----===
*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +7,7 @@
*===-----------------------------------------------------------------------===
*
* This header provides a public interface for user programs to provide
- * fine-grained control of profile dumping.
+ * fine-grained control of counter reset and profile dumping.
*
\*===---------------------------------------------------------------------===*/
More information about the cfe-commits
mailing list