Home | History | Annotate | Download | only in llvm-profdata
      1 //===- llvm-profdata.cpp - LLVM profile data tool -------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // llvm-profdata merges .profdata files.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/ADT/StringRef.h"
     15 #include "llvm/ProfileData/InstrProfReader.h"
     16 #include "llvm/ProfileData/InstrProfWriter.h"
     17 #include "llvm/Support/CommandLine.h"
     18 #include "llvm/Support/FileSystem.h"
     19 #include "llvm/Support/Format.h"
     20 #include "llvm/Support/ManagedStatic.h"
     21 #include "llvm/Support/MemoryBuffer.h"
     22 #include "llvm/Support/PrettyStackTrace.h"
     23 #include "llvm/Support/Signals.h"
     24 #include "llvm/Support/raw_ostream.h"
     25 
     26 using namespace llvm;
     27 
     28 static void exitWithError(const Twine &Message, StringRef Whence = "") {
     29   errs() << "error: ";
     30   if (!Whence.empty())
     31     errs() << Whence << ": ";
     32   errs() << Message << "\n";
     33   ::exit(1);
     34 }
     35 
     36 int merge_main(int argc, const char *argv[]) {
     37   cl::list<std::string> Inputs(cl::Positional, cl::Required, cl::OneOrMore,
     38                                cl::desc("<filenames...>"));
     39 
     40   cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
     41                                       cl::init("-"),
     42                                       cl::desc("Output file"));
     43   cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), cl::Required,
     44                             cl::aliasopt(OutputFilename));
     45 
     46   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
     47 
     48   if (OutputFilename.compare("-") == 0)
     49     exitWithError("Cannot write indexed profdata format to stdout.");
     50 
     51   std::string ErrorInfo;
     52   raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_None);
     53   if (!ErrorInfo.empty())
     54     exitWithError(ErrorInfo, OutputFilename);
     55 
     56   InstrProfWriter Writer;
     57   for (const auto &Filename : Inputs) {
     58     std::unique_ptr<InstrProfReader> Reader;
     59     if (std::error_code ec = InstrProfReader::create(Filename, Reader))
     60       exitWithError(ec.message(), Filename);
     61 
     62     for (const auto &I : *Reader)
     63       if (std::error_code EC =
     64               Writer.addFunctionCounts(I.Name, I.Hash, I.Counts))
     65         errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n";
     66     if (Reader->hasError())
     67       exitWithError(Reader->getError().message(), Filename);
     68   }
     69   Writer.write(Output);
     70 
     71   return 0;
     72 }
     73 
     74 int show_main(int argc, const char *argv[]) {
     75   cl::opt<std::string> Filename(cl::Positional, cl::Required,
     76                                 cl::desc("<profdata-file>"));
     77 
     78   cl::opt<bool> ShowCounts("counts", cl::init(false),
     79                            cl::desc("Show counter values for shown functions"));
     80   cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
     81                                  cl::desc("Details for every function"));
     82   cl::opt<std::string> ShowFunction("function",
     83                                     cl::desc("Details for matching functions"));
     84 
     85   cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
     86                                       cl::init("-"),
     87                                       cl::desc("Output file"));
     88   cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
     89                             cl::aliasopt(OutputFilename));
     90 
     91   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
     92 
     93   std::unique_ptr<InstrProfReader> Reader;
     94   if (std::error_code EC = InstrProfReader::create(Filename, Reader))
     95     exitWithError(EC.message(), Filename);
     96 
     97   if (OutputFilename.empty())
     98     OutputFilename = "-";
     99 
    100   std::string ErrorInfo;
    101   raw_fd_ostream OS(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
    102   if (!ErrorInfo.empty())
    103     exitWithError(ErrorInfo, OutputFilename);
    104 
    105   if (ShowAllFunctions && !ShowFunction.empty())
    106     errs() << "warning: -function argument ignored: showing all functions\n";
    107 
    108   uint64_t MaxFunctionCount = 0, MaxBlockCount = 0;
    109   size_t ShownFunctions = 0, TotalFunctions = 0;
    110   for (const auto &Func : *Reader) {
    111     bool Show = ShowAllFunctions ||
    112                 (!ShowFunction.empty() &&
    113                  Func.Name.find(ShowFunction) != Func.Name.npos);
    114 
    115     ++TotalFunctions;
    116     assert(Func.Counts.size() > 0 && "function missing entry counter");
    117     if (Func.Counts[0] > MaxFunctionCount)
    118       MaxFunctionCount = Func.Counts[0];
    119 
    120     if (Show) {
    121       if (!ShownFunctions)
    122         OS << "Counters:\n";
    123       ++ShownFunctions;
    124 
    125       OS << "  " << Func.Name << ":\n"
    126          << "    Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
    127          << "    Counters: " << Func.Counts.size() << "\n"
    128          << "    Function count: " << Func.Counts[0] << "\n";
    129     }
    130 
    131     if (Show && ShowCounts)
    132       OS << "    Block counts: [";
    133     for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
    134       if (Func.Counts[I] > MaxBlockCount)
    135         MaxBlockCount = Func.Counts[I];
    136       if (Show && ShowCounts)
    137         OS << (I == 1 ? "" : ", ") << Func.Counts[I];
    138     }
    139     if (Show && ShowCounts)
    140       OS << "]\n";
    141   }
    142   if (Reader->hasError())
    143     exitWithError(Reader->getError().message(), Filename);
    144 
    145   if (ShowAllFunctions || !ShowFunction.empty())
    146     OS << "Functions shown: " << ShownFunctions << "\n";
    147   OS << "Total functions: " << TotalFunctions << "\n";
    148   OS << "Maximum function count: " << MaxFunctionCount << "\n";
    149   OS << "Maximum internal block count: " << MaxBlockCount << "\n";
    150   return 0;
    151 }
    152 
    153 int main(int argc, const char *argv[]) {
    154   // Print a stack trace if we signal out.
    155   sys::PrintStackTraceOnErrorSignal();
    156   PrettyStackTraceProgram X(argc, argv);
    157   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
    158 
    159   StringRef ProgName(sys::path::filename(argv[0]));
    160   if (argc > 1) {
    161     int (*func)(int, const char *[]) = nullptr;
    162 
    163     if (strcmp(argv[1], "merge") == 0)
    164       func = merge_main;
    165     else if (strcmp(argv[1], "show") == 0)
    166       func = show_main;
    167 
    168     if (func) {
    169       std::string Invocation(ProgName.str() + " " + argv[1]);
    170       argv[1] = Invocation.c_str();
    171       return func(argc - 1, argv + 1);
    172     }
    173 
    174     if (strcmp(argv[1], "-h") == 0 ||
    175         strcmp(argv[1], "-help") == 0 ||
    176         strcmp(argv[1], "--help") == 0) {
    177 
    178       errs() << "OVERVIEW: LLVM profile data tools\n\n"
    179              << "USAGE: " << ProgName << " <command> [args...]\n"
    180              << "USAGE: " << ProgName << " <command> -help\n\n"
    181              << "Available commands: merge, show\n";
    182       return 0;
    183     }
    184   }
    185 
    186   if (argc < 2)
    187     errs() << ProgName << ": No command specified!\n";
    188   else
    189     errs() << ProgName << ": Unknown command!\n";
    190 
    191   errs() << "USAGE: " << ProgName << " <merge|show> [args...]\n";
    192   return 1;
    193 }
    194