[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