Index: llvm/trunk/docs/CommandGuide/llvm-profdata.rst =================================================================== --- llvm/trunk/docs/CommandGuide/llvm-profdata.rst +++ llvm/trunk/docs/CommandGuide/llvm-profdata.rst @@ -192,6 +192,12 @@ information is dumped in a more human readable form (also in text) with annotations. +.. option:: -topn=n + + Instruct the profile dumper to show the top ``n`` functions with the + hottest basic blocks in the summary section. By default, the topn functions + are not dumped. + .. option:: -sample Specify that the input profile is a sample-based profile. Index: llvm/trunk/test/tools/llvm-profdata/c-general.test =================================================================== --- llvm/trunk/test/tools/llvm-profdata/c-general.test +++ llvm/trunk/test/tools/llvm-profdata/c-general.test @@ -10,6 +10,7 @@ REGENERATE: $ LLVM_PROFILE_FILE=$TESTDIR/Inputs/c-general.profraw ./a.out RUN: llvm-profdata show %p/Inputs/c-general.profraw -o - | FileCheck %s +RUN: llvm-profdata show %p/Inputs/c-general.profraw --topn=3 -o - | FileCheck %s --check-prefix=TOPN RUN: llvm-profdata show %p/Inputs/c-general.profraw -o - --function=switches | FileCheck %s -check-prefix=SWITCHES -check-prefix=CHECK SWITCHES-LABEL: Counters: @@ -22,3 +23,6 @@ CHECK-LABEL: Total functions: 12 CHECK-NEXT: Maximum function count: 1 CHECK-NEXT: Maximum internal block count: 100 +TOPN: boolean_operators, max count = 100 +TOPN-NEXT: simple_loops, max count = 100 +TOPN-NEXT: conditionals, max count = 100 Index: llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp =================================================================== --- llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp +++ llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp @@ -512,8 +512,8 @@ } 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 DetailedSummaryCutoffs, bool ShowAllFunctions, const std::string &ShowFunction, bool TextFormat, @@ -532,6 +532,17 @@ size_t ShownFunctions = 0; int NumVPKind = IPVK_Last - IPVK_First + 1; std::vector VPStats(NumVPKind); + + auto MinCmp = [](const std::pair &v1, + const std::pair &v2) { + return v1.second > v2.second; + }; + + std::priority_queue, + std::vector>, + decltype(MinCmp)> + HottestFuncs(MinCmp); + for (const auto &Func : *Reader) { bool Show = ShowAllFunctions || (!ShowFunction.empty() && @@ -549,6 +560,20 @@ 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) @@ -606,6 +631,18 @@ OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n"; OS << "Maximum internal block count: " << PS->getMaxInternalCount() << "\n"; + if (TopN) { + std::vector> 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, @@ -689,6 +726,9 @@ cl::desc("Profile kind:"), cl::init(instr), cl::values(clEnumVal(instr, "Instrumentation profile (default)"), clEnumVal(sample, "Sample profile"))); + cl::opt 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"); @@ -706,10 +746,10 @@ std::vector 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);