summaryrefslogtreecommitdiff
path: root/tools/llvm-profdata/llvm-profdata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-profdata/llvm-profdata.cpp')
-rw-r--r--tools/llvm-profdata/llvm-profdata.cpp74
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);