Skip to content

[MC/DC][Coverage] Enable profile correlation for MC/DC #136437

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

belyaevrd
Copy link

When using the -fcoverage-mcdc option in profile correlation mode MC/DC coverage is not actually collected.

In binary profile correlation mode this completes elements of a vector of per-function profile data structures called Data with BitmapPtr and NumBitmapBytes values that are taken from profile data section in the same way as it is done for Counters.

In debug info correlation mode this adds new Profile Bitmap Type DIEs to DWARFContext. These entries contain FunctionName and NumBitmapBits for functions. They are used by correlateProfileDataImpl() function to obtain BitmapPtr and NumBitmapBytes values to complete the corresponding elements of the vector of per-function profile data structures called Data. Creating and reading these new DIEs occur in the same way as it is done for DIEs of the type Profile Data Type.

Fixes #97385

When using the `-fcoverage-mcdc` option in profile correlation mode MC/DC
coverage is not actually collected.

In binary profile correlation mode this completes elements of a vector of
per-function profile data structures called `Data` with BitmapPtr and
NumBitmapBytes values that are taken from profile data section in the same way
as it is done for Counters.

In debug info correlation mode this adds new `Profile Bitmap Type` DIEs to
DWARFContext. These entries contain FunctionName and NumBitmapBits for
functions. They are used by `correlateProfileDataImpl()` function to obtain
BitmapPtr and NumBitmapBytes values to complete the corresponding elements of
the vector of per-function profile data structures called `Data`. Creating and
reading these new DIEs occur in the same way as it is done for DIEs of the type
`Profile Data Type`.

Fixes llvm#97385
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added compiler-rt PGO Profile Guided Optimizations llvm:transforms labels Apr 19, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 19, 2025

@llvm/pr-subscribers-pgo

@llvm/pr-subscribers-llvm-transforms

Author: Roman Beliaev (belyaevrd)

Changes

When using the -fcoverage-mcdc option in profile correlation mode MC/DC coverage is not actually collected.

In binary profile correlation mode this completes elements of a vector of per-function profile data structures called Data with BitmapPtr and NumBitmapBytes values that are taken from profile data section in the same way as it is done for Counters.

In debug info correlation mode this adds new Profile Bitmap Type DIEs to DWARFContext. These entries contain FunctionName and NumBitmapBits for functions. They are used by correlateProfileDataImpl() function to obtain BitmapPtr and NumBitmapBytes values to complete the corresponding elements of the vector of per-function profile data structures called Data. Creating and reading these new DIEs occur in the same way as it is done for DIEs of the type Profile Data Type.

Fixes #97385


Patch is 27.95 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136437.diff

8 Files Affected:

  • (modified) compiler-rt/lib/profile/InstrProfilingWriter.c (+1)
  • (added) compiler-rt/test/profile/Inputs/instrprof-mcdc-correlation.cpp (+14)
  • (added) compiler-rt/test/profile/instrprof-mcdc-correlation.c (+21)
  • (modified) llvm/include/llvm/ProfileData/InstrProfCorrelator.h (+12-4)
  • (modified) llvm/include/llvm/ProfileData/InstrProfReader.h (+2-1)
  • (modified) llvm/lib/ProfileData/InstrProfCorrelator.cpp (+219-90)
  • (modified) llvm/lib/ProfileData/InstrProfReader.cpp (+1-1)
  • (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+34)
diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c
index 633fdb9661162..4d453bc8d74b4 100644
--- a/compiler-rt/lib/profile/InstrProfilingWriter.c
+++ b/compiler-rt/lib/profile/InstrProfilingWriter.c
@@ -320,6 +320,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;
   }
 
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..acc63f0375cbd
--- /dev/null
+++ b/compiler-rt/test/profile/Inputs/instrprof-mcdc-correlation.cpp
@@ -0,0 +1,14 @@
+void test(bool a, bool b, bool c, bool d) {
+  if ((a && b) || (c && d))
+    ;
+  if (b && c)
+    ;
+}
+
+int main() {
+  test(true, true, true, true);
+  test(true, true, false, true);
+  test(true, false, true, true);
+  (void)0;
+  return 0;
+}
diff --git a/compiler-rt/test/profile/instrprof-mcdc-correlation.c b/compiler-rt/test/profile/instrprof-mcdc-correlation.c
new file mode 100644
index 0000000000000..e915f27c7b80a
--- /dev/null
+++ b/compiler-rt/test/profile/instrprof-mcdc-correlation.c
@@ -0,0 +1,21 @@
+// REQUIRES: linux || windows
+// 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/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
index ed8642495cd74..1c800ae22cd3c 100644
--- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
+++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
@@ -68,6 +68,7 @@ class InstrProfCorrelator {
   static const char *FunctionNameAttributeName;
   static const char *CFGHashAttributeName;
   static const char *NumCountersAttributeName;
+  static const char *NumBitmapBitsAttributeName;
 
   enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit };
   InstrProfCorrelatorKind getKind() const { return Kind; }
@@ -82,6 +83,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;
@@ -104,7 +108,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;
   };
@@ -158,8 +164,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 {
@@ -171,6 +178,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
@@ -190,8 +198,8 @@ 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, const StringRef &Prefix);
 
   /// 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 f1010b312ee56..02f49d08cf29d 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -470,7 +470,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 difference between
       // the data and counts sections:
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index d92107f93dc56..7d6d320f92b16 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -51,6 +51,7 @@ Expected<object::SectionRef> getInstrProfSection(const object::ObjectFile &Obj,
 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,
@@ -81,6 +82,17 @@ InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
   C->Buffer = std::move(Buffer);
   C->CountersSectionStart = CountersSection->getAddress();
   C->CountersSectionEnd = C->CountersSectionStart + CountersSection->getSize();
+
+  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 the counter
   // section which doesn't exist in raw profile.
   if (Obj.getTripleObjectFormat() == Triple::COFF)
@@ -236,6 +248,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;
 }
@@ -253,7 +266,9 @@ template <> struct yaml::MappingTraits<InstrProfCorrelator::Probe> {
     io.mapOptional("Linkage Name", P.LinkageName);
     io.mapRequired("CFG Hash", P.CFGHash);
     io.mapRequired("Counter Offset", P.CounterOffset);
+    io.mapRequired("Bitmap Offset", P.BitmapOffset);
     io.mapRequired("Num Counters", P.NumCounters);
+    io.mapRequired("Num BitmapBytes", P.NumBitmapBytes);
     io.mapOptional("File", P.FilePath);
     io.mapOptional("Line", P.LineNumber);
   }
@@ -281,8 +296,10 @@ template <class IntPtrT>
 void InstrProfCorrelatorImpl<IntPtrT>::addDataProbe(uint64_t NameRef,
                                                     uint64_t CFGHash,
                                                     IntPtrT CounterOffset,
+                                                    IntPtrT BitmapOffset,
                                                     IntPtrT FunctionPtr,
-                                                    uint32_t NumCounters) {
+                                                    uint32_t NumCounters,
+                                                    uint32_t NumBitmapBytes) {
   // Check if a probe was already added for this counter offset.
   if (!CounterOffsets.insert(CounterOffset).second)
     return;
@@ -292,15 +309,13 @@ void InstrProfCorrelatorImpl<IntPtrT>::addDataProbe(uint64_t NameRef,
       // In this mode, CounterPtr actually stores the section relative address
       // of the counter.
       maybeSwap<IntPtrT>(CounterOffset),
-      // 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)},
-      // TODO: MC/DC is not yet supported.
-      /*NumBitmapBytes=*/maybeSwap<uint32_t>(0),
+      maybeSwap<uint32_t>(NumBitmapBytes),
   });
 }
 
@@ -331,7 +346,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,
+                                                     const StringRef &Prefix) {
   const auto &ParentDie = Die.getParent();
   if (!Die.isValid() || !ParentDie.isValid() || Die.isNULL())
     return false;
@@ -342,106 +358,199 @@ 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>
 void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
     int MaxWarnings, InstrProfCorrelator::CorrelationData *Data) {
+  using RawProfData = RawInstrProf::ProfileData<IntPtrT>;
   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))
+  auto maybeAddProbe = [&](DWARFDie Die, const StringRef &Prefix) {
+    if (!isDIEOfProbe(Die, Prefix))
       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;
+    if (Prefix == getInstrProfCountersVarPrefix()) {
+      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();
+        }
       }
-      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 (!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;
       }
-    }
-    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()));
+      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;
       }
-      return;
-    }
-    uint64_t CountersStart = this->Ctx->CountersSectionStart;
-    uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
-    if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {
-      if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+      if (!FunctionPtr && (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);
+            << format("Could not find address of function %s\n", *FunctionName);
         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 (auto 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);
+      // 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 (auto 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, 0, FunctionPtr.value_or(0),
+                           *NumCounters, 0);
+        this->NamesVec.push_back(*FunctionName);
+      }
+    } else if (Prefix == getInstrProfBitmapVarPrefix()) {
+      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(Fu...
[truncated]

@evodius96
Copy link
Contributor

Hello -- thank you for implementing this! I can review, if you like, but it would probably also be good to include @ellishg as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt llvm:transforms PGO Profile Guided Optimizations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[llvm-cov][MC/DC] "Out-of-bounds Bit access." when run with binary profile correlation
3 participants