Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Profile] Add binary profile correlation for code coverage. #69493

Merged
merged 14 commits into from
Dec 14, 2023
Merged
13 changes: 9 additions & 4 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -55,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"
Expand All @@ -78,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"
Expand All @@ -98,13 +99,17 @@ 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;
ZequanWu marked this conversation as resolved.
Show resolved Hide resolved
} // namespace llvm

namespace {

// Default filename used for profile generation.
std::string getDefaultProfileGenName() {
return DebugInfoCorrelate ? "default_%m.proflite" : "default_%m.profraw";
return DebugInfoCorrelate || ProfileCorrelate != InstrProfCorrelator::NONE
? "default_%m.proflite"
: "default_%m.profraw";
}

class EmitAssemblyHelper {
Expand Down Expand Up @@ -197,7 +202,7 @@ class EmitAssemblyHelper {
void EmitAssembly(BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS);
};
}
} // namespace

static SanitizerCoverageOptions
getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) {
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down Expand Up @@ -1829,6 +1833,22 @@ void CoverageMappingModuleGen::emit() {
llvm::GlobalValue::InternalLinkage, NamesArrVal,
llvm::getCoverageUnusedNamesVarName());
}
const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some comments for this segment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already reverted changes in Clang because VARIANT_MASK_BIN_CORRELATE flag is no longer necessary: #69493 (comment)

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might overwrite other modifier bits set else where.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

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()) {
ZequanWu marked this conversation as resolved.
Show resolved Hide resolved
VersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
VersionVariable->setComdat(CGM.getModule().getOrInsertComdat(VarName));
}
}

unsigned CoverageMappingModuleGen::getFileID(FileEntryRef File) {
Expand Down
9 changes: 9 additions & 0 deletions clang/test/CodeGen/coverage-profile-raw-version.c
Original file line number Diff line number Diff line change
@@ -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
ZequanWu marked this conversation as resolved.
Show resolved Hide resolved

// CHECK: @__llvm_profile_raw_version = {{.*}} i64 9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it 9?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

// BIN-CORRELATE: @__llvm_profile_raw_version = {{.*}} i64 4294967305

int main() {
return 0;
}
2 changes: 2 additions & 0 deletions compiler-rt/include/profile/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,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.
Expand All @@ -674,6 +675,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)
Expand Down
3 changes: 2 additions & 1 deletion compiler-rt/lib/profile/InstrProfiling.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,6 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
}

COMPILER_RT_VISIBILITY int __llvm_profile_has_correlation() {
return (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) != 0ULL;
return (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) != 0ULL ||
(__llvm_profile_get_version() & VARIANT_MASK_BIN_CORRELATE) != 0ULL;
}
3 changes: 3 additions & 0 deletions compiler-rt/lib/profile/InstrProfiling.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,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);
ZequanWu marked this conversation as resolved.
Show resolved Hide resolved

/*! \brief Get the size in bytes of a single counter entry. */
size_t __llvm_profile_counter_entry_size(void);

Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@

#if defined(_MSC_VER)
/* Merge read-write sections into .data. */
#pragma comment(linker, "/MERGE:.lprfc=.data")
#pragma comment(linker, "/MERGE:.lprfb=.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
* after the fact.
* Do *NOT* merge .lprfc and lprfd into .rdata. When binary profile correlation
* is enabled, llvm-profdata must be able to find after the fact.
*/

/* Allocate read-only section bounds. */
Expand Down
5 changes: 3 additions & 2 deletions compiler-rt/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// 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 data metadata in correlated file

Expand Down
46 changes: 46 additions & 0 deletions compiler-rt/test/profile/instrprof-binary-correlate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// REQUIRES: linux || windows
ZequanWu marked this conversation as resolved.
Show resolved Hide resolved
// 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
// 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
ZequanWu marked this conversation as resolved.
Show resolved Hide resolved
// 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.
14 changes: 10 additions & 4 deletions llvm/docs/CommandGuide/llvm-profdata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,14 @@ 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
ZequanWu marked this conversation as resolved.
Show resolved Hide resolved
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

Expand Down Expand Up @@ -346,8 +352,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

Expand Down
6 changes: 3 additions & 3 deletions llvm/include/llvm/ProfileData/InstrProf.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,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,
Expand Down Expand Up @@ -468,7 +468,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.
Expand Down
Loading