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);  | 
