[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
Wed Dec 3 15:54:32 PST 2025
================
@@ -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(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;
+ }
+ 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;
+ }
+ 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;
+ }
+ // 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;
+ // Add bitmap information to the corresponding profile data entry.
+ if (Data) {
+ for (auto P : Data->Probes) {
+ if (P.FunctionName == *FunctionName) {
+ P.BitmapOffset = BitmapOffset;
+ P.NumBitmapBytes = NumBitmapBytes;
+ return;
+ }
+ }
+ } else {
+ for (const RawProfData &I : this->Data) {
+ if (I.NameRef == IndexedInstrProf::ComputeHash(*FunctionName)) {
+ const_cast<IntPtrT &>(I.BitmapPtr) = BitmapOffset;
+ const_cast<uint32_t &>(I.NumBitmapBytes) = NumBitmapBytes;
+ return;
+ }
+ }
+ }
+ WithColor::warning() << format(
+ "Could not find Counters for function %s\n", *FunctionName);
}
};
- for (auto &CU : DICtx->normal_units())
+ for (auto &CU : DICtx->normal_units()) {
for (const auto &Entry : CU->dies())
- maybeAddProbe(DWARFDie(CU.get(), &Entry));
- for (auto &CU : DICtx->dwo_units())
+ maybeAddProbe(DWARFDie(CU.get(), &Entry),
+ getInstrProfCountersVarPrefix());
for (const auto &Entry : CU->dies())
- maybeAddProbe(DWARFDie(CU.get(), &Entry));
+ maybeAddProbe(DWARFDie(CU.get(), &Entry), getInstrProfBitmapVarPrefix());
----------------
ellishg wrote:
Can we fold these two loops into one? And also put `DWARFDie(CU.get(), &Entry)` into a variable so it can be reused?
https://github.com/llvm/llvm-project/pull/136437
More information about the llvm-commits
mailing list