diff options
Diffstat (limited to 'tools/llvm-profdata/llvm-profdata.cpp')
-rw-r--r-- | tools/llvm-profdata/llvm-profdata.cpp | 74 |
1 files changed, 64 insertions, 10 deletions
diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp index e9bc2de82bdf0..eee242107dabe 100644 --- a/tools/llvm-profdata/llvm-profdata.cpp +++ b/tools/llvm-profdata/llvm-profdata.cpp @@ -159,14 +159,20 @@ static void loadInput(const WeightedFile &Input, WriterContext *WC) { for (auto &I : *Reader) { const StringRef FuncName = I.Name; - if (Error E = WC->Writer.addRecord(std::move(I), Input.Weight)) { + bool Reported = false; + WC->Writer.addRecord(std::move(I), Input.Weight, [&](Error E) { + if (Reported) { + consumeError(std::move(E)); + return; + } + Reported = true; // Only show hint the first time an error occurs. instrprof_error IPE = InstrProfError::take(std::move(E)); std::unique_lock<std::mutex> ErrGuard{WC->ErrLock}; bool firstTime = WC->WriterErrorCodes.insert(IPE).second; handleMergeWriterError(make_error<InstrProfError>(IPE), Input.Filename, FuncName, firstTime); - } + }); } if (Reader->hasError()) WC->Err = Reader->getError(); @@ -174,8 +180,15 @@ static void loadInput(const WeightedFile &Input, WriterContext *WC) { /// Merge the \p Src writer context into \p Dst. static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) { - if (Error E = Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer))) + bool Reported = false; + Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) { + if (Reported) { + consumeError(std::move(E)); + return; + } + Reported = true; Dst->Err = std::move(E); + }); } static void mergeInstrProfile(const WeightedFileVector &Inputs, @@ -499,8 +512,8 @@ static void showValueSitesStats(raw_fd_ostream &OS, uint32_t VK, } static int showInstrProfile(const std::string &Filename, bool ShowCounts, - bool ShowIndirectCallTargets, bool ShowMemOPSizes, - bool ShowDetailedSummary, + uint32_t TopN, bool ShowIndirectCallTargets, + bool ShowMemOPSizes, bool ShowDetailedSummary, std::vector<uint32_t> DetailedSummaryCutoffs, bool ShowAllFunctions, const std::string &ShowFunction, bool TextFormat, @@ -519,6 +532,17 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, size_t ShownFunctions = 0; int NumVPKind = IPVK_Last - IPVK_First + 1; std::vector<ValueSitesStats> VPStats(NumVPKind); + + auto MinCmp = [](const std::pair<std::string, uint64_t> &v1, + const std::pair<std::string, uint64_t> &v2) { + return v1.second > v2.second; + }; + + std::priority_queue<std::pair<std::string, uint64_t>, + std::vector<std::pair<std::string, uint64_t>>, + decltype(MinCmp)> + HottestFuncs(MinCmp); + for (const auto &Func : *Reader) { bool Show = ShowAllFunctions || (!ShowFunction.empty() && @@ -528,13 +552,28 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, if (doTextFormatDump) { InstrProfSymtab &Symtab = Reader->getSymtab(); - InstrProfWriter::writeRecordInText(Func, Symtab, OS); + InstrProfWriter::writeRecordInText(Func.Name, Func.Hash, Func, Symtab, + OS); continue; } assert(Func.Counts.size() > 0 && "function missing entry counter"); Builder.addRecord(Func); + if (TopN) { + uint64_t FuncMax = 0; + for (size_t I = 0, E = Func.Counts.size(); I < E; ++I) + FuncMax = std::max(FuncMax, Func.Counts[I]); + + if (HottestFuncs.size() == TopN) { + if (HottestFuncs.top().second < FuncMax) { + HottestFuncs.pop(); + HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax)); + } + } else + HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax)); + } + if (Show) { if (!ShownFunctions) @@ -592,6 +631,18 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n"; OS << "Maximum internal block count: " << PS->getMaxInternalCount() << "\n"; + if (TopN) { + std::vector<std::pair<std::string, uint64_t>> SortedHottestFuncs; + while (!HottestFuncs.empty()) { + SortedHottestFuncs.emplace_back(HottestFuncs.top()); + HottestFuncs.pop(); + } + OS << "Top " << TopN + << " functions with the largest internal block counts: \n"; + for (auto &hotfunc : llvm::reverse(SortedHottestFuncs)) + OS << " " << hotfunc.first << ", max count = " << hotfunc.second << "\n"; + } + if (ShownFunctions && ShowIndirectCallTargets) { OS << "Statistics for indirect call sites profile:\n"; showValueSitesStats(OS, IPVK_IndirectCallTarget, @@ -675,6 +726,9 @@ static int show_main(int argc, const char *argv[]) { cl::desc("Profile kind:"), cl::init(instr), cl::values(clEnumVal(instr, "Instrumentation profile (default)"), clEnumVal(sample, "Sample profile"))); + cl::opt<uint32_t> TopNFunctions( + "topn", cl::init(0), + cl::desc("Show the list of functions with the largest internal counts")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); @@ -692,10 +746,10 @@ static int show_main(int argc, const char *argv[]) { std::vector<uint32_t> Cutoffs(DetailedSummaryCutoffs.begin(), DetailedSummaryCutoffs.end()); if (ProfileKind == instr) - return showInstrProfile(Filename, ShowCounts, ShowIndirectCallTargets, - ShowMemOPSizes, ShowDetailedSummary, - DetailedSummaryCutoffs, ShowAllFunctions, - ShowFunction, TextFormat, OS); + return showInstrProfile(Filename, ShowCounts, TopNFunctions, + ShowIndirectCallTargets, ShowMemOPSizes, + ShowDetailedSummary, DetailedSummaryCutoffs, + ShowAllFunctions, ShowFunction, TextFormat, OS); else return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, ShowFunction, OS); |