Index: test/tools/llvm-profdata/Inputs/cutoff.proftext =================================================================== --- test/tools/llvm-profdata/Inputs/cutoff.proftext +++ test/tools/llvm-profdata/Inputs/cutoff.proftext @@ -0,0 +1,21 @@ +# IR level Instrumentation Flag +:ir +bar +10 +2 +0 +0 + +main +16650 +4 +1 +1000 +1000000 +499500 + +foo +10 +2 +999 +1 Index: test/tools/llvm-profdata/cutoff.test =================================================================== --- test/tools/llvm-profdata/cutoff.test +++ test/tools/llvm-profdata/cutoff.test @@ -0,0 +1,23 @@ +Basic tests for cutoff options in show command. + +RUN: llvm-profdata show -value-cutoff=1 %p/Inputs/cutoff.proftext | FileCheck %s -check-prefix=CUTOFF1 -check-prefix=CHECK +RUN: llvm-profdata show -value-cutoff=1000 %p/Inputs/cutoff.proftext | FileCheck %s -check-prefix=CUTOFF1000 -check-prefix=CHECK +RUN: llvm-profdata show -all-functions -value-cutoff=1 %p/Inputs/cutoff.proftext | FileCheck %s -check-prefix=CUTOFF1FUNC -check-prefix=CUTOFF1 -check-prefix=CHECK +RUN: llvm-profdata show -all-functions -value-cutoff=1000 %p/Inputs/cutoff.proftext | FileCheck %s -check-prefix=CUTOFF1000FUNC -check-prefix=CUTOFF1000 -check-prefix=CHECK +RUN: llvm-profdata show -value-cutoff=1 -list-below-cutoff %p/Inputs/cutoff.proftext | FileCheck %s -check-prefix=BELOW1 -check-prefix=CUTOFF1 -check-prefix=CHECK +RUN: llvm-profdata show -value-cutoff=1000 -list-below-cutoff %p/Inputs/cutoff.proftext | FileCheck %s -check-prefix=BELOW1000 -check-prefix=CUTOFF1000 -check-prefix=CHECK +CUTOFF1FUNC-NOT: bar +CUTOFF1FUNC: Functions shown: 2 +CUTOFF1000FUNC-NOT: bar +CUTOFF1000FUNC-NOT: foo +CUTOFF1000FUNC: Functions shown: 1 +BELOW1: The list of functions with the maximum counter less than 1: +BELOW1: bar: (Max = 0 Sum = 0) +BELOW1000:The list of functions with the maximum counter less than 1000: +BELOW1000: bar: (Max = 0 Sum = 0) +BELOW1000: foo: (Max = 999 Sum = 1000) +CHECK: Total functions: 3 +CUTOFF1: Below Value Cutoff functions: 1 +CUTOFF1: Number of Functions with maximum Count (>= 1): 2, and (< 1): 1 +CUTOFF1000: Below Value Cutoff functions: 2 +CUTOFF1000: Number of Functions with maximum Count (>= 1000): 1, and (< 1000): 2 Index: test/tools/llvm-profdata/value-prof.proftext =================================================================== --- test/tools/llvm-profdata/value-prof.proftext +++ test/tools/llvm-profdata/value-prof.proftext @@ -47,9 +47,9 @@ #ICTXT: Indirect Call Site Count: 3 #ICTXT-NEXT: Indirect Target Results: -#ICTXT-NEXT: [ 1, foo, 100 ] -#ICTXT-NEXT: [ 1, foo2, 1000 ] -#ICTXT-NEXT: [ 2, foo2, 20000 ] +#ICTXT-NEXT: [ 1, foo, 100 ] ( 9.09%) +#ICTXT-NEXT: [ 1, foo2, 1000 ] ( 90.91%) +#ICTXT-NEXT: [ 2, foo2, 20000 ] (100.00%) #IC: Indirect Call Site Count: 3 #IC-NEXT: Indirect Target Results: Index: tools/llvm-profdata/llvm-profdata.cpp =================================================================== --- tools/llvm-profdata/llvm-profdata.cpp +++ tools/llvm-profdata/llvm-profdata.cpp @@ -237,6 +237,7 @@ if (Remapper) I.Name = (*Remapper)(I.Name); const StringRef FuncName = I.Name; + bool Reported = false; WC->Writer.addRecord(std::move(I), Input.Weight, [&](Error E) { if (Reported) { @@ -633,13 +634,21 @@ Stats.ValueSitesHistogram.resize(NV, 0); Stats.ValueSitesHistogram[NV - 1]++; } + + uint64_t SiteSum = 0; + for (uint32_t V = 0; V < NV; V++) + SiteSum += VD[V].Count; + if (SiteSum == 0) + SiteSum = 1; + for (uint32_t V = 0; V < NV; V++) { - OS << "\t[ " << I << ", "; + OS << "\t[ " << format("%2u", I) << ", "; if (Symtab == nullptr) - OS << VD[V].Value; + OS << format("%4u", VD[V].Value); else OS << Symtab->getFuncName(VD[V].Value); - OS << ", " << VD[V].Count << " ]\n"; + OS << ", " << format("%10" PRId64, VD[V].Count) << " ] (" + << format("%6.2f%%", (VD[V].Count * 100.0 / SiteSum)) << ")\n"; } } } @@ -662,9 +671,9 @@ uint32_t TopN, bool ShowIndirectCallTargets, bool ShowMemOPSizes, bool ShowDetailedSummary, std::vector DetailedSummaryCutoffs, - bool ShowAllFunctions, - const std::string &ShowFunction, bool TextFormat, - raw_fd_ostream &OS) { + bool ShowAllFunctions, uint64_t ValueCutoff, + bool ListBelow, const std::string &ShowFunction, + bool TextFormat, raw_fd_ostream &OS) { auto ReaderOrErr = InstrProfReader::create(Filename); std::vector Cutoffs = std::move(DetailedSummaryCutoffs); if (ShowDetailedSummary && Cutoffs.empty()) { @@ -677,6 +686,7 @@ auto Reader = std::move(ReaderOrErr.get()); bool IsIRInstr = Reader->isIRLevelProfile(); size_t ShownFunctions = 0; + size_t BelowCutoffFunctions = 0; int NumVPKind = IPVK_Last - IPVK_First + 1; std::vector VPStats(NumVPKind); @@ -690,6 +700,11 @@ decltype(MinCmp)> HottestFuncs(MinCmp); + if (ListBelow) { + OS << "The list of functions with the maximum counter less than " + << ValueCutoff << ":\n"; + } + // Add marker so that IR-level instrumentation round-trips properly. if (TextFormat && IsIRInstr) OS << ":ir\n"; @@ -711,11 +726,24 @@ 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]); + uint64_t FuncMax = 0; + uint64_t FuncSum = 0; + for (size_t I = 0, E = Func.Counts.size(); I < E; ++I) { + FuncMax = std::max(FuncMax, Func.Counts[I]); + FuncSum += Func.Counts[I]; + } + if (FuncMax < ValueCutoff) { + ++BelowCutoffFunctions; + if (ListBelow) { + OS << " " << Func.Name << ": (Max = " << FuncMax + << " Sum = " << FuncSum << ")\n"; + } + continue; + } else if (ListBelow) + continue; + + if (TopN) { if (HottestFuncs.size() == TopN) { if (HottestFuncs.top().second < FuncMax) { HottestFuncs.pop(); @@ -726,7 +754,6 @@ } if (Show) { - if (!ShownFunctions) OS << "Counters:\n"; @@ -781,6 +808,12 @@ if (ShowAllFunctions || !ShowFunction.empty()) OS << "Functions shown: " << ShownFunctions << "\n"; OS << "Total functions: " << PS->getNumFunctions() << "\n"; + if (ValueCutoff > 0) { + OS << "Below Value Cutoff functions: " << BelowCutoffFunctions << "\n"; + OS << "Number of Functions with maximum Count (>= " << ValueCutoff + << "): " << PS->getNumFunctions() - BelowCutoffFunctions; + OS << ", and (< " << ValueCutoff << "): " << BelowCutoffFunctions << "\n"; + } OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n"; OS << "Maximum internal block count: " << PS->getMaxInternalCount() << "\n"; @@ -882,7 +915,14 @@ cl::opt TopNFunctions( "topn", cl::init(0), cl::desc("Show the list of functions with the largest internal counts")); - + cl::opt ValueCutoff( + "value-cutoff", cl::init(0), + cl::desc("Set the count value cutoff. Functions with the maximum count " + "less than this value will not be printed out. (Default is 0)")); + cl::opt ListBelow( + "list-below-cutoff", cl::init(false), + cl::desc("Print out the functions that with maximum count less than " + "ValueCutoff")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); if (OutputFilename.empty()) @@ -899,10 +939,10 @@ std::vector Cutoffs(DetailedSummaryCutoffs.begin(), DetailedSummaryCutoffs.end()); if (ProfileKind == instr) - return showInstrProfile(Filename, ShowCounts, TopNFunctions, - ShowIndirectCallTargets, ShowMemOPSizes, - ShowDetailedSummary, DetailedSummaryCutoffs, - ShowAllFunctions, ShowFunction, TextFormat, OS); + return showInstrProfile( + Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets, + ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs, + ShowAllFunctions, ValueCutoff, ListBelow, ShowFunction, TextFormat, OS); else return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, ShowFunction, OS);