From: Xinliang David Li Date: Tue, 11 Jul 2017 20:30:43 +0000 (+0000) Subject: [ProfileData] Add new option to dump topn hottest functions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dcb98bd9b07dc2df45a5dbf37facea8a1a7039b6;p=llvm [ProfileData] Add new option to dump topn hottest functions Differential Revision: http://reviews.llvm.org/D35155 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307702 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/CommandGuide/llvm-profdata.rst b/docs/CommandGuide/llvm-profdata.rst index f7aa8309485..5b6330b5dc4 100644 --- a/docs/CommandGuide/llvm-profdata.rst +++ b/docs/CommandGuide/llvm-profdata.rst @@ -192,6 +192,12 @@ OPTIONS 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. diff --git a/test/tools/llvm-profdata/c-general.test b/test/tools/llvm-profdata/c-general.test index 0ec7c113eb4..ddb95d1260d 100644 --- a/test/tools/llvm-profdata/c-general.test +++ b/test/tools/llvm-profdata/c-general.test @@ -10,6 +10,7 @@ REGENERATE: $ clang -o a.out -fprofile-instr-generate $CFE_TESTDIR/c-general.c 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 @@ SWITCHES-LABEL: Functions shown: 1 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 diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp index f7d1c622f8f..eee242107da 100644 --- a/tools/llvm-profdata/llvm-profdata.cpp +++ b/tools/llvm-profdata/llvm-profdata.cpp @@ -512,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 DetailedSummaryCutoffs, bool ShowAllFunctions, const std::string &ShowFunction, bool TextFormat, @@ -532,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 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 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, 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 @@ 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> 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 @@ 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 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 @@ static int show_main(int argc, const char *argv[]) { 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);