diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.c @@ -0,0 +1,13 @@ +// Disable full debug info and verify that we get warnings during merging + +// RUN: %clang_pgogen -o %t -gline-tables-only -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp +// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t +// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.proflite --max-debug-info-correlation-warnings=2 2>&1 >/dev/null | FileCheck %s --check-prefixes=CHECK,LIMIT --implicit-check-not=warning +// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.proflite --max-debug-info-correlation-warnings=0 2>&1 >/dev/null | FileCheck %s --check-prefixes=CHECK,NOLIMIT --implicit-check-not=warning + +// CHECK: warning: Could not find address of function +// CHECK: warning: Could not find address of function +// NOLIMIT: warning: Could not find address of function +// NOLIMIT: warning: Could not find address of function +// NOLIMIT: warning: Could not find address of function +// LIMIT: warning: Suppressed 3 additional warnings diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h --- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h +++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h @@ -36,10 +36,12 @@ /// Construct a ProfileData vector used to correlate raw instrumentation data /// to their functions. - virtual Error correlateProfileData() = 0; + /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit) + virtual Error correlateProfileData(int MaxWarnings) = 0; /// Process debug info and dump the correlation data. - virtual Error dumpYaml(raw_ostream &OS) = 0; + /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit) + virtual Error dumpYaml(int MaxWarnings, raw_ostream &OS) = 0; /// Return the number of ProfileData elements. std::optional getDataSize() const; @@ -131,11 +133,12 @@ protected: std::vector> Data; - Error correlateProfileData() override; + Error correlateProfileData(int MaxWarnings) override; virtual void correlateProfileDataImpl( + int MaxWarnings, InstrProfCorrelator::CorrelationData *Data = nullptr) = 0; - Error dumpYaml(raw_ostream &OS) override; + Error dumpYaml(int MaxWarnings, raw_ostream &OS) override; void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset, IntPtrT FunctionPtr, uint32_t NumCounters); @@ -197,7 +200,10 @@ /// NULL /// NULL /// \endcode + /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit) + /// \param Data if provided, populate with the correlation data found void correlateProfileDataImpl( + int MaxWarnings, InstrProfCorrelator::CorrelationData *Data = nullptr) override; }; diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp --- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp +++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp @@ -16,6 +16,8 @@ #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/WithColor.h" #include #define DEBUG_TYPE "correlator" @@ -142,9 +144,9 @@ } template -Error InstrProfCorrelatorImpl::correlateProfileData() { +Error InstrProfCorrelatorImpl::correlateProfileData(int MaxWarnings) { assert(Data.empty() && Names.empty() && NamesVec.empty()); - correlateProfileDataImpl(); + correlateProfileDataImpl(MaxWarnings); if (Data.empty() || NamesVec.empty()) return make_error( instrprof_error::unable_to_correlate_profile, @@ -180,9 +182,10 @@ }; template -Error InstrProfCorrelatorImpl::dumpYaml(raw_ostream &OS) { +Error InstrProfCorrelatorImpl::dumpYaml(int MaxWarnings, + raw_ostream &OS) { InstrProfCorrelator::CorrelationData Data; - correlateProfileDataImpl(&Data); + correlateProfileDataImpl(MaxWarnings, &Data); if (Data.Probes.empty()) return make_error( instrprof_error::unable_to_correlate_profile, @@ -260,7 +263,10 @@ template void DwarfInstrProfCorrelator::correlateProfileDataImpl( - InstrProfCorrelator::CorrelationData *Data) { + 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; @@ -297,28 +303,30 @@ } } if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) { - LLVM_DEBUG(dbgs() << "Incomplete DIE for probe\n\tFunctionName: " - << FunctionName << "\n\tCFGHash: " << CFGHash - << "\n\tCounterPtr: " << CounterPtr - << "\n\tNumCounters: " << NumCounters); - LLVM_DEBUG(Die.dump(dbgs())); + 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) { - LLVM_DEBUG( - dbgs() << "CounterPtr out of range for probe\n\tFunction Name: " - << FunctionName << "\n\tExpected: [0x" - << Twine::utohexstr(CountersStart) << ", 0x" - << Twine::utohexstr(CountersEnd) << ")\n\tActual: 0x" - << Twine::utohexstr(*CounterPtr)); - LLVM_DEBUG(Die.dump(dbgs())); + 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) { - LLVM_DEBUG(dbgs() << "Could not find address of " << *FunctionName - << "\n"); + if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) { + WithColor::warning() << format("Could not find address of function %s\n", + *FunctionName); LLVM_DEBUG(Die.dump(dbgs())); } IntPtrT CounterOffset = *CounterPtr - CountersStart; @@ -348,4 +356,8 @@ for (auto &CU : DICtx->dwo_units()) for (const auto &Entry : CU->dies()) maybeAddProbe(DWARFDie(CU.get(), &Entry)); + + if (!UnlimitedWarnings && NumSuppressedWarnings > 0) + WithColor::warning() << format("Suppressed %d additional warnings\n", + NumSuppressedWarnings); } diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -1056,12 +1056,6 @@ Annotations); CounterPtr->addDebugInfo(DICounter); DB.finalize(); - } else { - std::string Msg = ("Missing debug info for function " + Fn->getName() + - "; required for profile correlation.") - .str(); - Ctx.diagnose( - DiagnosticInfoPGOProfile(M->getName().data(), Msg, DS_Warning)); } } diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -407,8 +407,8 @@ mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename, SymbolRemapper *Remapper, StringRef OutputFilename, ProfileFormat OutputFormat, uint64_t TraceReservoirSize, - uint64_t MaxTraceLength, bool OutputSparse, - unsigned NumThreads, FailureMode FailMode, + uint64_t MaxTraceLength, int MaxDbgCorrelationWarnings, + bool OutputSparse, unsigned NumThreads, FailureMode FailMode, const StringRef ProfiledBinary) { if (OutputFormat == PF_Compact_Binary) exitWithError("Compact Binary is deprecated"); @@ -421,7 +421,7 @@ if (auto Err = InstrProfCorrelator::get(DebugInfoFilename).moveInto(Correlator)) exitWithError(std::move(Err), DebugInfoFilename); - if (auto Err = Correlator->correlateProfileData()) + if (auto Err = Correlator->correlateProfileData(MaxDbgCorrelationWarnings)) exitWithError(std::move(Err), DebugInfoFilename); } @@ -1270,6 +1270,11 @@ cl::opt DebugInfoFilename( "debug-info", cl::init(""), cl::desc("Use the provided debug info to correlate the raw profile.")); + cl::opt MaxDbgCorrelationWarnings( + "max-debug-info-correlation-warnings", + cl::desc("The maximum number of warnings to emit when correlating " + "profile from debug info (0 = no limit)"), + cl::init(5)); cl::opt ProfiledBinary( "profiled-binary", cl::init(""), cl::desc("Path to binary from which the profile was collected.")); @@ -1331,8 +1336,8 @@ mergeInstrProfile(WeightedInputs, DebugInfoFilename, Remapper.get(), OutputFilename, OutputFormat, TemporalProfTraceReservoirSize, - TemporalProfMaxTraceLength, OutputSparse, NumThreads, - FailureMode, ProfiledBinary); + TemporalProfMaxTraceLength, MaxDbgCorrelationWarnings, + OutputSparse, NumThreads, FailureMode, ProfiledBinary); else mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename, OutputFormat, ProfileSymbolListFile, CompressAllSections, @@ -2877,6 +2882,7 @@ static int showDebugInfoCorrelation(const std::string &Filename, bool ShowDetailedSummary, bool ShowProfileSymbolList, + int MaxDbgCorrelationWarnings, ShowFormat SFormat, raw_fd_ostream &OS) { if (SFormat == ShowFormat::Json) exitWithError("JSON output is not supported for debug info correlation"); @@ -2884,12 +2890,12 @@ if (auto Err = InstrProfCorrelator::get(Filename).moveInto(Correlator)) exitWithError(std::move(Err), Filename); if (SFormat == ShowFormat::Yaml) { - if (auto Err = Correlator->dumpYaml(OS)) + if (auto Err = Correlator->dumpYaml(MaxDbgCorrelationWarnings, OS)) exitWithError(std::move(Err), Filename); return 0; } - if (auto Err = Correlator->correlateProfileData()) + if (auto Err = Correlator->correlateProfileData(MaxDbgCorrelationWarnings)) exitWithError(std::move(Err), Filename); InstrProfSymtab Symtab; @@ -2989,6 +2995,11 @@ "debug-info", cl::init(""), cl::desc("Read and extract profile metadata from debug info and show " "the functions it found.")); + cl::opt MaxDbgCorrelationWarnings( + "max-debug-info-correlation-warnings", + cl::desc("The maximum number of warnings to emit when correlating " + "profile from debug info (0 = no limit)"), + cl::init(5)); cl::opt ShowCovered( "covered", cl::init(false), cl::desc("Show only the functions that have been executed.")); @@ -3022,7 +3033,8 @@ if (!DebugInfoFilename.empty()) return showDebugInfoCorrelation(DebugInfoFilename, ShowDetailedSummary, - ShowProfileSymbolList, SFormat, OS); + ShowProfileSymbolList, + MaxDbgCorrelationWarnings, SFormat, OS); if (ProfileKind == instr) return showInstrProfile(