[compiler-rt] 668803f - Reland "[MC/DC][Coverage] Enable profile correlation for MC/DC" (#204675)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 08:55:22 PDT 2026
Author: Roman Beliaev
Date: 2026-06-30T08:55:16-07:00
New Revision: 668803fa73bdf2f8d095162a1f81c000d18458c9
URL: https://github.com/llvm/llvm-project/commit/668803fa73bdf2f8d095162a1f81c000d18458c9
DIFF: https://github.com/llvm/llvm-project/commit/668803fa73bdf2f8d095162a1f81c000d18458c9.diff
LOG: Reland "[MC/DC][Coverage] Enable profile correlation for MC/DC" (#204675)
Added:
compiler-rt/test/profile/Darwin/instrprof-mcdc-correlation.c
compiler-rt/test/profile/Inputs/instrprof-mcdc-correlation.cpp
compiler-rt/test/profile/Linux/instrprof-mcdc-correlation.c
llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-bitmap.ll
Modified:
compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
compiler-rt/lib/profile/InstrProfilingWriter.c
compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c
compiler-rt/test/profile/instrprof-binary-correlate.c
llvm/include/llvm/ProfileData/InstrProfCorrelator.h
llvm/include/llvm/ProfileData/InstrProfReader.h
llvm/lib/ProfileData/InstrProfCorrelator.cpp
llvm/lib/ProfileData/InstrProfReader.cpp
llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
index 128d73c1d54a1..a0582d6645b7f 100644
--- a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
@@ -15,14 +15,13 @@
#if defined(_MSC_VER)
/* Merge read-write sections into .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 .rdata. When binary profile correlation is enabled,
- * llvm-cov must be able to find after the fact.
+ * Do *NOT* merge .lprfb .lprfc .rdata. When binary profile correlation is
+ * enabled, llvm-cov must be able to find after the fact.
*/
/* Allocate read-only section bounds. */
diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c
index 2c459acd39af0..3021e3b3cfc31 100644
--- a/compiler-rt/lib/profile/InstrProfilingWriter.c
+++ b/compiler-rt/lib/profile/InstrProfilingWriter.c
@@ -343,6 +343,7 @@ COMPILER_RT_VISIBILITY int lprofWriteDataImpl(
/* The data and names sections are omitted in lightweight mode. */
if (NumData == 0 && NamesSize == 0) {
Header.CountersDelta = 0;
+ Header.BitmapDelta = 0;
Header.NamesDelta = 0;
Header.UniformCountersDelta = 0;
}
diff --git a/compiler-rt/test/profile/Darwin/instrprof-mcdc-correlation.c b/compiler-rt/test/profile/Darwin/instrprof-mcdc-correlation.c
new file mode 100644
index 0000000000000..c06e247ea162f
--- /dev/null
+++ b/compiler-rt/test/profile/Darwin/instrprof-mcdc-correlation.c
@@ -0,0 +1,20 @@
+// Default
+// RUN: %clang -o %t.normal -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc %S/../Inputs/instrprof-mcdc-correlation.cpp
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
+// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
+// RUN: llvm-profdata show --all-functions --counts --text %t.normal.profdata > %t.normal.profdata.show
+
+// With -profile-correlate=binary flag
+// RUN: %clang -o %t-1.exe -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc -mllvm -profile-correlate=binary %S/../Inputs/instrprof-mcdc-correlation.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-profdata show --all-functions --counts --text %t-1.profdata > %t-1.profdata.show
+
+// With -profile-correlate=debug-info flag
+// RUN: %clang -o %t-2.exe -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc -mllvm -profile-correlate=debug-info -g %S/../Inputs/instrprof-mcdc-correlation.cpp
+// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t-2.exe
+// RUN: llvm-profdata merge -o %t-2.profdata --debug-info=%t-2.exe.dSYM %t-2.profraw
+// RUN: llvm-profdata show --all-functions --counts --text %t-2.profdata > %t-2.profdata.show
+
+// RUN:
diff %t.normal.profdata.show %t-1.profdata.show
+// RUN:
diff %t.normal.profdata.show %t-2.profdata.show
diff --git a/compiler-rt/test/profile/Inputs/instrprof-mcdc-correlation.cpp b/compiler-rt/test/profile/Inputs/instrprof-mcdc-correlation.cpp
new file mode 100644
index 0000000000000..ba6d281aca45c
--- /dev/null
+++ b/compiler-rt/test/profile/Inputs/instrprof-mcdc-correlation.cpp
@@ -0,0 +1,14 @@
+void test(int a, int b, int c, int d) {
+ if ((a && b) || (c && d))
+ ;
+ if (b && c)
+ ;
+}
+
+int main() {
+ test(1, 1, 1, 1);
+ test(1, 1, 0, 1);
+ test(0, 0, 1, 0);
+ test(0, 0, 1, 1);
+ return 0;
+}
diff --git a/compiler-rt/test/profile/Linux/instrprof-mcdc-correlation.c b/compiler-rt/test/profile/Linux/instrprof-mcdc-correlation.c
new file mode 100644
index 0000000000000..1dba18487d98c
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/instrprof-mcdc-correlation.c
@@ -0,0 +1,20 @@
+// Default
+// RUN: %clang -o %t.normal -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc %S/../Inputs/instrprof-mcdc-correlation.cpp
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
+// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
+// RUN: llvm-profdata show --all-functions --counts --text %t.normal.profdata > %t.normal.profdata.show
+
+// With -profile-correlate=binary flag
+// RUN: %clang -o %t-1.exe -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc -mllvm -profile-correlate=binary %S/../Inputs/instrprof-mcdc-correlation.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-profdata show --all-functions --counts --text %t-1.profdata > %t-1.profdata.show
+
+// With -profile-correlate=debug-info flag
+// RUN: %clang -o %t-2.exe -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc -mllvm -profile-correlate=debug-info -g %S/../Inputs/instrprof-mcdc-correlation.cpp
+// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t-2.exe
+// RUN: llvm-profdata merge -o %t-2.profdata --debug-info=%t-2.exe %t-2.profraw
+// RUN: llvm-profdata show --all-functions --counts --text %t-2.profdata > %t-2.profdata.show
+
+// RUN:
diff %t.normal.profdata.show %t-1.profdata.show
+// RUN:
diff %t.normal.profdata.show %t-2.profdata.show
diff --git a/compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c b/compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c
index 09fb39cc3d076..2cf12faf3e498 100644
--- a/compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c
+++ b/compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c
@@ -2,13 +2,13 @@
// REQUIRES: curl
// Default instrumented build with no profile correlation.
-// RUN: %clang_profgen -o %t.default.exe -Wl,--build-id=0x12345678 -fprofile-instr-generate -fcoverage-mapping %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_profgen -o %t.default.exe -Wl,--build-id=0x12345678 -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.default.profraw %run %t.default.exe
// RUN: llvm-profdata merge -o %t.default.profdata %t.default.profraw
// RUN: llvm-profdata show --all-functions --counts %t.default.profdata > %t.default.profdata.show
// Build with profile binary correlation.
-// RUN: %clang_profgen -o %t.correlate.exe -Wl,--build-id=0x12345678 -fprofile-instr-generate -fcoverage-mapping -mllvm -profile-correlate=binary %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang_profgen -o %t.correlate.exe -Wl,--build-id=0x12345678 -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc -mllvm -profile-correlate=binary %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
// Strip above binary and run
// RUN: llvm-strip %t.correlate.exe -o %t.stripped.exe
// RUN: env LLVM_PROFILE_FILE=%t.correlate.profraw %run %t.stripped.exe
diff --git a/compiler-rt/test/profile/instrprof-binary-correlate.c b/compiler-rt/test/profile/instrprof-binary-correlate.c
index 69648513943a6..abc9bc36339fc 100644
--- a/compiler-rt/test/profile/instrprof-binary-correlate.c
+++ b/compiler-rt/test/profile/instrprof-binary-correlate.c
@@ -1,13 +1,13 @@
// REQUIRES: linux || windows || darwin
// Default
-// RUN: %clang -o %t.normal -fprofile-instr-generate -fcoverage-mapping %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang -o %t.normal -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc %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 %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: %clang -o %t-1.exe -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc -mllvm -profile-correlate=binary %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
diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
index 9c7e4732768b2..fb2d64a977ffd 100644
--- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
+++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
@@ -14,6 +14,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Object/BuildID.h"
@@ -70,6 +71,7 @@ class InstrProfCorrelator {
LLVM_ABI static const char *FunctionNameAttributeName;
LLVM_ABI static const char *CFGHashAttributeName;
LLVM_ABI static const char *NumCountersAttributeName;
+ LLVM_ABI static const char *NumBitmapBitsAttributeName;
enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit };
InstrProfCorrelatorKind getKind() const { return Kind; }
@@ -84,6 +86,9 @@ class InstrProfCorrelator {
/// The address range of the __llvm_prf_cnts section.
uint64_t CountersSectionStart;
uint64_t CountersSectionEnd;
+ /// The address range of the __llvm_prf_bits section.
+ uint64_t BitmapSectionStart;
+ uint64_t BitmapSectionEnd;
/// The pointer points to start/end of profile data/name sections if
/// FileKind is Binary.
const char *DataStart;
@@ -110,7 +115,9 @@ class InstrProfCorrelator {
std::optional<std::string> LinkageName;
yaml::Hex64 CFGHash;
yaml::Hex64 CounterOffset;
+ yaml::Hex64 BitmapOffset;
uint32_t NumCounters;
+ uint32_t NumBitmapBytes;
std::optional<std::string> FilePath;
std::optional<int> LineNumber;
};
@@ -164,8 +171,9 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
Error dumpYaml(int MaxWarnings, raw_ostream &OS) override;
void addDataProbe(uint64_t FunctionName, uint64_t CFGHash,
- IntPtrT CounterOffset, IntPtrT FunctionPtr,
- uint32_t NumCounters);
+ IntPtrT CounterOffset, IntPtrT BitmapOffset,
+ IntPtrT FunctionPtr, uint32_t NumCounters,
+ uint32_t NumBitmapBytes);
// Byte-swap the value if necessary.
template <class T> T maybeSwap(T Value) const {
@@ -177,6 +185,7 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
std::unique_ptr<InstrProfCorrelator::Context> Ctx)
: InstrProfCorrelator(Kind, std::move(Ctx)){};
llvm::DenseSet<IntPtrT> CounterOffsets;
+ llvm::DenseSet<IntPtrT> BitmapOffsets;
};
/// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes
@@ -196,8 +205,16 @@ class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
std::optional<uint64_t> getLocation(const DWARFDie &Die) const;
/// Returns true if the provided DIE symbolizes an instrumentation probe
- /// symbol.
- static bool isDIEOfProbe(const DWARFDie &Die);
+ /// symbol of the necessary type.
+ static bool isDIEOfProbe(const DWARFDie &Die, StringRef Prefix);
+
+ std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
+ addCountersToDataProbe(const DWARFDie &Die, const bool UnlimitedWarnings,
+ int &NumSuppressedWarnings);
+
+ std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
+ addBitmapToDataProbe(const DWARFDie &Die, const bool UnlimitedWarnings,
+ int &NumSuppressedWarnings);
/// Iterate over DWARF DIEs to find those that symbolize instrumentation
/// probes and construct the ProfileData vector and Names string.
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index 0b94886f44e28..51b97e9f88ee3 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -477,7 +477,8 @@ class RawInstrProfReader : public InstrProfReader {
bool atEnd() const { return Data == DataEnd; }
void advanceData() {
- // `CountersDelta` is a constant zero when using debug info correlation.
+ // `CountersDelta` and `BitmapDelta` are constant zero when using debug info
+ // correlation.
if (!Correlator && !BIDFetcherCorrelator) {
// The initial CountersDelta is the in-memory address
diff erence between
// the data and counts sections:
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index c732382eb399a..1f41a6e141149 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -51,6 +51,7 @@ getInstrProfSection(const object::ObjectFile &Obj, InstrProfSectKind IPSK) {
const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name";
const char *InstrProfCorrelator::CFGHashAttributeName = "CFG Hash";
const char *InstrProfCorrelator::NumCountersAttributeName = "Num Counters";
+const char *InstrProfCorrelator::NumBitmapBitsAttributeName = "Num BitmapBits";
llvm::Expected<std::unique_ptr<InstrProfCorrelator::Context>>
InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
@@ -101,10 +102,24 @@ InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
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 (ObjFormat == Triple::COFF)
+
+ auto BitmapSection = getInstrProfSection(Obj, IPSK_bitmap);
+ if (auto E = BitmapSection.takeError()) {
+ // It is not an error if NumBitmapBytes of each function is zero.
+ consumeError(std::move(E));
+ C->BitmapSectionStart = 0;
+ C->BitmapSectionEnd = 0;
+ } else {
+ C->BitmapSectionStart = BitmapSection->getAddress();
+ C->BitmapSectionEnd = C->BitmapSectionStart + BitmapSection->getSize();
+ }
+ // In COFF object file, there's a null byte at the beginning of both the
+ // counter and bitmap sections which doesn't exist in raw profile.
+ if (ObjFormat == Triple::COFF) {
++C->CountersSectionStart;
+ if (C->BitmapSectionStart)
+ ++C->BitmapSectionStart;
+ }
C->ShouldSwapBytes = Obj.isLittleEndian() != sys::IsLittleEndianHost;
return Expected<std::unique_ptr<Context>>(std::move(C));
@@ -255,6 +270,7 @@ Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData(int MaxWarnings) {
"could not find any profile data metadata in correlated file");
Error Result = correlateProfileNameImpl();
this->CounterOffsets.clear();
+ this->BitmapOffsets.clear();
this->NamesVec.clear();
return Result;
}
@@ -273,6 +289,8 @@ template <> struct yaml::MappingTraits<InstrProfCorrelator::Probe> {
io.mapRequired("CFG Hash", P.CFGHash);
io.mapRequired("Counter Offset", P.CounterOffset);
io.mapRequired("Num Counters", P.NumCounters);
+ io.mapRequired("Bitmap Offset", P.BitmapOffset);
+ io.mapRequired("Num BitmapBytes", P.NumBitmapBytes);
io.mapOptional("File", P.FilePath);
io.mapOptional("Line", P.LineNumber);
}
@@ -297,13 +315,15 @@ Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(int MaxWarnings,
}
template <class IntPtrT>
-void InstrProfCorrelatorImpl<IntPtrT>::addDataProbe(uint64_t NameRef,
- uint64_t CFGHash,
- IntPtrT CounterOffset,
- IntPtrT FunctionPtr,
- uint32_t NumCounters) {
+void InstrProfCorrelatorImpl<IntPtrT>::addDataProbe(
+ uint64_t NameRef, uint64_t CFGHash, IntPtrT CounterOffset,
+ IntPtrT BitmapOffset, IntPtrT FunctionPtr, uint32_t NumCounters,
+ uint32_t NumBitmapBytes) {
// Check if a probe was already added for this counter offset.
- if (!CounterOffsets.insert(CounterOffset).second)
+ if (NumCounters && !CounterOffsets.insert(CounterOffset).second)
+ return;
+ // Check if a probe was already added for this bitmap offset.
+ if (NumBitmapBytes && !BitmapOffsets.insert(BitmapOffset).second)
return;
Data.push_back({
maybeSwap<uint64_t>(NameRef),
@@ -312,16 +332,14 @@ void InstrProfCorrelatorImpl<IntPtrT>::addDataProbe(uint64_t NameRef,
// of the counter.
maybeSwap<IntPtrT>(CounterOffset),
/*UniformCounterPtr=*/maybeSwap<IntPtrT>(0),
- // TODO: MC/DC is not yet supported.
- /*BitmapOffset=*/maybeSwap<IntPtrT>(0),
+ maybeSwap<IntPtrT>(BitmapOffset),
maybeSwap<IntPtrT>(FunctionPtr),
// TODO: Value profiling is not yet supported.
/*ValuesPtr=*/maybeSwap<IntPtrT>(0),
maybeSwap<uint32_t>(NumCounters),
/*NumValueSites=*/{maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)},
/*OffloadDeviceWaveSize=*/maybeSwap<uint16_t>(0),
- // TODO: MC/DC is not yet supported.
- /*NumBitmapBytes=*/maybeSwap<uint32_t>(0),
+ maybeSwap<uint32_t>(NumBitmapBytes),
});
}
@@ -352,7 +370,8 @@ DwarfInstrProfCorrelator<IntPtrT>::getLocation(const DWARFDie &Die) const {
}
template <class IntPtrT>
-bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die) {
+bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die,
+ StringRef Prefix) {
const auto &ParentDie = Die.getParent();
if (!Die.isValid() || !ParentDie.isValid() || Die.isNULL())
return false;
@@ -363,101 +382,204 @@ bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die) {
if (!Die.hasChildren())
return false;
if (const char *Name = Die.getName(DINameKind::ShortName))
- return StringRef(Name).starts_with(getInstrProfCountersVarPrefix());
+ return StringRef(Name).starts_with(Prefix);
return false;
}
+template <class IntPtrT>
+std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
+DwarfInstrProfCorrelator<IntPtrT>::addCountersToDataProbe(
+ const DWARFDie &Die, const bool UnlimitedWarnings,
+ int &NumSuppressedWarnings) {
+ std::optional<const char *> FunctionName;
+ std::optional<uint64_t> CFGHash;
+ std::optional<uint64_t> CounterPtr = getLocation(Die);
+ auto FnDie = Die.getParent();
+ auto FunctionPtr = dwarf::toAddress(FnDie.find(dwarf::DW_AT_low_pc));
+ std::optional<uint64_t> NumCounters;
+ for (const DWARFDie &Child : Die.children()) {
+ if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
+ continue;
+ auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
+ auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
+ if (!AnnotationFormName || !AnnotationFormValue)
+ continue;
+ auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
+ if (auto Err = AnnotationNameOrErr.takeError()) {
+ consumeError(std::move(Err));
+ continue;
+ }
+ StringRef AnnotationName = *AnnotationNameOrErr;
+ if (AnnotationName == InstrProfCorrelator::FunctionNameAttributeName) {
+ if (auto EC = AnnotationFormValue->getAsCString().moveInto(FunctionName))
+ consumeError(std::move(EC));
+ } else if (AnnotationName == InstrProfCorrelator::CFGHashAttributeName) {
+ CFGHash = AnnotationFormValue->getAsUnsignedConstant();
+ } else if (AnnotationName ==
+ InstrProfCorrelator::NumCountersAttributeName) {
+ NumCounters = AnnotationFormValue->getAsUnsignedConstant();
+ }
+ }
+ // If there is no function and no counter, assume it was dead-stripped
+ if (!FunctionPtr && !CounterPtr)
+ return std::nullopt;
+ if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
+ if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ WithColor::warning() << "Incomplete DIE for function " << FunctionName
+ << ": CFGHash=" << CFGHash
+ << " CounterPtr=" << CounterPtr
+ << " NumCounters=" << NumCounters << "\n";
+ LLVM_DEBUG(Die.dump(dbgs()));
+ }
+ return std::nullopt;
+ }
+ 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 %s: Actual=0x%x "
+ "Expected=[0x%x, 0x%x)\n",
+ *FunctionName, *CounterPtr, CountersStart, CountersEnd);
+ LLVM_DEBUG(Die.dump(dbgs()));
+ }
+ return std::nullopt;
+ }
+ if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) {
+ WithColor::warning() << format("Could not find address of function %s\n",
+ *FunctionName);
+ LLVM_DEBUG(Die.dump(dbgs()));
+ }
+ // In debug info correlation mode, the CounterPtr is an absolute address
+ // of the counter, but it's expected to be relative later when iterating
+ // Data.
+ IntPtrT CounterOffset = *CounterPtr - CountersStart;
+ InstrProfCorrelator::Probe P = {};
+ P.FunctionName = *FunctionName;
+ if (const char *Name = FnDie.getName(DINameKind::LinkageName))
+ P.LinkageName = Name;
+ P.CFGHash = *CFGHash;
+ P.CounterOffset = CounterOffset;
+ P.NumCounters = *NumCounters;
+ auto FilePath = FnDie.getDeclFile(
+ DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
+ if (!FilePath.empty())
+ P.FilePath = FilePath;
+ if (auto LineNumber = FnDie.getDeclLine())
+ P.LineNumber = LineNumber;
+
+ return std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>(
+ {P, FunctionPtr.value_or(0)});
+}
+
+template <class IntPtrT>
+std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
+DwarfInstrProfCorrelator<IntPtrT>::addBitmapToDataProbe(
+ const DWARFDie &Die, const bool UnlimitedWarnings,
+ int &NumSuppressedWarnings) {
+ std::optional<const char *> FunctionName;
+ std::optional<uint64_t> BitmapPtr = getLocation(Die);
+ uint64_t NumBitmapBytes;
+ for (const DWARFDie &Child : Die.children()) {
+ if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
+ continue;
+ auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
+ auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
+ if (!AnnotationFormName || !AnnotationFormValue)
+ continue;
+ auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
+ if (auto Err = AnnotationNameOrErr.takeError()) {
+ consumeError(std::move(Err));
+ continue;
+ }
+ StringRef AnnotationName = *AnnotationNameOrErr;
+ if (AnnotationName == InstrProfCorrelator::FunctionNameAttributeName) {
+ if (auto EC = AnnotationFormValue->getAsCString().moveInto(FunctionName))
+ consumeError(std::move(EC));
+ } else if (AnnotationName ==
+ InstrProfCorrelator::NumBitmapBitsAttributeName) {
+ std::optional<uint64_t> NumBitmapBits =
+ AnnotationFormValue->getAsUnsignedConstant();
+ NumBitmapBytes = alignTo(*NumBitmapBits, CHAR_BIT) / CHAR_BIT;
+ }
+ }
+ if (!FunctionName || !BitmapPtr || !NumBitmapBytes) {
+ if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ WithColor::warning() << "Incomplete DIE for function " << FunctionName
+ << " BitmapPtr=" << BitmapPtr
+ << " NumBitmapBytes=" << NumBitmapBytes << "\n";
+ LLVM_DEBUG(Die.dump(dbgs()));
+ }
+ return std::nullopt;
+ }
+ uint64_t BitmapStart = this->Ctx->BitmapSectionStart;
+ uint64_t BitmapEnd = this->Ctx->BitmapSectionEnd;
+ if (!BitmapStart && !BitmapEnd && NumBitmapBytes) {
+ auto E = make_error<InstrProfError>(
+ instrprof_error::unable_to_correlate_profile,
+ "could not find profile bitmap section in correlated file");
+ return std::nullopt;
+ }
+ if (*BitmapPtr < BitmapStart || (*BitmapPtr >= BitmapEnd && NumBitmapBytes)) {
+ if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ WithColor::warning() << format(
+ "BitmapPtr out of range for function %s: Actual=0x%x "
+ "Expected=[0x%x, 0x%x)\n",
+ *FunctionName, *BitmapPtr, BitmapStart, BitmapEnd);
+ LLVM_DEBUG(Die.dump(dbgs()));
+ }
+ return std::nullopt;
+ }
+ // In debug info correlation mode, the BitmapPtr is an absolute address of
+ // the bitmap, but it's expected to be relative later when iterating Data.
+ IntPtrT BitmapOffset = *BitmapPtr - BitmapStart;
+ InstrProfCorrelator::Probe P = {};
+ P.FunctionName = *FunctionName;
+ P.BitmapOffset = BitmapOffset;
+ P.NumBitmapBytes = NumBitmapBytes;
+
+ return std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>({P, 0});
+}
+
template <class IntPtrT>
void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
int MaxWarnings, InstrProfCorrelator::CorrelationData *Data) {
+ // Map from FunctionName string to (Probe, FunctionPtr) pair.
+ // We use it to collect data from all functions Counter and Bitmap DIEs.
+ MapVector<std::string, std::pair<InstrProfCorrelator::Probe, IntPtrT>,
+ StringMap<unsigned>>
+ Probes;
bool UnlimitedWarnings = (MaxWarnings == 0);
// -N suppressed warnings means we can emit up to N (unsuppressed) warnings
int NumSuppressedWarnings = -MaxWarnings;
+
auto MaybeAddProbe = [&](DWARFDie Die) {
- if (!isDIEOfProbe(Die))
+ std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>> ProbeData;
+ if (isDIEOfProbe(Die, getInstrProfCountersVarPrefix()))
+ ProbeData =
+ addCountersToDataProbe(Die, UnlimitedWarnings, NumSuppressedWarnings);
+ else if (isDIEOfProbe(Die, getInstrProfBitmapVarPrefix()))
+ ProbeData =
+ addBitmapToDataProbe(Die, UnlimitedWarnings, NumSuppressedWarnings);
+ if (!ProbeData)
return;
- std::optional<const char *> FunctionName;
- std::optional<uint64_t> CFGHash;
- std::optional<uint64_t> CounterPtr = getLocation(Die);
- auto FnDie = Die.getParent();
- auto FunctionPtr = dwarf::toAddress(FnDie.find(dwarf::DW_AT_low_pc));
- std::optional<uint64_t> NumCounters;
- for (const DWARFDie &Child : Die.children()) {
- if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
- continue;
- auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
- auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
- if (!AnnotationFormName || !AnnotationFormValue)
- continue;
- auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
- if (auto Err = AnnotationNameOrErr.takeError()) {
- consumeError(std::move(Err));
- continue;
+ auto [Probe, FunctionPtr] = *ProbeData;
+
+ auto [It, Inserted] =
+ Probes.try_emplace(Probe.FunctionName, Probe, FunctionPtr);
+ if (!Inserted) {
+ auto &P = It->second.first;
+ if (isDIEOfProbe(Die, getInstrProfCountersVarPrefix())) {
+ P.LinkageName = Probe.LinkageName;
+ P.CFGHash = Probe.CFGHash;
+ P.CounterOffset = Probe.CounterOffset;
+ P.NumCounters = Probe.NumCounters;
+ P.FilePath = Probe.FilePath;
+ P.LineNumber = Probe.LineNumber;
+ } else {
+ P.BitmapOffset = Probe.BitmapOffset;
+ P.NumBitmapBytes = Probe.NumBitmapBytes;
}
- StringRef AnnotationName = *AnnotationNameOrErr;
- if (AnnotationName == InstrProfCorrelator::FunctionNameAttributeName) {
- if (auto EC =
- AnnotationFormValue->getAsCString().moveInto(FunctionName))
- consumeError(std::move(EC));
- } else if (AnnotationName == InstrProfCorrelator::CFGHashAttributeName) {
- CFGHash = AnnotationFormValue->getAsUnsignedConstant();
- } else if (AnnotationName ==
- InstrProfCorrelator::NumCountersAttributeName) {
- NumCounters = AnnotationFormValue->getAsUnsignedConstant();
- }
- }
- // If there is no function and no counter, assume it was dead-stripped
- if (!FunctionPtr && !CounterPtr)
- return;
- if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
- if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
- WithColor::warning()
- << "Incomplete DIE for function " << FunctionName
- << ": CFGHash=" << CFGHash << " CounterPtr=" << CounterPtr
- << " NumCounters=" << NumCounters << "\n";
- LLVM_DEBUG(Die.dump(dbgs()));
- }
- return;
- }
- 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 %s: Actual=0x%x "
- "Expected=[0x%x, 0x%x)\n",
- *FunctionName, *CounterPtr, CountersStart, CountersEnd);
- LLVM_DEBUG(Die.dump(dbgs()));
- }
- return;
- }
- if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) {
- WithColor::warning() << format("Could not find address of function %s\n",
- *FunctionName);
- LLVM_DEBUG(Die.dump(dbgs()));
- }
- // In debug info correlation mode, the CounterPtr is an absolute address of
- // the counter, but it's expected to be relative later when iterating Data.
- IntPtrT CounterOffset = *CounterPtr - CountersStart;
- if (Data) {
- InstrProfCorrelator::Probe P;
- P.FunctionName = *FunctionName;
- if (const char *Name = FnDie.getName(DINameKind::LinkageName))
- P.LinkageName = Name;
- P.CFGHash = *CFGHash;
- P.CounterOffset = CounterOffset;
- P.NumCounters = *NumCounters;
- auto FilePath = FnDie.getDeclFile(
- DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
- if (!FilePath.empty())
- P.FilePath = FilePath;
- if (auto LineNumber = FnDie.getDeclLine())
- P.LineNumber = LineNumber;
- Data->Probes.push_back(P);
- } else {
- this->addDataProbe(IndexedInstrProf::ComputeHash(*FunctionName), *CFGHash,
- CounterOffset, FunctionPtr.value_or(0), *NumCounters);
- this->NamesVec.push_back(*FunctionName);
}
};
for (auto &CU : DICtx->normal_units())
@@ -467,6 +589,18 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
for (const auto &Entry : CU->dies())
MaybeAddProbe(DWARFDie(CU.get(), &Entry));
+ for (const auto &[FunctionName, ProbeData] : Probes) {
+ const auto &[Probe, FunctionPtr] = ProbeData;
+ if (Data)
+ Data->Probes.push_back(Probe);
+ else {
+ this->NamesVec.push_back(FunctionName);
+ uint64_t NameRef = IndexedInstrProf::ComputeHash(FunctionName);
+ this->addDataProbe(NameRef, Probe.CFGHash, Probe.CounterOffset,
+ Probe.BitmapOffset, FunctionPtr, Probe.NumCounters,
+ Probe.NumBitmapBytes);
+ }
+ }
if (!UnlimitedWarnings && NumSuppressedWarnings > 0)
WithColor::warning() << format("Suppressed %d additional warnings\n",
NumSuppressedWarnings);
@@ -500,15 +634,30 @@ void BinaryInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
uint64_t CounterPtr = this->template maybeSwap<IntPtrT>(I->CounterPtr);
uint64_t CountersStart = this->Ctx->CountersSectionStart;
uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
+
+ uint64_t BitmapPtr = this->template maybeSwap<IntPtrT>(I->BitmapPtr);
+ uint64_t BitmapStart = this->Ctx->BitmapSectionStart;
+ uint64_t BitmapEnd = this->Ctx->BitmapSectionEnd;
+ if (!BitmapStart && !BitmapEnd && I->NumBitmapBytes) {
+ auto E = make_error<InstrProfError>(
+ instrprof_error::unable_to_correlate_profile,
+ "could not find profile bitmap section in correlated file");
+ return;
+ }
if (!this->Ctx->MachOFixups.empty()) {
- uint64_t Offset = (uint64_t)&I->CounterPtr - (uint64_t)DataStart;
- auto It = this->Ctx->MachOFixups.find(Offset);
- if (It != this->Ctx->MachOFixups.end()) {
- CounterPtr = It->second;
- } else if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
- WithColor::warning() << format(
- "Mach-O fixup not found for covdata offset 0x%llx\n", Offset);
- }
+ auto GetPtrByOffset = [&](uint64_t Offset, uint64_t &Ptr) {
+ auto It = this->Ctx->MachOFixups.find(Offset);
+ if (It != this->Ctx->MachOFixups.end()) {
+ Ptr = It->second;
+ } else if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ WithColor::warning() << format(
+ "Mach-O fixup not found for covdata offset 0x%llx\n", Offset);
+ }
+ };
+ uint64_t CounterOffset = (uint64_t)&I->CounterPtr - (uint64_t)DataStart;
+ uint64_t BitmapOffset = (uint64_t)&I->BitmapPtr - (uint64_t)DataStart;
+ GetPtrByOffset(CounterOffset, CounterPtr);
+ GetPtrByOffset(BitmapOffset, BitmapPtr);
}
if (CounterPtr < CountersStart || CounterPtr >= CountersEnd) {
if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
@@ -519,11 +668,22 @@ void BinaryInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
(I - DataStart) * sizeof(RawProfData));
}
}
- // In binary correlation mode, the CounterPtr is an absolute address of the
- // counter, but it's expected to be relative later when iterating Data.
+ if (I->NumBitmapBytes &&
+ (BitmapPtr < BitmapStart || BitmapPtr >= BitmapEnd)) {
+ if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ WithColor::warning()
+ << format("BitmapPtr out of range for function: Actual=0x%x "
+ "Expected=[0x%x, 0x%x) at data offset=0x%x\n",
+ BitmapPtr, BitmapStart, BitmapEnd,
+ (I - DataStart) * sizeof(RawProfData));
+ }
+ }
+ // In binary correlation mode, CounterPtr and BitmapPtr are absolute
+ // addresses, but they're expected to be relative later when iterating Data.
IntPtrT CounterOffset = CounterPtr - CountersStart;
- this->addDataProbe(I->NameRef, I->FuncHash, CounterOffset,
- I->FunctionPointer, I->NumCounters);
+ IntPtrT BitmapOffset = BitmapPtr - BitmapStart;
+ this->addDataProbe(I->NameRef, I->FuncHash, CounterOffset, BitmapOffset,
+ I->FunctionPointer, I->NumCounters, I->NumBitmapBytes);
}
}
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index b0bf80c0a7a6e..05770f83ed160 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -669,7 +669,7 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
// These sizes in the raw file are zero because we constructed them in the
// Correlator.
if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 &&
- NamesDelta == 0))
+ BitmapDelta == 0 && NamesDelta == 0))
return error(instrprof_error::unexpected_correlation_info);
Data = Correlator->getDataPointer();
DataEnd = Data + Correlator->getDataSize();
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index 79f0145c64957..73a8182949910 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -1878,6 +1878,39 @@ InstrLowerer::getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc) {
auto *BitmapPtr = setupProfileSection(Inc, IPSK_bitmap);
PD.RegionBitmaps = BitmapPtr;
PD.NumBitmapBytes = Inc->getNumBitmapBytes();
+
+ if (PD.NumBitmapBytes &&
+ ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO) {
+ LLVMContext &Ctx = M.getContext();
+ Function *Fn = Inc->getParent()->getParent();
+ if (auto *SP = Fn->getSubprogram()) {
+ DIBuilder DB(M, true, SP->getUnit());
+ Metadata *FunctionNameAnnotation[] = {
+ MDString::get(Ctx, InstrProfCorrelator::FunctionNameAttributeName),
+ MDString::get(Ctx, getPGOFuncNameVarInitializer(NamePtr)),
+ };
+ Metadata *NumBitmapBitsAnnotation[] = {
+ MDString::get(Ctx, InstrProfCorrelator::NumBitmapBitsAttributeName),
+ ConstantAsMetadata::get(Inc->getNumBitmapBits()),
+ };
+ auto Annotations = DB.getOrCreateArray({
+ MDNode::get(Ctx, FunctionNameAnnotation),
+ MDNode::get(Ctx, NumBitmapBitsAnnotation),
+ });
+ auto *DICounter = DB.createGlobalVariableExpression(
+ SP, BitmapPtr->getName(), /*LinkageName=*/StringRef(), SP->getFile(),
+ /*LineNo=*/0, DB.createUnspecifiedType("Profile Bitmap Type"),
+ BitmapPtr->hasLocalLinkage(), /*IsDefined=*/true, /*Expr=*/nullptr,
+ /*Decl=*/nullptr, /*TemplateParams=*/nullptr, /*AlignInBits=*/0,
+ Annotations);
+ BitmapPtr->addDebugInfo(DICounter);
+ DB.finalize();
+ }
+
+ // Mark the bitmap variable as used so that it isn't optimized out.
+ CompilerUsedVars.push_back(PD.RegionBitmaps);
+ }
+
return PD.RegionBitmaps;
}
diff --git a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-bitmap.ll b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-bitmap.ll
new file mode 100644
index 0000000000000..29bd0037a7e8b
--- /dev/null
+++ b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate-bitmap.ll
@@ -0,0 +1,85 @@
+; 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
+
+; REQUIRES: target={{.*-linux.*}}, object-emission
+
+ at __profn_foo = private constant [3 x i8] c"foo"
+; CHECK: @__profbm_foo =
+; CHECK-SAME: !dbg ![[EXPR:[0-9]+]]
+
+; CHECK: ![[EXPR]] = !DIGlobalVariableExpression(var: ![[GLOBAL:[0-9]+]]
+; CHECK: ![[GLOBAL]] = {{.*}} !DIGlobalVariable(name: "__profbm_foo"
+; CHECK-SAME: scope: ![[SCOPE:[0-9]+]]
+; CHECK-SAME: annotations: ![[ANNOTATIONS:[0-9]+]]
+; CHECK: ![[SCOPE]] = {{.*}} !DISubprogram(name: "foo"
+; CHECK-DAG: ![[ANNOTATIONS]] = !{![[NAME:[0-9]+]], ![[BITMAP_BITS:[0-9]+]]}
+; CHECK-DAG: ![[NAME]] = !{!"Function Name", !"foo"}
+; CHECK: ![[BITMAP_BITS]] = !{!"Num BitmapBits", i32 1}
+
+define void @_Z3foov() !dbg !12 {
+ %mcdc.addr = alloca i32, align 4
+ call void @llvm.instrprof.increment(ptr @__profn_foo, i64 12345678, i32 2, i32 0)
+ call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foo, i64 12345678, i32 1)
+ call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_foo, i64 12345678, i32 0, ptr %mcdc.addr)
+ ret void
+}
+
+declare void @llvm.instrprof.increment(ptr, i64, i32, i32)
+declare void @llvm.instrprof.mcdc.parameters(ptr, i64, i32)
+declare void @llvm.instrprof.mcdc.tvbitmap.update(ptr, i64, i32, ptr)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8, !9, !10}
+!llvm.ident = !{!11}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-info-correlate.cpp", directory: "")
+!2 = !{i32 7, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"branch-target-enforcement", i32 0}
+!6 = !{i32 8, !"sign-return-address", i32 0}
+!7 = !{i32 8, !"sign-return-address-all", i32 0}
+!8 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
+!9 = !{i32 7, !"uwtable", i32 1}
+!10 = !{i32 7, !"frame-pointer", i32 1}
+!11 = !{!"clang version 14.0.0"}
+!12 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !13, file: !13, line: 1, type: !14, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !16)
+!13 = !DIFile(filename: "debug-info-correlate.cpp", directory: "")
+!14 = !DISubroutineType(types: !15)
+!15 = !{null}
+!16 = !{}
+
+; CHECK-DWARF: DW_TAG_compile_unit
+; CHECK-DWARF: DW_TAG_subprogram
+; CHECK-DWARF: DW_AT_name ("foo")
+; CHECK-DWARF: DW_TAG_variable
+; CHECK-DWARF: DW_AT_name ("__profbm_foo")
+; CHECK-DWARF: DW_AT_type ({{.*}} "Profile Bitmap Type")
+; CHECK-DWARF: DW_TAG_LLVM_annotation
+; CHECK-DWARF: DW_AT_name ("Function Name")
+; CHECK-DWARF: DW_AT_const_value ("foo")
+; CHECK-DWARF: DW_TAG_LLVM_annotation
+; CHECK-DWARF: DW_AT_name ("Num BitmapBits")
+; CHECK-DWARF: DW_AT_const_value (1)
+; CHECK-DWARF: NULL
+; CHECK-DWARF: DW_TAG_variable
+; CHECK-DWARF: DW_AT_name ("__profc_foo")
+; CHECK-DWARF: DW_AT_type ({{.*}} "Profile Data Type")
+; CHECK-DWARF: DW_TAG_LLVM_annotation
+; CHECK-DWARF: DW_AT_name ("Function Name")
+; CHECK-DWARF: DW_AT_const_value ("foo")
+; CHECK-DWARF: DW_TAG_LLVM_annotation
+; CHECK-DWARF: DW_AT_name ("CFG Hash")
+; CHECK-DWARF: DW_AT_const_value (12345678)
+; CHECK-DWARF: DW_TAG_LLVM_annotation
+; CHECK-DWARF: DW_AT_name ("Num Counters")
+; CHECK-DWARF: DW_AT_const_value (2)
+; CHECK-DWARF: NULL
+; CHECK-DWARF: NULL
+; CHECK-DWARF: DW_TAG_unspecified_type
+; CHECK-DWARF: DW_AT_name ("Profile Bitmap Type")
+; CHECK-DWARF: DW_TAG_unspecified_type
+; CHECK-DWARF: DW_AT_name ("Profile Data Type")
+; CHECK-DWARF: NULL
More information about the llvm-commits
mailing list