diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp index 14402730cb8fc..77baa9bc5a43e 100644 --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -153,6 +153,12 @@ void VirtualUnwinder::collectSamplesFromFrameTrie( for (const auto &Item : Cur->Children) { collectSamplesFromFrameTrie(Item.second.get(), EmptyStack); } + + // Keep note of untracked call site and deduplicate them + // for warning later. + if (!Cur->isLeafFrame()) + UntrackedCallsites.insert(Cur->Address); + return; } } @@ -368,12 +374,22 @@ void HybridPerfReader::writeRawProfile(raw_fd_ostream &OS) { } void HybridPerfReader::unwindSamples() { + std::set AllUntrackedCallsites; for (const auto &Item : AggregatedSamples) { const PerfSample *Sample = Item.first.getPtr(); VirtualUnwinder Unwinder(&SampleCounters, Binary); Unwinder.unwind(Sample, Item.second); + auto &CurrUntrackedCallsites = Unwinder.getUntrackedCallsites(); + AllUntrackedCallsites.insert(CurrUntrackedCallsites.begin(), + CurrUntrackedCallsites.end()); } + // Warn about untracked frames due to missing probes. + for (auto Address : AllUntrackedCallsites) + WithColor::warning() << "Profile context truncated due to missing probe " + << "for call instruction at " + << format("%" PRIx64, Address) << "\n"; + if (SkipSymbolization) PerfReaderBase::writeRawProfile(OutputFilename); } diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h index 41ab200543514..0595c7dc5973a 100644 --- a/llvm/tools/llvm-profgen/PerfReader.h +++ b/llvm/tools/llvm-profgen/PerfReader.h @@ -13,6 +13,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Regex.h" +#include #include #include #include @@ -411,13 +412,8 @@ struct ProbeStack { // Callsite merging may cause the loss of original probe IDs. // Cutting off the context from here since the inliner will // not know how to consume a context with unknown callsites. - if (!CallProbe) { - if (!Cur->isLeafFrame()) - WithColor::warning() - << "Untracked frame at " << format("%" PRIx64, Cur->Address) - << " due to missing call probe\n"; + if (!CallProbe) return false; - } Stack.push_back(CallProbe); return true; } @@ -464,6 +460,7 @@ class VirtualUnwinder { VirtualUnwinder(ContextSampleCounterMap *Counter, const ProfiledBinary *B) : CtxCounterMap(Counter), Binary(B) {} bool unwind(const PerfSample *Sample, uint64_t Repeat); + std::set &getUntrackedCallsites() { return UntrackedCallsites; } private: bool isCallState(UnwindState &State) const { @@ -498,6 +495,8 @@ class VirtualUnwinder { ContextSampleCounterMap *CtxCounterMap; // Profiled binary that current frame address belongs to const ProfiledBinary *Binary; + // Keep track of all untracked callsites + std::set UntrackedCallsites; }; // Read perf trace to parse the events and samples.