[flang-commits] [clang] [llvm] [mlir] [flang] [compiler-rt] [clang-tools-extra] [lldb] [Profile] Add binary profile correlation to offload profile metadata at runtime. (PR #69493)
Zequan Wu via flang-commits
flang-commits at lists.llvm.org
Thu Nov 2 12:45:33 PDT 2023
https://github.com/ZequanWu updated https://github.com/llvm/llvm-project/pull/69493
>From 3a394ce5d4d7d91251337bd0a2c1c1a074eb37e6 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 17 Oct 2023 19:24:12 -0400
Subject: [PATCH 1/5] [Profile] Add binary profile correlation.
---
clang/lib/CodeGen/BackendUtil.cpp | 10 +-
clang/lib/CodeGen/CoverageMappingGen.cpp | 20 ++
.../CodeGen/coverage-profile-raw-version.c | 9 +
compiler-rt/include/profile/InstrProfData.inc | 2 +
compiler-rt/lib/profile/InstrProfiling.h | 3 +
.../lib/profile/InstrProfilingBuffer.c | 14 ++
compiler-rt/lib/profile/InstrProfilingMerge.c | 8 +-
.../profile/InstrProfilingPlatformWindows.c | 2 -
.../lib/profile/InstrProfilingWriter.c | 24 +--
compiler-rt/test/CMakeLists.txt | 5 +-
.../Darwin/instrprof-debug-info-correlate.c | 4 +-
.../instrprof-debug-info-correlate-warnings.c | 2 +-
.../Linux/instrprof-debug-info-correlate.c | 6 +-
.../instrprof-show-debug-info-correlation.c | 6 +-
.../test/profile/instrprof-binary-correlate.c | 29 +++
llvm/include/llvm/ProfileData/InstrProf.h | 6 +-
.../llvm/ProfileData/InstrProfCorrelator.h | 59 ++++-
.../llvm/ProfileData/InstrProfData.inc | 2 +
.../llvm/ProfileData/InstrProfReader.h | 10 +
.../Instrumentation/PGOInstrumentation.h | 2 -
.../CodeGen/TargetLoweringObjectFileImpl.cpp | 23 +-
.../Coverage/CoverageMappingReader.cpp | 28 ++-
llvm/lib/ProfileData/InstrProf.cpp | 8 +-
llvm/lib/ProfileData/InstrProfCorrelator.cpp | 203 ++++++++++++++----
llvm/lib/ProfileData/InstrProfReader.cpp | 8 +-
.../Instrumentation/InstrProfiling.cpp | 31 +--
.../Instrumentation/PGOInstrumentation.cpp | 3 +-
.../debug-info-correlate-coverage.ll | 2 +-
.../InstrProfiling/debug-info-correlate.ll | 2 +-
llvm/tools/llvm-profdata/llvm-profdata.cpp | 37 +++-
30 files changed, 436 insertions(+), 132 deletions(-)
create mode 100644 clang/test/CodeGen/coverage-profile-raw-version.c
create mode 100644 compiler-rt/test/profile/instrprof-binary-correlate.c
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 70accce456d3c07..dad3c9a145b5049 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -42,6 +42,7 @@
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/StandardInstrumentations.h"
+#include "llvm/ProfileData/InstrProfCorrelator.h"
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -98,13 +99,16 @@ extern cl::opt<bool> PrintPipelinePasses;
static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
"sanitizer-early-opt-ep", cl::Optional,
cl::desc("Insert sanitizers on OptimizerEarlyEP."), cl::init(false));
-}
+
+extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;
+} // namespace llvm
namespace {
// Default filename used for profile generation.
std::string getDefaultProfileGenName() {
- return DebugInfoCorrelate ? "default_%m.proflite" : "default_%m.profraw";
+ return ProfileCorrelate.getNumOccurrences() ? "default_%m.proflite"
+ : "default_%m.profraw";
}
class EmitAssemblyHelper {
@@ -197,7 +201,7 @@ class EmitAssemblyHelper {
void EmitAssembly(BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS);
};
-}
+} // namespace
static SanitizerCoverageOptions
getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) {
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 76ed10091b025be..daff0d1d50923f5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -31,6 +31,10 @@
// is textually included.
#define COVMAP_V3
+namespace llvm {
+extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;
+} // namespace llvm
+
static llvm::cl::opt<bool> EmptyLineCommentCoverage(
"emptyline-comment-coverage",
llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only "
@@ -1831,6 +1835,22 @@ void CoverageMappingModuleGen::emit() {
llvm::GlobalValue::InternalLinkage, NamesArrVal,
llvm::getCoverageUnusedNamesVarName());
}
+ const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
+ llvm::Type *IntTy64 = llvm::Type::getInt64Ty(Ctx);
+ uint64_t ProfileVersion = INSTR_PROF_RAW_VERSION;
+ if (llvm::ProfileCorrelate == llvm::InstrProfCorrelator::BINARY)
+ ProfileVersion |= VARIANT_MASK_BIN_CORRELATE;
+ auto *VersionVariable = new llvm::GlobalVariable(
+ CGM.getModule(), llvm::Type::getInt64Ty(Ctx), true,
+ llvm::GlobalValue::WeakAnyLinkage,
+ llvm::Constant::getIntegerValue(IntTy64, llvm::APInt(64, ProfileVersion)),
+ VarName);
+ VersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ llvm::Triple TT(CGM.getModule().getTargetTriple());
+ if (TT.supportsCOMDAT()) {
+ VersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ VersionVariable->setComdat(CGM.getModule().getOrInsertComdat(VarName));
+ }
}
unsigned CoverageMappingModuleGen::getFileID(FileEntryRef File) {
diff --git a/clang/test/CodeGen/coverage-profile-raw-version.c b/clang/test/CodeGen/coverage-profile-raw-version.c
new file mode 100644
index 000000000000000..fc81179e1a33e06
--- /dev/null
+++ b/clang/test/CodeGen/coverage-profile-raw-version.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -mllvm -profile-correlate=binary -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -o - %s | FileCheck %s --check-prefix=BIN-CORRELATE
+
+// CHECK: @__llvm_profile_raw_version = {{.*}} i64 8
+// BIN-CORRELATE: @__llvm_profile_raw_version = {{.*}} i64 4294967304
+
+int main() {
+ return 0;
+}
diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc
index 8ba7e186d4fb1a6..1841ef348a70061 100644
--- a/compiler-rt/include/profile/InstrProfData.inc
+++ b/compiler-rt/include/profile/InstrProfData.inc
@@ -655,6 +655,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
* version for other variants of profile. We set the 8th most significant bit
* (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation
* generated profile, and 0 if this is a Clang FE generated profile.
+ * 1 in bit 32 indicates there is no profile name and data sections.
* 1 in bit 57 indicates there are context-sensitive records in the profile.
* The 59th bit indicates whether to use debug info to correlate profiles.
* The 60th bit indicates single byte coverage instrumentation.
@@ -664,6 +665,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
*/
#define VARIANT_MASKS_ALL 0xffffffff00000000ULL
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
+#define VARIANT_MASK_BIN_CORRELATE (0x1ULL << 32)
#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57)
#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58)
diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h
index 4433d7bd48871fc..8b9e029ee8baee5 100644
--- a/compiler-rt/lib/profile/InstrProfiling.h
+++ b/compiler-rt/lib/profile/InstrProfiling.h
@@ -267,6 +267,9 @@ uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
const __llvm_profile_data *End);
+/*! \brief Get the size of the profile name section in bytes. */
+uint64_t __llvm_profile_get_name_size(const char *Begin, const char *End);
+
/*! \brief Get the size in bytes of a single counter entry. */
size_t __llvm_profile_counter_entry_size(void);
diff --git a/compiler-rt/lib/profile/InstrProfilingBuffer.c b/compiler-rt/lib/profile/InstrProfilingBuffer.c
index 61ac5d9c0285002..e60aa9fc04e7fac 100644
--- a/compiler-rt/lib/profile/InstrProfilingBuffer.c
+++ b/compiler-rt/lib/profile/InstrProfilingBuffer.c
@@ -53,6 +53,9 @@ uint64_t __llvm_profile_get_size_for_buffer(void) {
COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
const __llvm_profile_data *End) {
+ if ((__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) ||
+ (__llvm_profile_get_version() & VARIANT_MASK_BIN_CORRELATE))
+ return 0;
intptr_t BeginI = (intptr_t)Begin, EndI = (intptr_t)End;
return ((EndI + sizeof(__llvm_profile_data) - 1) - BeginI) /
sizeof(__llvm_profile_data);
@@ -61,9 +64,20 @@ uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
const __llvm_profile_data *End) {
+ if ((__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) ||
+ (__llvm_profile_get_version() & VARIANT_MASK_BIN_CORRELATE))
+ return 0;
return __llvm_profile_get_num_data(Begin, End) * sizeof(__llvm_profile_data);
}
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_name_size(const char *Begin, const char *End) {
+ if ((__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) ||
+ (__llvm_profile_get_version() & VARIANT_MASK_BIN_CORRELATE))
+ return 0;
+ return End - Begin;
+}
+
COMPILER_RT_VISIBILITY size_t __llvm_profile_counter_entry_size(void) {
if (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE)
return sizeof(uint8_t);
diff --git a/compiler-rt/lib/profile/InstrProfilingMerge.c b/compiler-rt/lib/profile/InstrProfilingMerge.c
index 9cf12f251f7262d..554ce3693b6e464 100644
--- a/compiler-rt/lib/profile/InstrProfilingMerge.c
+++ b/compiler-rt/lib/profile/InstrProfilingMerge.c
@@ -66,8 +66,9 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
Header->NumCounters !=
__llvm_profile_get_num_counters(__llvm_profile_begin_counters(),
__llvm_profile_end_counters()) ||
- Header->NamesSize != (uint64_t)(__llvm_profile_end_names() -
- __llvm_profile_begin_names()) ||
+ Header->NamesSize !=
+ __llvm_profile_get_name_size(__llvm_profile_begin_names(),
+ __llvm_profile_end_names()) ||
Header->ValueKindLast != IPVK_Last)
return 1;
@@ -132,7 +133,8 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
// Merge counters by iterating the entire counter section when debug info
// correlation is enabled.
- if (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) {
+ if ((__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) ||
+ (__llvm_profile_get_version() & VARIANT_MASK_BIN_CORRELATE)) {
for (SrcCounter = SrcCountersStart,
DstCounter = __llvm_profile_begin_counters();
SrcCounter < SrcCountersEnd;) {
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
index dd576b2f8357dbb..23a7739355e2ed6 100644
--- a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
@@ -13,8 +13,6 @@
#if defined(_MSC_VER)
/* Merge read-write sections into .data. */
-#pragma comment(linker, "/MERGE:.lprfc=.data")
-#pragma comment(linker, "/MERGE:.lprfd=.data")
#pragma comment(linker, "/MERGE:.lprfv=.data")
#pragma comment(linker, "/MERGE:.lprfnd=.data")
/* Do *NOT* merge .lprfn and .lcovmap into .rdata. llvm-cov must be able to find
diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c
index 1e22398a4c0f64a..f3709694427d5c8 100644
--- a/compiler-rt/lib/profile/InstrProfilingWriter.c
+++ b/compiler-rt/lib/profile/InstrProfilingWriter.c
@@ -259,19 +259,19 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
const char *CountersBegin, const char *CountersEnd,
VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd, int SkipNameDataWrite) {
- int DebugInfoCorrelate =
- (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) != 0ULL;
+ int ProfileCorrelation =
+ (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) ||
+ (__llvm_profile_get_version() & VARIANT_MASK_BIN_CORRELATE);
/* Calculate size of sections. */
const uint64_t DataSectionSize =
- DebugInfoCorrelate ? 0 : __llvm_profile_get_data_size(DataBegin, DataEnd);
- const uint64_t NumData =
- DebugInfoCorrelate ? 0 : __llvm_profile_get_num_data(DataBegin, DataEnd);
+ __llvm_profile_get_data_size(DataBegin, DataEnd);
+ const uint64_t NumData = __llvm_profile_get_num_data(DataBegin, DataEnd);
const uint64_t CountersSectionSize =
__llvm_profile_get_counters_size(CountersBegin, CountersEnd);
const uint64_t NumCounters =
__llvm_profile_get_num_counters(CountersBegin, CountersEnd);
- const uint64_t NamesSize = DebugInfoCorrelate ? 0 : NamesEnd - NamesBegin;
+ const uint64_t NamesSize = __llvm_profile_get_name_size(NamesBegin, NamesEnd);
/* Create the header. */
__llvm_profile_header Header;
@@ -298,7 +298,7 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
#endif
/* The data and names sections are omitted in lightweight mode. */
- if (DebugInfoCorrelate) {
+ if (ProfileCorrelation) {
Header.CountersDelta = 0;
Header.NamesDelta = 0;
}
@@ -314,19 +314,19 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
/* Write the profile data. */
ProfDataIOVec IOVecData[] = {
- {DebugInfoCorrelate ? NULL : DataBegin, sizeof(uint8_t), DataSectionSize,
+ {ProfileCorrelation ? NULL : DataBegin, sizeof(uint8_t), DataSectionSize,
0},
{NULL, sizeof(uint8_t), PaddingBytesBeforeCounters, 1},
{CountersBegin, sizeof(uint8_t), CountersSectionSize, 0},
{NULL, sizeof(uint8_t), PaddingBytesAfterCounters, 1},
- {(SkipNameDataWrite || DebugInfoCorrelate) ? NULL : NamesBegin,
+ {(SkipNameDataWrite || ProfileCorrelation) ? NULL : NamesBegin,
sizeof(uint8_t), NamesSize, 0},
{NULL, sizeof(uint8_t), PaddingBytesAfterNames, 1}};
if (Writer->Write(Writer, IOVecData, sizeof(IOVecData) / sizeof(*IOVecData)))
return -1;
-
- /* Value profiling is not yet supported in continuous mode. */
- if (__llvm_profile_is_continuous_mode_enabled())
+ /* Value profiling is not yet supported in continuous mode and profile
+ * correlation mode. */
+ if (__llvm_profile_is_continuous_mode_enabled() || ProfileCorrelation)
return 0;
return writeValueProfData(Writer, VPDataReader, DataBegin, DataEnd);
diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt
index f9b01b15b0e62c6..7357604b1f651eb 100644
--- a/compiler-rt/test/CMakeLists.txt
+++ b/compiler-rt/test/CMakeLists.txt
@@ -37,8 +37,9 @@ if(NOT ANDROID)
if(NOT COMPILER_RT_STANDALONE_BUILD AND NOT LLVM_RUNTIMES_BUILD)
# Use LLVM utils and Clang from the same build tree.
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS
- clang clang-resource-headers FileCheck count not llvm-config llvm-nm llvm-objdump
- llvm-readelf llvm-readobj llvm-size llvm-symbolizer compiler-rt-headers sancov split-file)
+ clang clang-resource-headers FileCheck count not llvm-config llvm-nm
+ llvm-objdump llvm-readelf llvm-readobj llvm-size llvm-symbolizer
+ compiler-rt-headers sancov split-file llvm-strip)
if (WIN32)
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS KillTheDoctor)
endif()
diff --git a/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c b/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c
index f347d439e2e0671..46d25a4e386dc3a 100644
--- a/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c
+++ b/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c
@@ -1,5 +1,5 @@
// Value profiling is currently not supported in lightweight mode.
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_pgogen -o %t -g -mllvm --profile-correlate=debug-info -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t.dSYM %t.proflite
@@ -9,7 +9,7 @@
// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
-// RUN: %clang_pgogen -o %t.cov -g -mllvm --debug-info-correlate -mllvm -pgo-function-entry-coverage -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_pgogen -o %t.cov -g -mllvm --profile-correlate=debug-info -mllvm -pgo-function-entry-coverage -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.cov.proflite %run %t.cov
// RUN: llvm-profdata merge -o %t.cov.profdata --debug-info=%t.cov.dSYM %t.cov.proflite
diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.c
index 5069c6340b64fd2..25022f241a6d281 100644
--- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.c
+++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.c
@@ -1,6 +1,6 @@
// Disable full debug info and verify that we get warnings during merging
-// RUN: %clang_pgogen -o %t -gline-tables-only -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_pgogen -o %t -gline-tables-only -mllvm --profile-correlate=debug-info -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.proflite --max-debug-info-correlation-warnings=2 2>&1 >/dev/null | FileCheck %s --check-prefixes=CHECK,LIMIT --implicit-check-not=warning
// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.proflite --max-debug-info-correlation-warnings=0 2>&1 >/dev/null | FileCheck %s --check-prefixes=CHECK,NOLIMIT --implicit-check-not=warning
diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
index a918d7b6299005e..ccfd65b6f4c4b16 100644
--- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
+++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
@@ -3,19 +3,19 @@
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
-// RUN: %clang_pgogen -o %t.d4 -g -gdwarf-4 -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_pgogen -o %t.d4 -g -gdwarf-4 -mllvm --profile-correlate=debug-info -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.d4.proflite %run %t.d4
// RUN: llvm-profdata merge -o %t.d4.profdata --debug-info=%t.d4 %t.d4.proflite
// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.d4.profdata)
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_pgogen -o %t -g -mllvm --profile-correlate=debug-info -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.proflite
// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
-// RUN: %clang_pgogen -o %t.cov -g -mllvm --debug-info-correlate -mllvm -pgo-function-entry-coverage -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_pgogen -o %t.cov -g -mllvm --profile-correlate=debug-info -mllvm -pgo-function-entry-coverage -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.cov.proflite %run %t.cov
// RUN: llvm-profdata merge -o %t.cov.profdata --debug-info=%t.cov %t.cov.proflite
diff --git a/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c
index 226d678aca347a4..93bf40f98d3ab62 100644
--- a/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c
+++ b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c
@@ -1,10 +1,10 @@
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %s
+// RUN: %clang_pgogen -o %t -g -mllvm --profile-correlate=debug-info -mllvm --disable-vp=true %s
// RUN: llvm-profdata show --debug-info=%t --detailed-summary --show-prof-sym-list | FileCheck %s
// RUN: llvm-profdata show --debug-info=%t --show-format=yaml | FileCheck %s --match-full-lines --check-prefix YAML
-// RUN: %clang_pgogen -o %t.no.dbg -mllvm --debug-info-correlate -mllvm --disable-vp=true %s
+// RUN: %clang_pgogen -o %t.no.dbg -mllvm --profile-correlate=debug-info -mllvm --disable-vp=true %s
// RUN: not llvm-profdata show --debug-info=%t.no.dbg 2>&1 | FileCheck %s --check-prefix NO-DBG
-// NO-DBG: unable to correlate profile: could not find any profile metadata in debug info
+// NO-DBG: unable to correlate profile: could not find any profile data metadata in correlated file
// YAML: Probes:
// YAML: - Function Name: a
diff --git a/compiler-rt/test/profile/instrprof-binary-correlate.c b/compiler-rt/test/profile/instrprof-binary-correlate.c
new file mode 100644
index 000000000000000..2154c13027e286b
--- /dev/null
+++ b/compiler-rt/test/profile/instrprof-binary-correlate.c
@@ -0,0 +1,29 @@
+// REQUIRES: linux || windows
+// Default
+// RUN: %clang -o %t.normal -fprofile-instr-generate -fcoverage-mapping -fuse-ld=lld %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
+// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
+
+// With -profile-correlate=binary flag
+// RUN: %clang -o %t-1.exe -fprofile-instr-generate -fcoverage-mapping -mllvm -profile-correlate=binary -fuse-ld=lld %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t-1.exe
+// RUN: llvm-profdata merge -o %t-1.profdata --object-file=%t-1.exe %t-1.profraw
+// RUN: diff %t.normal.profdata %t-1.profdata
+
+// Strip above binary and run
+// RUN: llvm-strip %t-1.exe -o %t-2.exe
+// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t-2.exe
+// RUN: llvm-profdata merge -o %t-2.profdata --object-file=%t-1.exe %t-2.profraw
+// RUN: diff %t.normal.profdata %t-2.profdata
+
+// Online merging.
+// RUN: env LLVM_PROFILE_FILE=%t-3.profraw %run %t.normal
+// RUN: env LLVM_PROFILE_FILE=%t-4.profraw %run %t.normal
+// RUN: llvm-profdata merge -o %t.normal.merged.profdata %t-3.profraw %t-4.profraw
+// RUN: rm -rf %t.profdir && mkdir %t.profdir
+// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m-4.profraw %run %t-2.exe
+// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m-4.profraw %run %t-2.exe
+// RUN: llvm-profdata merge -o %t-4.profdata --object-file=%t-1.exe %t.profdir
+// RUN: diff %t.normal.merged.profdata %t-4.profdata
+
+// TODO: After adding support for binary ID, test binaries with different binary IDs.
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 9239c1a691eca19..00a7bafb54e89ea 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -328,8 +328,8 @@ enum class instrprof_error {
too_large,
truncated,
malformed,
- missing_debug_info_for_correlation,
- unexpected_debug_info_for_correlation,
+ missing_correlation_info,
+ unexpected_correlation_info,
unable_to_correlate_profile,
unknown_function,
invalid_prof,
@@ -460,7 +460,7 @@ class InstrProfSymtab {
/// only initialize the symtab with reference to the data and
/// the section base address. The decompression will be delayed
/// until before it is used. See also \c create(StringRef) method.
- Error create(object::SectionRef &Section);
+ Error create(object::SectionRef &Section, bool MightHasNullByte = false);
/// This interface is used by reader of CoverageMapping test
/// format.
diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
index dd062951f277c1c..661570eaee11300 100644
--- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
+++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-// This file defines InstrProfCorrelator used to generate PGO profiles from
-// raw profile data and debug info.
+// This file defines InstrProfCorrelator used to generate PGO/coverage profiles
+// from raw profile data and debug info/binary file.
//===----------------------------------------------------------------------===//
#ifndef LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
@@ -31,8 +31,12 @@ class ObjectFile;
/// to their functions.
class InstrProfCorrelator {
public:
+ /// Indicate if we should use the debug info or profile metadata sections to
+ /// correlate.
+ enum ProfCorrelatorKind { NONE, DEBUG_INFO, BINARY };
+
static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
- get(StringRef DebugInfoFilename);
+ get(StringRef Filename, ProfCorrelatorKind FileKind);
/// Construct a ProfileData vector used to correlate raw instrumentation data
/// to their functions.
@@ -68,11 +72,18 @@ class InstrProfCorrelator {
protected:
struct Context {
static llvm::Expected<std::unique_ptr<Context>>
- get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj);
+ get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj,
+ ProfCorrelatorKind FileKind);
std::unique_ptr<MemoryBuffer> Buffer;
/// The address range of the __llvm_prf_cnts section.
uint64_t CountersSectionStart;
uint64_t CountersSectionEnd;
+ /// The pointer points to start/end of profile data/name sections if
+ /// FileKind is Binary.
+ const char *DataStart;
+ const char *DataEnd;
+ const char *NameStart;
+ size_t NameSize;
/// True if target and host have different endian orders.
bool ShouldSwapBytes;
};
@@ -104,7 +115,7 @@ class InstrProfCorrelator {
private:
static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
- get(std::unique_ptr<MemoryBuffer> Buffer);
+ get(std::unique_ptr<MemoryBuffer> Buffer, ProfCorrelatorKind FileKind);
const InstrProfCorrelatorKind Kind;
};
@@ -128,7 +139,7 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
get(std::unique_ptr<InstrProfCorrelator::Context> Ctx,
- const object::ObjectFile &Obj);
+ const object::ObjectFile &Obj, ProfCorrelatorKind FileKind);
protected:
std::vector<RawInstrProf::ProfileData<IntPtrT>> Data;
@@ -138,21 +149,23 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
int MaxWarnings,
InstrProfCorrelator::CorrelationData *Data = nullptr) = 0;
+ virtual Error correlateProfileNameImpl() = 0;
+
Error dumpYaml(int MaxWarnings, raw_ostream &OS) override;
void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset,
IntPtrT FunctionPtr, uint32_t NumCounters);
+ // Byte-swap the value if necessary.
+ template <class T> T maybeSwap(T Value) const {
+ return Ctx->ShouldSwapBytes ? llvm::byteswap(Value) : Value;
+ }
+
private:
InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind,
std::unique_ptr<InstrProfCorrelator::Context> Ctx)
: InstrProfCorrelator(Kind, std::move(Ctx)){};
llvm::DenseSet<IntPtrT> CounterOffsets;
-
- // Byte-swap the value if necessary.
- template <class T> T maybeSwap(T Value) const {
- return Ctx->ShouldSwapBytes ? llvm::byteswap(Value) : Value;
- }
};
/// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes
@@ -205,6 +218,30 @@ class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
void correlateProfileDataImpl(
int MaxWarnings,
InstrProfCorrelator::CorrelationData *Data = nullptr) override;
+
+ Error correlateProfileNameImpl() override;
+};
+
+/// BinaryInstrProfCorrelator - A child of InstrProfCorrelatorImpl that
+/// takes an object file as input to correlate profiles.
+template <class IntPtrT>
+class BinaryInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
+public:
+ BinaryInstrProfCorrelator(std::unique_ptr<InstrProfCorrelator::Context> Ctx)
+ : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)) {}
+
+ /// Return a pointer to the names string that this class constructs.
+ const char *getNamesPointer() const { return this->Ctx.NameStart; }
+
+ /// Return the number of bytes in the names string.
+ size_t getNamesSize() const { return this->Ctx.NameSize; }
+
+private:
+ void correlateProfileDataImpl(
+ int MaxWarnings,
+ InstrProfCorrelator::CorrelationData *Data = nullptr) override;
+
+ Error correlateProfileNameImpl() override;
};
} // end namespace llvm
diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc
index 13be2753e514efe..f6c5f2b3fa17301 100644
--- a/llvm/include/llvm/ProfileData/InstrProfData.inc
+++ b/llvm/include/llvm/ProfileData/InstrProfData.inc
@@ -655,6 +655,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
* version for other variants of profile. We set the 8th most significant bit
* (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation
* generated profile, and 0 if this is a Clang FE generated profile.
+ * 1 in bit 32 indicates whether to use binary to correlate profiles.
* 1 in bit 57 indicates there are context-sensitive records in the profile.
* The 59th bit indicates whether to use debug info to correlate profiles.
* The 60th bit indicates single byte coverage instrumentation.
@@ -664,6 +665,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
*/
#define VARIANT_MASKS_ALL 0xffffffff00000000ULL
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
+#define VARIANT_MASK_BIN_CORRELATE (0x1ULL << 32)
#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57)
#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58)
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index 5f54cbeb1b01eda..d5eb009087d9f9b 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -126,6 +126,8 @@ class InstrProfReader {
/// Return true if we must provide debug info to create PGO profiles.
virtual bool useDebugInfoCorrelate() const { return false; }
+ virtual bool useBinaryCorrelate() const { return false; }
+
/// Return true if the profile has single byte counters representing coverage.
virtual bool hasSingleByteCoverage() const = 0;
@@ -374,6 +376,14 @@ class RawInstrProfReader : public InstrProfReader {
return (Version & VARIANT_MASK_DBG_CORRELATE) != 0;
}
+ bool useBinaryCorrelate() const override {
+ return (Version & VARIANT_MASK_BIN_CORRELATE) != 0;
+ }
+
+ bool useCorrelate() const {
+ return useDebugInfoCorrelate() || useBinaryCorrelate();
+ }
+
bool hasSingleByteCoverage() const override {
return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0;
}
diff --git a/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h b/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h
index 5b1977b7de9a2ae..3d8f3bd9235451f 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h
@@ -24,8 +24,6 @@
namespace llvm {
-extern cl::opt<bool> DebugInfoCorrelate;
-
class Function;
class Instruction;
class Module;
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 6210e7fc128a30c..fd785ff2629932e 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -57,6 +57,7 @@
#include "llvm/MC/MCValue.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/ProfileData/InstrProfCorrelator.h"
#include "llvm/Support/Base64.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
@@ -71,6 +72,10 @@
using namespace llvm;
using namespace dwarf;
+namespace llvm {
+extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;
+} // namespace llvm
+
static cl::opt<bool> JumpTableInFunctionSection(
"jumptable-in-function-section", cl::Hidden, cl::init(false),
cl::desc("Putting Jump Table in function section"));
@@ -472,7 +477,15 @@ static SectionKind getELFKindForNamedSection(StringRef Name, SectionKind K) {
/*AddSegmentInfo=*/false) ||
Name == getInstrProfSectionName(IPSK_covfun, Triple::ELF,
/*AddSegmentInfo=*/false) ||
- Name == ".llvmbc" || Name == ".llvmcmd")
+ Name == ".llvmbc" || Name == ".llvmcmd" ||
+ // Instead of checking the flag, maybe we should check if
+ // VARIANT_MASK_BIN_CORRELATE flag is set at the profile version global
+ // variable.
+ (ProfileCorrelate == InstrProfCorrelator::BINARY &&
+ (Name == getInstrProfSectionName(llvm::IPSK_name, Triple::ELF,
+ /*AddSegmentInfo=*/false) ||
+ Name == getInstrProfSectionName(llvm::IPSK_data, Triple::ELF,
+ /*AddSegmentInfo=*/false))))
return SectionKind::getMetadata();
if (Name.empty() || Name[0] != '.') return K;
@@ -1674,9 +1687,15 @@ static int getSelectionForCOFF(const GlobalValue *GV) {
MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
+ StringRef Name = GO->getSection();
+ if (ProfileCorrelate == InstrProfCorrelator::BINARY &&
+ (Name == getInstrProfSectionName(llvm::IPSK_name, Triple::COFF,
+ /*AddSegmentInfo=*/false) ||
+ Name == getInstrProfSectionName(llvm::IPSK_data, Triple::COFF,
+ /*AddSegmentInfo=*/false)))
+ Kind = SectionKind::getMetadata();
int Selection = 0;
unsigned Characteristics = getCOFFSectionFlags(Kind, TM);
- StringRef Name = GO->getSection();
StringRef COMDATSymName = "";
if (GO->hasComdat()) {
Selection = getSelectionForCOFF(GO);
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index 857498256ec54c4..a56e4c90911141b 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -457,7 +457,7 @@ Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
return Tag == Counter::Zero;
}
-Error InstrProfSymtab::create(SectionRef &Section) {
+Error InstrProfSymtab::create(SectionRef &Section, bool MightHasNullByte) {
Expected<StringRef> DataOrErr = Section.getContents();
if (!DataOrErr)
return DataOrErr.takeError();
@@ -467,7 +467,8 @@ Error InstrProfSymtab::create(SectionRef &Section) {
// If this is a linked PE/COFF file, then we have to skip over the null byte
// that is allocated in the .lprfn$A section in the LLVM profiling runtime.
const ObjectFile *Obj = Section.getObject();
- if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
+ if (MightHasNullByte && isa<COFFObjectFile>(Obj) &&
+ !Obj->isRelocatableObject())
Data = Data.drop_front(1);
return Error::success();
@@ -1070,11 +1071,24 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
InstrProfSymtab ProfileNames;
std::vector<SectionRef> NamesSectionRefs = *NamesSection;
- if (NamesSectionRefs.size() != 1)
- return make_error<CoverageMapError>(
- coveragemap_error::malformed,
- "the size of coverage mapping section is not one");
- if (Error E = ProfileNames.create(NamesSectionRefs.back()))
+ bool MightHasNullByte = true;
+ if (NamesSectionRefs.size() != 1) {
+ // By default, the profile name section in the binary starts with a null
+ // byte and followed by names. But if binary correlation is enabled, there
+ // will be 2 name sections. One contains only two null bytes, and another
+ // one contains the names without the dummy null byte at the beginning.
+ if (ObjFormat == Triple::COFF) {
+ NamesSectionRefs.erase(
+ std::remove_if(NamesSectionRefs.begin(), NamesSectionRefs.end(),
+ [](const SectionRef &S) { return S.isData(); }));
+ MightHasNullByte = false;
+ }
+ if (NamesSectionRefs.size() != 1)
+ return make_error<CoverageMapError>(
+ coveragemap_error::malformed,
+ "the size of coverage mapping section is not one");
+ }
+ if (Error E = ProfileNames.create(NamesSectionRefs.back(), MightHasNullByte))
return std::move(E);
// Look for the coverage records section (Version4 only).
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index ddc11304742df76..349ebf3762df40a 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -113,11 +113,11 @@ static std::string getInstrProfErrString(instrprof_error Err,
case instrprof_error::malformed:
OS << "malformed instrumentation profile data";
break;
- case instrprof_error::missing_debug_info_for_correlation:
- OS << "debug info for correlation is required";
+ case instrprof_error::missing_correlation_info:
+ OS << "debug info/binary for correlation is required";
break;
- case instrprof_error::unexpected_debug_info_for_correlation:
- OS << "debug info for correlation is not necessary";
+ case instrprof_error::unexpected_correlation_info:
+ OS << "debug info/binary for correlation is not necessary";
break;
case instrprof_error::unable_to_correlate_profile:
OS << "unable to correlate profile";
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index 71787c9bd8577b4..347879e71bbda18 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -24,15 +24,43 @@
using namespace llvm;
-/// Get the __llvm_prf_cnts section.
-Expected<object::SectionRef> getCountersSection(const object::ObjectFile &Obj) {
+namespace llvm {
+cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate(
+ "profile-correlate",
+ cl::desc("Use debug info or binary file to correlate profiles."),
+ cl::init(InstrProfCorrelator::NONE),
+ cl::values(clEnumValN(InstrProfCorrelator::NONE, "",
+ "No profile correlation"),
+ clEnumValN(InstrProfCorrelator::DEBUG_INFO, "debug-info",
+ "Use debug info to correlate"),
+ clEnumValN(InstrProfCorrelator::BINARY, "binary",
+ "Use binary to correlate")));
+} // namespace llvm
+
+/// Get profile section.
+Expected<object::SectionRef> getInstrProfSection(const object::ObjectFile &Obj,
+ InstrProfSectKind IPSK) {
+ // On COFF, the object file section name may end in "$M". This tells the
+ // linker to sort these sections between "$A" and "$Z". The linker removes the
+ // dollar and everything after it in the final binary. Do the same to match.
+ Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat();
+ std::string ExpectedSectionName =
+ getInstrProfSectionName(IPSK, ObjFormat,
+ /*AddSegmentInfo=*/false);
for (auto &Section : Obj.sections())
if (auto SectionName = Section.getName())
- if (SectionName.get() == INSTR_PROF_CNTS_SECT_NAME)
+ if (SectionName.get() == ExpectedSectionName) {
+ // There will be extra profile name and data sections in COFF used for
+ // runtime to detect start/stop of those sections, skipping them.
+ // (details at compiler-rt/lib/profile/InstrProfilingPlatformWindows.c)
+ if (ObjFormat == Triple::COFF && IPSK != IPSK_cnts && Section.isData())
+ continue;
return Section;
+ }
+
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile,
- "could not find counter section (" INSTR_PROF_CNTS_SECT_NAME ")");
+ "could not find section (" + Twine(ExpectedSectionName) + ")");
}
const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name";
@@ -41,56 +69,84 @@ const char *InstrProfCorrelator::NumCountersAttributeName = "Num Counters";
llvm::Expected<std::unique_ptr<InstrProfCorrelator::Context>>
InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
- const object::ObjectFile &Obj) {
- auto CountersSection = getCountersSection(Obj);
+ const object::ObjectFile &Obj,
+ ProfCorrelatorKind FileKind) {
+ auto C = std::make_unique<Context>();
+ auto CountersSection = getInstrProfSection(Obj, IPSK_cnts);
if (auto Err = CountersSection.takeError())
return std::move(Err);
- auto C = std::make_unique<Context>();
+ if (FileKind == InstrProfCorrelator::BINARY) {
+ auto DataSection = getInstrProfSection(Obj, IPSK_data);
+ if (auto Err = DataSection.takeError())
+ return std::move(Err);
+ auto DataOrErr = DataSection->getContents();
+ if (!DataOrErr)
+ return DataOrErr.takeError();
+ auto NameSection = getInstrProfSection(Obj, IPSK_name);
+ if (auto Err = NameSection.takeError())
+ return std::move(Err);
+ auto NameOrErr = NameSection->getContents();
+ if (!NameOrErr)
+ return NameOrErr.takeError();
+ C->DataStart = DataOrErr->data();
+ C->DataEnd = DataOrErr->data() + DataOrErr->size();
+ C->NameStart = NameOrErr->data();
+ C->NameSize = NameOrErr->size();
+ }
C->Buffer = std::move(Buffer);
C->CountersSectionStart = CountersSection->getAddress();
C->CountersSectionEnd = C->CountersSectionStart + CountersSection->getSize();
+ // In COFF object file, there's a null byte at the beginning of the counter
+ // section which doesn't exist in raw profile.
+ if (Obj.getTripleObjectFormat() == Triple::COFF)
+ C->CountersSectionStart++;
+
C->ShouldSwapBytes = Obj.isLittleEndian() != sys::IsLittleEndianHost;
return Expected<std::unique_ptr<Context>>(std::move(C));
}
llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
-InstrProfCorrelator::get(StringRef DebugInfoFilename) {
- auto DsymObjectsOrErr =
- object::MachOObjectFile::findDsymObjectMembers(DebugInfoFilename);
- if (auto Err = DsymObjectsOrErr.takeError())
- return std::move(Err);
- if (!DsymObjectsOrErr->empty()) {
- // TODO: Enable profile correlation when there are multiple objects in a
- // dSYM bundle.
- if (DsymObjectsOrErr->size() > 1)
- return make_error<InstrProfError>(
- instrprof_error::unable_to_correlate_profile,
- "using multiple objects is not yet supported");
- DebugInfoFilename = *DsymObjectsOrErr->begin();
+InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind) {
+ if (FileKind == DEBUG_INFO) {
+ auto DsymObjectsOrErr =
+ object::MachOObjectFile::findDsymObjectMembers(Filename);
+ if (auto Err = DsymObjectsOrErr.takeError())
+ return std::move(Err);
+ if (!DsymObjectsOrErr->empty()) {
+ // TODO: Enable profile correlation when there are multiple objects in a
+ // dSYM bundle.
+ if (DsymObjectsOrErr->size() > 1)
+ return make_error<InstrProfError>(
+ instrprof_error::unable_to_correlate_profile,
+ "using multiple objects is not yet supported");
+ Filename = *DsymObjectsOrErr->begin();
+ }
}
- auto BufferOrErr =
- errorOrToExpected(MemoryBuffer::getFile(DebugInfoFilename));
+ auto BufferOrErr = errorOrToExpected(MemoryBuffer::getFile(Filename));
if (auto Err = BufferOrErr.takeError())
return std::move(Err);
- return get(std::move(*BufferOrErr));
+ return get(std::move(*BufferOrErr), FileKind);
}
llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
-InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer) {
+InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer,
+ ProfCorrelatorKind FileKind) {
auto BinOrErr = object::createBinary(*Buffer);
if (auto Err = BinOrErr.takeError())
return std::move(Err);
if (auto *Obj = dyn_cast<object::ObjectFile>(BinOrErr->get())) {
- auto CtxOrErr = Context::get(std::move(Buffer), *Obj);
+ auto CtxOrErr = Context::get(std::move(Buffer), *Obj, FileKind);
if (auto Err = CtxOrErr.takeError())
return std::move(Err);
auto T = Obj->makeTriple();
if (T.isArch64Bit())
- return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj);
+ return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj,
+ FileKind);
if (T.isArch32Bit())
- return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj);
+ return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj,
+ FileKind);
}
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile, "not an object file");
@@ -132,29 +188,35 @@ template <class IntPtrT>
llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
InstrProfCorrelatorImpl<IntPtrT>::get(
std::unique_ptr<InstrProfCorrelator::Context> Ctx,
- const object::ObjectFile &Obj) {
- if (Obj.isELF() || Obj.isMachO()) {
- auto DICtx = DWARFContext::create(Obj);
- return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(std::move(DICtx),
- std::move(Ctx));
+ const object::ObjectFile &Obj, ProfCorrelatorKind FileKind) {
+ if (FileKind == DEBUG_INFO) {
+ if (Obj.isELF() || Obj.isMachO()) {
+ auto DICtx = DWARFContext::create(Obj);
+ return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(
+ std::move(DICtx), std::move(Ctx));
+ }
+ return make_error<InstrProfError>(
+ instrprof_error::unable_to_correlate_profile,
+ "unsupported debug info format (only DWARF is supported)");
}
+ if (Obj.isELF() || Obj.isCOFF())
+ return std::make_unique<BinaryInstrProfCorrelator<IntPtrT>>(std::move(Ctx));
return make_error<InstrProfError>(
- instrprof_error::unable_to_correlate_profile,
- "unsupported debug info format (only DWARF is supported)");
+ instrprof_error::unable_to_correlate_profile,
+ "unsupported binary format (only ELF and COFF are supported)");
}
template <class IntPtrT>
Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData(int MaxWarnings) {
assert(Data.empty() && Names.empty() && NamesVec.empty());
correlateProfileDataImpl(MaxWarnings);
- if (Data.empty() || NamesVec.empty())
+ if (this->Data.empty())
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile,
- "could not find any profile metadata in debug info");
- auto Result =
- collectPGOFuncNameStrings(NamesVec, /*doCompression=*/false, Names);
- CounterOffsets.clear();
- NamesVec.clear();
+ "could not find any profile data metadata in correlated file");
+ Error Result = correlateProfileNameImpl();
+ this->CounterOffsets.clear();
+ this->NamesVec.clear();
return Result;
}
@@ -361,3 +423,64 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
WithColor::warning() << format("Suppressed %d additional warnings\n",
NumSuppressedWarnings);
}
+
+template <class IntPtrT>
+Error DwarfInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
+ if (this->NamesVec.empty()) {
+ return make_error<InstrProfError>(
+ instrprof_error::unable_to_correlate_profile,
+ "could not find any profile name metadata in debug info");
+ }
+ auto Result = collectPGOFuncNameStrings(this->NamesVec,
+ /*doCompression=*/false, this->Names);
+ return Result;
+}
+
+template <class IntPtrT>
+void BinaryInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
+ int MaxWarnings, InstrProfCorrelator::CorrelationData *CorrelateData) {
+ bool UnlimitedWarnings = (MaxWarnings == 0);
+ // -N suppressed warnings means we can emit up to N (unsuppressed) warnings
+ int NumSuppressedWarnings = -MaxWarnings;
+
+ const RawInstrProf::ProfileData<IntPtrT> *DataStart =
+ (const RawInstrProf::ProfileData<IntPtrT> *)this->Ctx->DataStart;
+ const RawInstrProf::ProfileData<IntPtrT> *DataEnd =
+ (const RawInstrProf::ProfileData<IntPtrT> *)this->Ctx->DataEnd;
+ // We need to use < here because the last data record may have no padding.
+ for (const RawInstrProf::ProfileData<IntPtrT> *I = DataStart; I < DataEnd;
+ ++I) {
+ uint64_t CounterPtr = this->template maybeSwap<IntPtrT>(I->CounterPtr);
+ uint64_t CountersStart = this->Ctx->CountersSectionStart;
+ uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
+ if (CounterPtr < CountersStart || CounterPtr >= CountersEnd) {
+ if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ WithColor::warning() << format(
+ "CounterPtr out of range for function: Actual=0x%x "
+ "Expected=[0x%x, 0x%x) at data offset=0x%x\n",
+ CounterPtr, CountersStart, CountersEnd,
+ (I - DataStart) * sizeof(RawInstrProf::ProfileData<IntPtrT>));
+ }
+ }
+ IntPtrT CounterOffset = CounterPtr - CountersStart;
+ this->Data.push_back({I->NameRef,
+ I->FuncHash,
+ this->template maybeSwap<IntPtrT>(CounterOffset),
+ I->FunctionPointer,
+ // Value profiling is not supported.
+ 0,
+ I->NumCounters,
+ {0, 0}});
+ }
+}
+
+template <class IntPtrT>
+Error BinaryInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
+ if (this->Ctx->NameSize == 0) {
+ return make_error<InstrProfError>(
+ instrprof_error::unable_to_correlate_profile,
+ "could not find any profile data metadata in object file");
+ }
+ this->Names.append(this->Ctx->NameStart, this->Ctx->NameSize);
+ return Error::success();
+}
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index a920a31d0a4b229..2b5181e6b34043c 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -540,10 +540,10 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
"\nPLEASE update this tool to version in the raw profile, or "
"regenerate raw profile with expected version.")
.str());
- if (useDebugInfoCorrelate() && !Correlator)
- return error(instrprof_error::missing_debug_info_for_correlation);
- if (!useDebugInfoCorrelate() && Correlator)
- return error(instrprof_error::unexpected_debug_info_for_correlation);
+ if (useCorrelate() && !Correlator)
+ return error(instrprof_error::missing_correlation_info);
+ if (!useCorrelate() && Correlator)
+ return error(instrprof_error::unexpected_correlation_info);
BinaryIdsSize = swap(Header.BinaryIdsSize);
if (BinaryIdsSize % sizeof(uint64_t))
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index 57fcfd53836911b..7eaa92bfe842e16 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -60,10 +60,7 @@ using namespace llvm;
#define DEBUG_TYPE "instrprof"
namespace llvm {
-cl::opt<bool>
- DebugInfoCorrelate("debug-info-correlate",
- cl::desc("Use debug info to correlate profiles."),
- cl::init(false));
+extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;
} // namespace llvm
namespace {
@@ -627,7 +624,7 @@ void InstrProfiling::lowerValueProfileInst(InstrProfValueProfileInst *Ind) {
// in lightweight mode. We need to move the value profile pointer to the
// Counter struct to get this working.
assert(
- !DebugInfoCorrelate &&
+ ProfileCorrelate == InstrProfCorrelator::NONE &&
"Value profiling is not yet supported with lightweight instrumentation");
GlobalVariable *Name = Ind->getName();
auto It = ProfileDataMap.find(Name);
@@ -965,8 +962,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
// Use internal rather than private linkage so the counter variable shows up
// in the symbol table when using debug info for correlation.
- if (DebugInfoCorrelate && TT.isOSBinFormatMachO() &&
- Linkage == GlobalValue::PrivateLinkage)
+ if (ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO &&
+ TT.isOSBinFormatMachO() && Linkage == GlobalValue::PrivateLinkage)
Linkage = GlobalValue::InternalLinkage;
// Due to the limitation of binder as of 2021/09/28, the duplicate weak
@@ -1030,7 +1027,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
CounterPtr->setLinkage(Linkage);
MaybeSetComdat(CounterPtr);
PD.RegionCounters = CounterPtr;
- if (DebugInfoCorrelate) {
+ if (ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO) {
if (auto *SP = Fn->getSubprogram()) {
DIBuilder DB(*M, true, SP->getUnit());
Metadata *FunctionNameAnnotation[] = {
@@ -1083,7 +1080,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
}
- if (DebugInfoCorrelate) {
+ if (ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO) {
// Mark the counter variable as used so that it isn't optimized out.
CompilerUsedVars.push_back(PD.RegionCounters);
return PD.RegionCounters;
@@ -1124,11 +1121,17 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
}
auto *Data =
new GlobalVariable(*M, DataTy, false, Linkage, nullptr, DataVarName);
- // Reference the counter variable with a label difference (link-time
- // constant).
- auto *RelativeCounterPtr =
- ConstantExpr::getSub(ConstantExpr::getPtrToInt(CounterPtr, IntPtrTy),
- ConstantExpr::getPtrToInt(Data, IntPtrTy));
+ Constant *RelativeCounterPtr;
+ if (ProfileCorrelate == InstrProfCorrelator::BINARY) {
+ // CounterPtr needs to be absolute when we make data section strippable.
+ RelativeCounterPtr = ConstantExpr::getPtrToInt(CounterPtr, IntPtrTy);
+ } else {
+ // Reference the counter variable with a label difference (link-time
+ // constant).
+ RelativeCounterPtr =
+ ConstantExpr::getSub(ConstantExpr::getPtrToInt(CounterPtr, IntPtrTy),
+ ConstantExpr::getPtrToInt(Data, IntPtrTy));
+ }
Constant *DataVals[] = {
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init,
diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
index 7ad1c9bc54f3780..6dcbf3ada5f0c72 100644
--- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
+++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
@@ -327,6 +327,7 @@ extern cl::opt<PGOViewCountsType> PGOViewCounts;
// Defined in Analysis/BlockFrequencyInfo.cpp: -view-bfi-func-name=
extern cl::opt<std::string> ViewBlockFreqFuncName;
+extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;
} // namespace llvm
static cl::opt<bool>
@@ -381,7 +382,7 @@ static GlobalVariable *createIRLevelProfileFlagVar(Module &M, bool IsCS) {
ProfileVersion |= VARIANT_MASK_CSIR_PROF;
if (PGOInstrumentEntry)
ProfileVersion |= VARIANT_MASK_INSTR_ENTRY;
- if (DebugInfoCorrelate)
+ if (ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO)
ProfileVersion |= VARIANT_MASK_DBG_CORRELATE;
if (PGOFunctionEntryCoverage)
ProfileVersion |=
diff --git a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-coverage.ll b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-coverage.ll
index 192bac6e503a07b..dd6461533817050 100644
--- a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-coverage.ll
+++ b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-coverage.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -passes=instrprof -debug-info-correlate -S | opt -O2 -S | FileCheck %s
+; RUN: opt < %s -passes=instrprof -profile-correlate=debug-info -S | opt -O2 -S | FileCheck %s
@__profn_foo = private constant [3 x i8] c"foo"
; CHECK: @__profc_foo
diff --git a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll
index fd868ead5b78d21..84eaab33701a487 100644
--- a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll
+++ b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -passes=instrprof -debug-info-correlate -S > %t.ll
+; RUN: opt < %s -passes=instrprof -profile-correlate=debug-info -S > %t.ll
; RUN: FileCheck < %t.ll --implicit-check-not "{{__llvm_prf_data|__llvm_prf_names}}" %s
; RUN: %llc_dwarf -O0 -filetype=obj < %t.ll | llvm-dwarfdump - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s --check-prefix CHECK-DWARF
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 7d665a8005b0d62..c0db32e8343d820 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -413,10 +413,11 @@ static void writeInstrProfile(StringRef OutputFilename,
static void
mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename,
- SymbolRemapper *Remapper, StringRef OutputFilename,
- ProfileFormat OutputFormat, uint64_t TraceReservoirSize,
- uint64_t MaxTraceLength, int MaxDbgCorrelationWarnings,
- bool OutputSparse, unsigned NumThreads, FailureMode FailMode,
+ StringRef ObjectFilename, SymbolRemapper *Remapper,
+ StringRef OutputFilename, ProfileFormat OutputFormat,
+ uint64_t TraceReservoirSize, uint64_t MaxTraceLength,
+ int MaxDbgCorrelationWarnings, bool OutputSparse,
+ unsigned NumThreads, FailureMode FailMode,
const StringRef ProfiledBinary) {
if (OutputFormat == PF_Compact_Binary)
exitWithError("Compact Binary is deprecated");
@@ -425,12 +426,17 @@ mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename,
exitWithError("unknown format is specified");
std::unique_ptr<InstrProfCorrelator> Correlator;
- if (!DebugInfoFilename.empty()) {
+ if (!DebugInfoFilename.empty() || !ObjectFilename.empty()) {
+ InstrProfCorrelator::ProfCorrelatorKind Kind =
+ DebugInfoFilename.empty() ? InstrProfCorrelator::BINARY
+ : InstrProfCorrelator::DEBUG_INFO;
+ StringRef FileName =
+ DebugInfoFilename.empty() ? ObjectFilename : DebugInfoFilename;
if (auto Err =
- InstrProfCorrelator::get(DebugInfoFilename).moveInto(Correlator))
- exitWithError(std::move(Err), DebugInfoFilename);
+ InstrProfCorrelator::get(FileName, Kind).moveInto(Correlator))
+ exitWithError(std::move(Err), FileName);
if (auto Err = Correlator->correlateProfileData(MaxDbgCorrelationWarnings))
- exitWithError(std::move(Err), DebugInfoFilename);
+ exitWithError(std::move(Err), FileName);
}
std::mutex ErrorLock;
@@ -1279,6 +1285,10 @@ static int merge_main(int argc, const char *argv[]) {
cl::opt<std::string> DebugInfoFilename(
"debug-info", cl::init(""),
cl::desc("Use the provided debug info to correlate the raw profile."));
+ cl::opt<std::string> ObjectFilename(
+ "object-file", cl::init(""),
+ cl::desc("Read and extract profile metadata from object file and show "
+ "the functions it found."));
cl::opt<unsigned> MaxDbgCorrelationWarnings(
"max-debug-info-correlation-warnings",
cl::desc("The maximum number of warnings to emit when correlating "
@@ -1304,6 +1314,9 @@ static int merge_main(int argc, const char *argv[]) {
"(default: 10000)"));
cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
+ if (!DebugInfoFilename.empty() && !ObjectFilename.empty()) {
+ exitWithError("Expected only one of -debug-info, -object-file");
+ }
WeightedFileVector WeightedInputs;
for (StringRef Filename : InputFilenames)
@@ -1342,8 +1355,8 @@ static int merge_main(int argc, const char *argv[]) {
}
if (ProfileKind == instr)
- mergeInstrProfile(WeightedInputs, DebugInfoFilename, Remapper.get(),
- OutputFilename, OutputFormat,
+ mergeInstrProfile(WeightedInputs, DebugInfoFilename, ObjectFilename,
+ Remapper.get(), OutputFilename, OutputFormat,
TemporalProfTraceReservoirSize,
TemporalProfMaxTraceLength, MaxDbgCorrelationWarnings,
OutputSparse, NumThreads, FailureMode, ProfiledBinary);
@@ -2893,7 +2906,9 @@ static int showDebugInfoCorrelation(const std::string &Filename,
if (SFormat == ShowFormat::Json)
exitWithError("JSON output is not supported for debug info correlation");
std::unique_ptr<InstrProfCorrelator> Correlator;
- if (auto Err = InstrProfCorrelator::get(Filename).moveInto(Correlator))
+ if (auto Err =
+ InstrProfCorrelator::get(Filename, InstrProfCorrelator::DEBUG_INFO)
+ .moveInto(Correlator))
exitWithError(std::move(Err), Filename);
if (SFormat == ShowFormat::Yaml) {
if (auto Err = Correlator->dumpYaml(MaxDbgCorrelationWarnings, OS))
>From 776784459f67f44c0455ab0f3b216f7d9c6a6376 Mon Sep 17 00:00:00 2001
From: My Name <zequanwu at google.com>
Date: Wed, 18 Oct 2023 13:30:21 -0400
Subject: [PATCH 2/5] fix correlator for coff.
---
llvm/lib/ProfileData/InstrProfCorrelator.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index 347879e71bbda18..168c2803145f1ff 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -44,12 +44,16 @@ Expected<object::SectionRef> getInstrProfSection(const object::ObjectFile &Obj,
// linker to sort these sections between "$A" and "$Z". The linker removes the
// dollar and everything after it in the final binary. Do the same to match.
Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat();
+ auto StripSuffix = [ObjFormat](StringRef N) {
+ return ObjFormat == Triple::COFF ? N.split('$').first : N;
+ };
std::string ExpectedSectionName =
getInstrProfSectionName(IPSK, ObjFormat,
/*AddSegmentInfo=*/false);
+ ExpectedSectionName = StripSuffix(ExpectedSectionName);
for (auto &Section : Obj.sections())
if (auto SectionName = Section.getName())
- if (SectionName.get() == ExpectedSectionName) {
+ if (StripSuffix(*SectionName) == ExpectedSectionName) {
// There will be extra profile name and data sections in COFF used for
// runtime to detect start/stop of those sections, skipping them.
// (details at compiler-rt/lib/profile/InstrProfilingPlatformWindows.c)
>From c5cca07062572077c4140b4eb9a4bdbb22a385a6 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Wed, 18 Oct 2023 13:59:04 -0400
Subject: [PATCH 3/5] update docs and renaming option
---
.../test/profile/instrprof-binary-correlate.c | 6 +++---
llvm/docs/CommandGuide/llvm-profdata.rst | 13 +++++++++----
llvm/tools/llvm-profdata/llvm-profdata.cpp | 18 +++++++++---------
3 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/compiler-rt/test/profile/instrprof-binary-correlate.c b/compiler-rt/test/profile/instrprof-binary-correlate.c
index 2154c13027e286b..bc05dbd99b82516 100644
--- a/compiler-rt/test/profile/instrprof-binary-correlate.c
+++ b/compiler-rt/test/profile/instrprof-binary-correlate.c
@@ -7,13 +7,13 @@
// With -profile-correlate=binary flag
// RUN: %clang -o %t-1.exe -fprofile-instr-generate -fcoverage-mapping -mllvm -profile-correlate=binary -fuse-ld=lld %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t-1.exe
-// RUN: llvm-profdata merge -o %t-1.profdata --object-file=%t-1.exe %t-1.profraw
+// RUN: llvm-profdata merge -o %t-1.profdata --binary-file=%t-1.exe %t-1.profraw
// RUN: diff %t.normal.profdata %t-1.profdata
// Strip above binary and run
// RUN: llvm-strip %t-1.exe -o %t-2.exe
// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t-2.exe
-// RUN: llvm-profdata merge -o %t-2.profdata --object-file=%t-1.exe %t-2.profraw
+// RUN: llvm-profdata merge -o %t-2.profdata --binary-file=%t-1.exe %t-2.profraw
// RUN: diff %t.normal.profdata %t-2.profdata
// Online merging.
@@ -23,7 +23,7 @@
// RUN: rm -rf %t.profdir && mkdir %t.profdir
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m-4.profraw %run %t-2.exe
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m-4.profraw %run %t-2.exe
-// RUN: llvm-profdata merge -o %t-4.profdata --object-file=%t-1.exe %t.profdir
+// RUN: llvm-profdata merge -o %t-4.profdata --binary-file=%t-1.exe %t.profdir
// RUN: diff %t.normal.merged.profdata %t-4.profdata
// TODO: After adding support for binary ID, test binaries with different binary IDs.
diff --git a/llvm/docs/CommandGuide/llvm-profdata.rst b/llvm/docs/CommandGuide/llvm-profdata.rst
index be42733ca140567..f81c80601e98a11 100644
--- a/llvm/docs/CommandGuide/llvm-profdata.rst
+++ b/llvm/docs/CommandGuide/llvm-profdata.rst
@@ -195,8 +195,13 @@ OPTIONS
.. option:: --debug-info=<path>
Specify the executable or ``.dSYM`` that contains debug info for the raw profile.
- When ``-debug-info-correlate`` was used for instrumentation, use this option
- to correlate the raw profile.
+ When ``-profile-correlate=debug-info`` was used for instrumentation, use this
+ option to correlate the raw profile.
+
+.. option:: --binary-file=<path>
+Specify the executable that contains profile data and profile name sections for
+the raw profile. When ``-profile-correlate=binary`` was used for
+instrumentation, use this option to correlate the raw profile.
.. option:: --temporal-profile-trace-reservoir-size
@@ -346,8 +351,8 @@ OPTIONS
.. option:: --debug-info=<path>
Specify the executable or ``.dSYM`` that contains debug info for the raw profile.
- When ``-debug-info-correlate`` was used for instrumentation, use this option
- to show the correlated functions from the raw profile.
+ When ``-profile-correlate=debug-info`` was used for instrumentation, use this
+ option to show the correlated functions from the raw profile.
.. option:: --covered
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index c0db32e8343d820..068504228d97d3f 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -413,7 +413,7 @@ static void writeInstrProfile(StringRef OutputFilename,
static void
mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename,
- StringRef ObjectFilename, SymbolRemapper *Remapper,
+ StringRef BinaryFilename, SymbolRemapper *Remapper,
StringRef OutputFilename, ProfileFormat OutputFormat,
uint64_t TraceReservoirSize, uint64_t MaxTraceLength,
int MaxDbgCorrelationWarnings, bool OutputSparse,
@@ -426,12 +426,12 @@ mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename,
exitWithError("unknown format is specified");
std::unique_ptr<InstrProfCorrelator> Correlator;
- if (!DebugInfoFilename.empty() || !ObjectFilename.empty()) {
+ if (!DebugInfoFilename.empty() || !BinaryFilename.empty()) {
InstrProfCorrelator::ProfCorrelatorKind Kind =
DebugInfoFilename.empty() ? InstrProfCorrelator::BINARY
: InstrProfCorrelator::DEBUG_INFO;
StringRef FileName =
- DebugInfoFilename.empty() ? ObjectFilename : DebugInfoFilename;
+ DebugInfoFilename.empty() ? BinaryFilename : DebugInfoFilename;
if (auto Err =
InstrProfCorrelator::get(FileName, Kind).moveInto(Correlator))
exitWithError(std::move(Err), FileName);
@@ -1285,9 +1285,9 @@ static int merge_main(int argc, const char *argv[]) {
cl::opt<std::string> DebugInfoFilename(
"debug-info", cl::init(""),
cl::desc("Use the provided debug info to correlate the raw profile."));
- cl::opt<std::string> ObjectFilename(
- "object-file", cl::init(""),
- cl::desc("Read and extract profile metadata from object file and show "
+ cl::opt<std::string> BinaryFilename(
+ "binary-file", cl::init(""),
+ cl::desc("Read and extract profile metadata from binary file and show "
"the functions it found."));
cl::opt<unsigned> MaxDbgCorrelationWarnings(
"max-debug-info-correlation-warnings",
@@ -1314,8 +1314,8 @@ static int merge_main(int argc, const char *argv[]) {
"(default: 10000)"));
cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
- if (!DebugInfoFilename.empty() && !ObjectFilename.empty()) {
- exitWithError("Expected only one of -debug-info, -object-file");
+ if (!DebugInfoFilename.empty() && !BinaryFilename.empty()) {
+ exitWithError("Expected only one of -debug-info, -binary-file");
}
WeightedFileVector WeightedInputs;
@@ -1355,7 +1355,7 @@ static int merge_main(int argc, const char *argv[]) {
}
if (ProfileKind == instr)
- mergeInstrProfile(WeightedInputs, DebugInfoFilename, ObjectFilename,
+ mergeInstrProfile(WeightedInputs, DebugInfoFilename, BinaryFilename,
Remapper.get(), OutputFilename, OutputFormat,
TemporalProfTraceReservoirSize,
TemporalProfMaxTraceLength, MaxDbgCorrelationWarnings,
>From 44704f6fd6ec0f277ed734b2d91c15b1fb3a7fe6 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Wed, 18 Oct 2023 14:48:54 -0400
Subject: [PATCH 4/5] format
---
clang/lib/CodeGen/BackendUtil.cpp | 2 +-
compiler-rt/test/profile/instrprof-binary-correlate.c | 8 ++++----
llvm/docs/CommandGuide/llvm-profdata.rst | 7 ++++---
llvm/include/llvm/ProfileData/InstrProfCorrelator.h | 2 +-
llvm/lib/ProfileData/InstrProfCorrelator.cpp | 4 ++--
5 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index dad3c9a145b5049..69692c28b16cba1 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -56,6 +56,7 @@
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/SubtargetFeature.h"
#include "llvm/TargetParser/Triple.h"
+#include "llvm/Transforms/HipStdPar/HipStdPar.h"
#include "llvm/Transforms/IPO/EmbedBitcodePass.h"
#include "llvm/Transforms/IPO/LowerTypeTests.h"
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
@@ -79,7 +80,6 @@
#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Scalar/JumpThreading.h"
-#include "llvm/Transforms/HipStdPar/HipStdPar.h"
#include "llvm/Transforms/Utils/Debugify.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
diff --git a/compiler-rt/test/profile/instrprof-binary-correlate.c b/compiler-rt/test/profile/instrprof-binary-correlate.c
index bc05dbd99b82516..d921c4c5dcb0191 100644
--- a/compiler-rt/test/profile/instrprof-binary-correlate.c
+++ b/compiler-rt/test/profile/instrprof-binary-correlate.c
@@ -7,14 +7,14 @@
// With -profile-correlate=binary flag
// RUN: %clang -o %t-1.exe -fprofile-instr-generate -fcoverage-mapping -mllvm -profile-correlate=binary -fuse-ld=lld %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t-1.exe
-// RUN: llvm-profdata merge -o %t-1.profdata --binary-file=%t-1.exe %t-1.profraw
-// RUN: diff %t.normal.profdata %t-1.profdata
+// RUN: llvm-profdata merge -o %t-1.profdata --binary-file=%t-1.exe %t-1.profraw
+// RUN: diff %t.normal.profdata %t-1.profdata
// Strip above binary and run
// RUN: llvm-strip %t-1.exe -o %t-2.exe
// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t-2.exe
-// RUN: llvm-profdata merge -o %t-2.profdata --binary-file=%t-1.exe %t-2.profraw
-// RUN: diff %t.normal.profdata %t-2.profdata
+// RUN: llvm-profdata merge -o %t-2.profdata --binary-file=%t-1.exe %t-2.profraw
+// RUN: diff %t.normal.profdata %t-2.profdata
// Online merging.
// RUN: env LLVM_PROFILE_FILE=%t-3.profraw %run %t.normal
diff --git a/llvm/docs/CommandGuide/llvm-profdata.rst b/llvm/docs/CommandGuide/llvm-profdata.rst
index f81c80601e98a11..89b331c5bbd9c6b 100644
--- a/llvm/docs/CommandGuide/llvm-profdata.rst
+++ b/llvm/docs/CommandGuide/llvm-profdata.rst
@@ -199,9 +199,10 @@ OPTIONS
option to correlate the raw profile.
.. option:: --binary-file=<path>
-Specify the executable that contains profile data and profile name sections for
-the raw profile. When ``-profile-correlate=binary`` was used for
-instrumentation, use this option to correlate the raw profile.
+
+ Specify the executable that contains profile data and profile name sections for
+ the raw profile. When ``-profile-correlate=binary`` was used for
+ instrumentation, use this option to correlate the raw profile.
.. option:: --temporal-profile-trace-reservoir-size
diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
index 661570eaee11300..ba82702354c1898 100644
--- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
+++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
@@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-// This file defines InstrProfCorrelator used to generate PGO/coverage profiles
+// This file defines InstrProfCorrelator used to generate PGO/coverage profiles
// from raw profile data and debug info/binary file.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index 168c2803145f1ff..6796f2828d01726 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -206,8 +206,8 @@ InstrProfCorrelatorImpl<IntPtrT>::get(
if (Obj.isELF() || Obj.isCOFF())
return std::make_unique<BinaryInstrProfCorrelator<IntPtrT>>(std::move(Ctx));
return make_error<InstrProfError>(
- instrprof_error::unable_to_correlate_profile,
- "unsupported binary format (only ELF and COFF are supported)");
+ instrprof_error::unable_to_correlate_profile,
+ "unsupported binary format (only ELF and COFF are supported)");
}
template <class IntPtrT>
>From 384ee6c1197683ff087bf04f8a5d1e79b27ecfc4 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Wed, 18 Oct 2023 17:05:44 -0400
Subject: [PATCH 5/5] add llvm-cov and IR test
---
.../test/profile/instrprof-binary-correlate.c | 17 +++++++++++++++++
.../InstrProfiling/binary-correlate.ll | 11 +++++++++++
2 files changed, 28 insertions(+)
create mode 100644 llvm/test/Instrumentation/InstrProfiling/binary-correlate.ll
diff --git a/compiler-rt/test/profile/instrprof-binary-correlate.c b/compiler-rt/test/profile/instrprof-binary-correlate.c
index d921c4c5dcb0191..8009e572652689a 100644
--- a/compiler-rt/test/profile/instrprof-binary-correlate.c
+++ b/compiler-rt/test/profile/instrprof-binary-correlate.c
@@ -3,27 +3,44 @@
// RUN: %clang -o %t.normal -fprofile-instr-generate -fcoverage-mapping -fuse-ld=lld %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
+// RUN: llvm-cov report --instr-profile=%t.normal.profdata %t.normal > %t.normal.report
+// RUN: llvm-cov show --instr-profile=%t.normal.profdata %t.normal > %t.normal.show
// With -profile-correlate=binary flag
// RUN: %clang -o %t-1.exe -fprofile-instr-generate -fcoverage-mapping -mllvm -profile-correlate=binary -fuse-ld=lld %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t-1.exe
// RUN: llvm-profdata merge -o %t-1.profdata --binary-file=%t-1.exe %t-1.profraw
+// RUN: llvm-cov report --instr-profile=%t-1.profdata %t-1.exe > %t-1.report
+// RUN: llvm-cov show --instr-profile=%t-1.profdata %t-1.exe > %t-1.show
// RUN: diff %t.normal.profdata %t-1.profdata
+// RUN: diff %t.normal.report %t-1.report
+// RUN: diff %t.normal.show %t-1.show
// Strip above binary and run
// RUN: llvm-strip %t-1.exe -o %t-2.exe
// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t-2.exe
// RUN: llvm-profdata merge -o %t-2.profdata --binary-file=%t-1.exe %t-2.profraw
+// RUN: llvm-cov report --instr-profile=%t-2.profdata %t-1.exe > %t-2.report
+// RUN: llvm-cov show --instr-profile=%t-2.profdata %t-1.exe > %t-2.show
// RUN: diff %t.normal.profdata %t-2.profdata
+// RUN: diff %t.normal.report %t-2.report
+// RUN: diff %t.normal.show %t-2.show
// Online merging.
// RUN: env LLVM_PROFILE_FILE=%t-3.profraw %run %t.normal
// RUN: env LLVM_PROFILE_FILE=%t-4.profraw %run %t.normal
// RUN: llvm-profdata merge -o %t.normal.merged.profdata %t-3.profraw %t-4.profraw
+// RUN: llvm-cov report --instr-profile=%t.normal.merged.profdata %t.normal > %t.normal.merged.report
+// RUN: llvm-cov show --instr-profile=%t.normal.merged.profdata %t.normal > %t.normal.merged.show
+
// RUN: rm -rf %t.profdir && mkdir %t.profdir
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m-4.profraw %run %t-2.exe
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m-4.profraw %run %t-2.exe
// RUN: llvm-profdata merge -o %t-4.profdata --binary-file=%t-1.exe %t.profdir
+// RUN: llvm-cov report --instr-profile=%t-4.profdata %t-1.exe > %t-4.report
+// RUN: llvm-cov show --instr-profile=%t-4.profdata %t-1.exe > %t-4.show
// RUN: diff %t.normal.merged.profdata %t-4.profdata
+// RUN: diff %t.normal.merged.report %t-4.report
+// RUN: diff %t.normal.merged.show %t-4.show
// TODO: After adding support for binary ID, test binaries with different binary IDs.
diff --git a/llvm/test/Instrumentation/InstrProfiling/binary-correlate.ll b/llvm/test/Instrumentation/InstrProfiling/binary-correlate.ll
new file mode 100644
index 000000000000000..2206ce17d881dfb
--- /dev/null
+++ b/llvm/test/Instrumentation/InstrProfiling/binary-correlate.ll
@@ -0,0 +1,11 @@
+; RUN: opt < %s -passes=instrprof -profile-correlate=binary -S | FileCheck %s
+
+; CHECK: @__profd_foo = private global { i64, i64, i64, ptr, ptr, i32, [2 x i16] } { i64 {{.*}}, i64 {{.*}}, i64 ptrtoint (ptr @__profc_foo to i64)
+
+ at __profn_foo = private constant [3 x i8] c"foo"
+define void @_Z3foov() {
+ call void @llvm.instrprof.increment(ptr @__profn_foo, i64 12345678, i32 2, i32 0)
+ ret void
+}
+
+declare void @llvm.instrprof.increment(ptr, i64, i32, i32)
More information about the flang-commits
mailing list