[compiler-rt] [llvm] [MC/DC][Coverage] Enable profile correlation for MC/DC (PR #136437)

Ellis Hoag via llvm-commits llvm-commits at lists.llvm.org
Fri May 1 11:31:32 PDT 2026


================
@@ -361,102 +377,223 @@ 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) {
-  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))
-      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;
-      }
-      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();
-      }
+void DwarfInstrProfCorrelator<IntPtrT>::addCountersToDataProbe(
+    InstrProfCorrelator::CorrelationData *Data, const DWARFDie &Die,
+    const bool UnlimitedWarnings, int &NumSuppressedWarnings) {
+  using RawProfData = RawInstrProf::ProfileData<IntPtrT>;
+  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 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()));
+    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;
+    // Try to find appropriate probe.
+    for (InstrProfCorrelator::Probe &Probe : Data->Probes) {
+      if (Probe.FunctionName == *FunctionName) {
+        Probe.LinkageName = P.LinkageName;
+        Probe.CFGHash = P.CFGHash;
+        Probe.CounterOffset = P.CounterOffset;
+        Probe.NumCounters = P.NumCounters;
+        Probe.FilePath = P.FilePath;
+        Probe.LineNumber = P.LineNumber;
+        return;
       }
-      return;
     }
----------------
ellishg wrote:

This is new. Can you elaborate on why we are searching for a probe with the same name? This might need to be a separate PR since it impact all debug info correlation, not just MC/DC. Also, if we really need to search existing probes, we should consider using a map from function name to probe.

https://github.com/llvm/llvm-project/pull/136437


More information about the llvm-commits mailing list