[llvm] [nfc][llvm-profdata]Refactor llvm-profdata show* code, by moving function-scope options to a show_llvmprofdata namespace (PR #71328)

Mingming Liu via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 7 22:03:39 PST 2023


https://github.com/minglotus-6 updated https://github.com/llvm/llvm-project/pull/71328

>From e9b590a65994c8e8a4bcd02859a9e7a17fd657b1 Mon Sep 17 00:00:00 2001
From: Mingming Liu <mingmingl at google.com>
Date: Tue, 7 Nov 2023 12:02:10 -0800
Subject: [PATCH 1/2] [nfc][llvm-profdata] Move show options to its namespace

---
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 252 ++++++++++-----------
 1 file changed, 115 insertions(+), 137 deletions(-)

diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index e7e7f8228d7d9c3..f8e6bf5dd9b99e5 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -2387,6 +2387,7 @@ static int overlap_main(int argc, const char *argv[]) {
   return 0;
 }
 
+namespace show_llvmprofdata {
 namespace {
 struct ValueSitesStats {
   ValueSitesStats()
@@ -2447,14 +2448,101 @@ static void showValueSitesStats(raw_fd_ostream &OS, uint32_t VK,
   }
 }
 
-static int showInstrProfile(
-    const std::string &Filename, bool ShowCounts, uint32_t TopN,
-    bool ShowIndirectCallTargets, bool ShowMemOPSizes, bool ShowDetailedSummary,
-    std::vector<uint32_t> DetailedSummaryCutoffs, bool ShowAllFunctions,
-    bool ShowCS, uint64_t ValueCutoff, bool OnlyListBelow,
-    const std::string &ShowFunction, bool TextFormat, bool ShowBinaryIds,
-    bool ShowCovered, bool ShowProfileVersion, bool ShowTemporalProfTraces,
-    ShowFormat SFormat, raw_fd_ostream &OS) {
+cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
+
+cl::opt<bool> ShowCounts("counts", cl::init(false),
+                         cl::desc("Show counter values for shown functions"));
+cl::opt<ShowFormat>
+    SFormat("show-format", cl::init(ShowFormat::Text),
+            cl::desc("Emit output in the selected format if supported"),
+            cl::values(clEnumValN(ShowFormat::Text, "text",
+                                  "emit normal text output (default)"),
+                       clEnumValN(ShowFormat::Json, "json", "emit JSON"),
+                       clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")));
+// TODO: Consider replacing this with `--show-format=text-encoding`.
+cl::opt<bool>
+    TextFormat("text", cl::init(false),
+               cl::desc("Show instr profile data in text dump format"));
+cl::opt<bool>
+    JsonFormat("json", cl::desc("Show sample profile data in the JSON format "
+                                "(deprecated, please use --show-format=json)"));
+cl::opt<bool> ShowIndirectCallTargets(
+    "ic-targets", cl::init(false),
+    cl::desc("Show indirect call site target values for shown functions"));
+cl::opt<bool> ShowMemOPSizes(
+    "memop-sizes", cl::init(false),
+    cl::desc("Show the profiled sizes of the memory intrinsic calls "
+             "for shown functions"));
+cl::opt<bool> ShowDetailedSummary("detailed-summary", cl::init(false),
+                                  cl::desc("Show detailed profile summary"));
+cl::list<uint32_t> DetailedSummaryCutoffs(
+    cl::CommaSeparated, "detailed-summary-cutoffs",
+    cl::desc(
+        "Cutoff percentages (times 10000) for generating detailed summary"),
+    cl::value_desc("800000,901000,999999"));
+cl::opt<bool> ShowHotFuncList(
+    "hot-func-list", cl::init(false),
+    cl::desc("Show profile summary of a list of hot functions"));
+cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
+                               cl::desc("Details for every function"));
+cl::opt<bool> ShowCS("showcs", cl::init(false),
+                     cl::desc("Show context sensitive counts"));
+cl::opt<std::string> ShowFunction("function",
+                                  cl::desc("Details for matching functions"));
+
+cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+                                    cl::init("-"), cl::desc("Output file"));
+cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
+                          cl::aliasopt(OutputFilename));
+cl::opt<ProfileKinds> ProfileKind(
+    cl::desc("Profile kind:"), cl::init(instr),
+    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
+               clEnumVal(sample, "Sample profile"),
+               clEnumVal(memory, "MemProf memory access profile")));
+cl::opt<uint32_t> TopNFunctions(
+    "topn", cl::init(0),
+    cl::desc("Show the list of functions with the largest internal counts"));
+cl::opt<uint32_t> 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<bool> OnlyListBelow(
+    "list-below-cutoff", cl::init(false),
+    cl::desc("Only output names of functions whose max count values are "
+             "below the cutoff value"));
+cl::opt<bool> ShowProfileSymbolList(
+    "show-prof-sym-list", cl::init(false),
+    cl::desc("Show profile symbol list if it exists in the profile. "));
+cl::opt<bool> ShowSectionInfoOnly(
+    "show-sec-info-only", cl::init(false),
+    cl::desc("Show the information of each section in the sample profile. "
+             "The flag is only usable when the sample profile is in "
+             "extbinary format"));
+cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
+                            cl::desc("Show binary ids in the profile. "));
+cl::opt<bool> ShowTemporalProfTraces(
+    "temporal-profile-traces",
+    cl::desc("Show temporal profile traces in the profile."));
+cl::opt<std::string> DebugInfoFilename(
+    "debug-info", cl::init(""),
+    cl::desc("Read and extract profile metadata from debug info and show "
+             "the functions it found."));
+cl::opt<unsigned> MaxDbgCorrelationWarnings(
+    "max-debug-info-correlation-warnings",
+    cl::desc("The maximum number of warnings to emit when correlating "
+             "profile from debug info (0 = no limit)"),
+    cl::init(5));
+cl::opt<bool>
+    ShowCovered("covered", cl::init(false),
+                cl::desc("Show only the functions that have been executed."));
+cl::opt<std::string> ProfiledBinary(
+    "profiled-binary", cl::init(""),
+    cl::desc("Path to binary from which the profile was collected."));
+cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
+                                 cl::desc("Show profile version. "));
+
+static int showInstrProfile(const std::string &Filename, ShowFormat SFormat,
+                            raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for instr profiles");
   if (SFormat == ShowFormat::Yaml)
@@ -2559,8 +2647,8 @@ static int showInstrProfile(
     } else if (OnlyListBelow)
       continue;
 
-    if (TopN) {
-      if (HottestFuncs.size() == TopN) {
+    if (TopNFunctions) {
+      if (HottestFuncs.size() == TopNFunctions) {
         if (HottestFuncs.top().second < FuncMax) {
           HottestFuncs.pop();
           HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax));
@@ -2636,13 +2724,13 @@ static int showInstrProfile(
   OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n";
   OS << "Maximum internal block count: " << PS->getMaxInternalCount() << "\n";
 
-  if (TopN) {
+  if (TopNFunctions) {
     std::vector<std::pair<std::string, uint64_t>> SortedHottestFuncs;
     while (!HottestFuncs.empty()) {
       SortedHottestFuncs.emplace_back(HottestFuncs.top());
       HottestFuncs.pop();
     }
-    OS << "Top " << TopN
+    OS << "Top " << TopNFunctions
        << " functions with the largest internal block counts: \n";
     for (auto &hotfunc : llvm::reverse(SortedHottestFuncs))
       OS << "  " << hotfunc.first << ", max count = " << hotfunc.second << "\n";
@@ -2832,13 +2920,8 @@ static int showHotFunctionList(const sampleprof::SampleProfileMap &Profiles,
   return 0;
 }
 
-static int showSampleProfile(const std::string &Filename, bool ShowCounts,
-                             uint32_t TopN, bool ShowAllFunctions,
-                             bool ShowDetailedSummary,
-                             const std::string &ShowFunction,
-                             bool ShowProfileSymbolList,
-                             bool ShowSectionInfoOnly, bool ShowHotFuncList,
-                             ShowFormat SFormat, raw_fd_ostream &OS) {
+static int showSampleProfile(const std::string &Filename, ShowFormat SFormat,
+                             raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Yaml)
     exitWithError("YAML output is not supported for sample profiles");
   using namespace sampleprof;
@@ -2886,15 +2969,14 @@ static int showSampleProfile(const std::string &Filename, bool ShowCounts,
     PS.printDetailedSummary(OS);
   }
 
-  if (ShowHotFuncList || TopN)
-    showHotFunctionList(Reader->getProfiles(), Reader->getSummary(), TopN, OS);
+  if (ShowHotFuncList || TopNFunctions)
+    showHotFunctionList(Reader->getProfiles(), Reader->getSummary(),
+                        TopNFunctions, OS);
 
   return 0;
 }
 
-static int showMemProfProfile(const std::string &Filename,
-                              const std::string &ProfiledBinary,
-                              ShowFormat SFormat, raw_fd_ostream &OS) {
+static int showMemProfProfile(const std::string &Filename, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for MemProf");
   auto ReaderOr = llvm::memprof::RawMemProfReader::create(
@@ -2913,10 +2995,7 @@ static int showMemProfProfile(const std::string &Filename,
 }
 
 static int showDebugInfoCorrelation(const std::string &Filename,
-                                    bool ShowDetailedSummary,
-                                    bool ShowProfileSymbolList,
-                                    int MaxDbgCorrelationWarnings,
-                                    ShowFormat SFormat, raw_fd_ostream &OS) {
+                                    raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for debug info correlation");
   std::unique_ptr<InstrProfCorrelator> Correlator;
@@ -2950,101 +3029,8 @@ static int showDebugInfoCorrelation(const std::string &Filename,
   return 0;
 }
 
-static int show_main(int argc, const char *argv[]) {
-  cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
-
-  cl::opt<bool> ShowCounts("counts", cl::init(false),
-                           cl::desc("Show counter values for shown functions"));
-  cl::opt<ShowFormat> SFormat(
-      "show-format", cl::init(ShowFormat::Text),
-      cl::desc("Emit output in the selected format if supported"),
-      cl::values(clEnumValN(ShowFormat::Text, "text",
-                            "emit normal text output (default)"),
-                 clEnumValN(ShowFormat::Json, "json", "emit JSON"),
-                 clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")));
-  // TODO: Consider replacing this with `--show-format=text-encoding`.
-  cl::opt<bool> TextFormat(
-      "text", cl::init(false),
-      cl::desc("Show instr profile data in text dump format"));
-  cl::opt<bool> JsonFormat(
-      "json", cl::desc("Show sample profile data in the JSON format "
-                       "(deprecated, please use --show-format=json)"));
-  cl::opt<bool> ShowIndirectCallTargets(
-      "ic-targets", cl::init(false),
-      cl::desc("Show indirect call site target values for shown functions"));
-  cl::opt<bool> ShowMemOPSizes(
-      "memop-sizes", cl::init(false),
-      cl::desc("Show the profiled sizes of the memory intrinsic calls "
-               "for shown functions"));
-  cl::opt<bool> ShowDetailedSummary("detailed-summary", cl::init(false),
-                                    cl::desc("Show detailed profile summary"));
-  cl::list<uint32_t> DetailedSummaryCutoffs(
-      cl::CommaSeparated, "detailed-summary-cutoffs",
-      cl::desc(
-          "Cutoff percentages (times 10000) for generating detailed summary"),
-      cl::value_desc("800000,901000,999999"));
-  cl::opt<bool> ShowHotFuncList(
-      "hot-func-list", cl::init(false),
-      cl::desc("Show profile summary of a list of hot functions"));
-  cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
-                                 cl::desc("Details for every function"));
-  cl::opt<bool> ShowCS("showcs", cl::init(false),
-                       cl::desc("Show context sensitive counts"));
-  cl::opt<std::string> ShowFunction("function",
-                                    cl::desc("Details for matching functions"));
-
-  cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                      cl::init("-"), cl::desc("Output file"));
-  cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
-                            cl::aliasopt(OutputFilename));
-  cl::opt<ProfileKinds> ProfileKind(
-      cl::desc("Profile kind:"), cl::init(instr),
-      cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
-                 clEnumVal(sample, "Sample profile"),
-                 clEnumVal(memory, "MemProf memory access profile")));
-  cl::opt<uint32_t> TopNFunctions(
-      "topn", cl::init(0),
-      cl::desc("Show the list of functions with the largest internal counts"));
-  cl::opt<uint32_t> 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<bool> OnlyListBelow(
-      "list-below-cutoff", cl::init(false),
-      cl::desc("Only output names of functions whose max count values are "
-               "below the cutoff value"));
-  cl::opt<bool> ShowProfileSymbolList(
-      "show-prof-sym-list", cl::init(false),
-      cl::desc("Show profile symbol list if it exists in the profile. "));
-  cl::opt<bool> ShowSectionInfoOnly(
-      "show-sec-info-only", cl::init(false),
-      cl::desc("Show the information of each section in the sample profile. "
-               "The flag is only usable when the sample profile is in "
-               "extbinary format"));
-  cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
-                              cl::desc("Show binary ids in the profile. "));
-  cl::opt<bool> ShowTemporalProfTraces(
-      "temporal-profile-traces",
-      cl::desc("Show temporal profile traces in the profile."));
-  cl::opt<std::string> DebugInfoFilename(
-      "debug-info", cl::init(""),
-      cl::desc("Read and extract profile metadata from debug info and show "
-               "the functions it found."));
-  cl::opt<unsigned> MaxDbgCorrelationWarnings(
-      "max-debug-info-correlation-warnings",
-      cl::desc("The maximum number of warnings to emit when correlating "
-               "profile from debug info (0 = no limit)"),
-      cl::init(5));
-  cl::opt<bool> ShowCovered(
-      "covered", cl::init(false),
-      cl::desc("Show only the functions that have been executed."));
-  cl::opt<std::string> ProfiledBinary(
-      "profiled-binary", cl::init(""),
-      cl::desc("Path to binary from which the profile was collected."));
-  cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
-                                   cl::desc("Show profile version. "));
+static int main(int argc, const char *argv[]) {
   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
-
   if (Filename.empty() && DebugInfoFilename.empty())
     exitWithError(
         "the positional argument '<profdata-file>' is required unless '--" +
@@ -3067,25 +3053,17 @@ static int show_main(int argc, const char *argv[]) {
     WithColor::warning() << "-function argument ignored: showing all functions\n";
 
   if (!DebugInfoFilename.empty())
-    return showDebugInfoCorrelation(DebugInfoFilename, ShowDetailedSummary,
-                                    ShowProfileSymbolList,
-                                    MaxDbgCorrelationWarnings, SFormat, OS);
+    return showDebugInfoCorrelation(DebugInfoFilename, OS);
 
   if (ProfileKind == instr)
-    return showInstrProfile(
-        Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets,
-        ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs,
-        ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction,
-        TextFormat, ShowBinaryIds, ShowCovered, ShowProfileVersion,
-        ShowTemporalProfTraces, SFormat, OS);
+    return showInstrProfile(Filename, SFormat, OS);
   if (ProfileKind == sample)
-    return showSampleProfile(Filename, ShowCounts, TopNFunctions,
-                             ShowAllFunctions, ShowDetailedSummary,
-                             ShowFunction, ShowProfileSymbolList,
-                             ShowSectionInfoOnly, ShowHotFuncList, SFormat, OS);
-  return showMemProfProfile(Filename, ProfiledBinary, SFormat, OS);
+    return showSampleProfile(Filename, SFormat, OS);
+  return showMemProfProfile(Filename, SFormat, OS);
 }
 
+} // namespace show_llvmprofdata
+
 static int order_main(int argc, const char *argv[]) {
   cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
   cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
@@ -3130,7 +3108,7 @@ typedef int (*llvm_profdata_subcommand)(int, const char *[]);
 static std::tuple<StringRef, llvm_profdata_subcommand>
     llvm_profdata_subcommands[] = {
         {"merge", merge_main},
-        {"show", show_main},
+        {"show", show_llvmprofdata::main},
         {"order", order_main},
         {"overlap", overlap_main},
 };

>From 02a0de693395c5de06678acf54d52b9e3af2477c Mon Sep 17 00:00:00 2001
From: Mingming Liu <mingmingl at google.com>
Date: Tue, 7 Nov 2023 17:52:18 -0800
Subject: [PATCH 2/2] Add show_options namespace and move show_options from
 function scope to namespace. - The change uses cl::SubCommand feature that
 allow to register options   under a subcommand.   - Without using
 cl::SubCommand, the options in the show name namespace will     take a
 registered name as global variables, causing runtime errors when a    
 function-scope static option tries to add a function of a same name.   - Make
 changes in the CommandLine library accordingly.

---
 llvm/include/llvm/Support/CommandLine.h    |   2 +-
 llvm/lib/Support/CommandLine.cpp           |   7 +
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 293 +++++++++++++--------
 3 files changed, 185 insertions(+), 117 deletions(-)

diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index 58ef176551b6852..ab62607b2a307e5 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -481,7 +481,7 @@ struct sub {
 
   sub(SubCommand &S) : Sub(S) {}
 
-  template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
+  void apply(Option &O) const { O.addSubCommand(Sub); }
 };
 
 // Specify a callback function to be called when an option is seen.
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 55633d7cafa4791..a7e0cae8b855d7c 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -1667,6 +1667,13 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
       Handler = LookupLongOption(*ChosenSubCommand, ArgName, Value,
                                  LongOptionsUseDoubleDash, HaveDoubleDash);
 
+      // If Handler is not found in a specialized subcommand, look up handler
+      // in the top-level subcommand.
+      // cl::opt without cl::sub belongs to top-level subcommand.
+      if (!Handler && ChosenSubCommand != &SubCommand::getTopLevel())
+        Handler = LookupLongOption(SubCommand::getTopLevel(), ArgName, Value,
+                                   LongOptionsUseDoubleDash, HaveDoubleDash);
+
       // Check to see if this "option" is really a prefixed or grouped argument.
       if (!Handler && !(LongOptionsUseDoubleDash && HaveDoubleDash))
         Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing,
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index f8e6bf5dd9b99e5..fd00798b8bc959e 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -47,6 +47,8 @@
 
 using namespace llvm;
 
+cl::SubCommand ShowSubcommand("show", "show profile data");
+
 // We use this string to indicate that there are
 // multiple static functions map to the same name.
 const std::string DuplicateNameStr = "----";
@@ -2387,7 +2389,6 @@ static int overlap_main(int argc, const char *argv[]) {
   return 0;
 }
 
-namespace show_llvmprofdata {
 namespace {
 struct ValueSitesStats {
   ValueSitesStats()
@@ -2448,101 +2449,14 @@ static void showValueSitesStats(raw_fd_ostream &OS, uint32_t VK,
   }
 }
 
-cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
-
-cl::opt<bool> ShowCounts("counts", cl::init(false),
-                         cl::desc("Show counter values for shown functions"));
-cl::opt<ShowFormat>
-    SFormat("show-format", cl::init(ShowFormat::Text),
-            cl::desc("Emit output in the selected format if supported"),
-            cl::values(clEnumValN(ShowFormat::Text, "text",
-                                  "emit normal text output (default)"),
-                       clEnumValN(ShowFormat::Json, "json", "emit JSON"),
-                       clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")));
-// TODO: Consider replacing this with `--show-format=text-encoding`.
-cl::opt<bool>
-    TextFormat("text", cl::init(false),
-               cl::desc("Show instr profile data in text dump format"));
-cl::opt<bool>
-    JsonFormat("json", cl::desc("Show sample profile data in the JSON format "
-                                "(deprecated, please use --show-format=json)"));
-cl::opt<bool> ShowIndirectCallTargets(
-    "ic-targets", cl::init(false),
-    cl::desc("Show indirect call site target values for shown functions"));
-cl::opt<bool> ShowMemOPSizes(
-    "memop-sizes", cl::init(false),
-    cl::desc("Show the profiled sizes of the memory intrinsic calls "
-             "for shown functions"));
-cl::opt<bool> ShowDetailedSummary("detailed-summary", cl::init(false),
-                                  cl::desc("Show detailed profile summary"));
-cl::list<uint32_t> DetailedSummaryCutoffs(
-    cl::CommaSeparated, "detailed-summary-cutoffs",
-    cl::desc(
-        "Cutoff percentages (times 10000) for generating detailed summary"),
-    cl::value_desc("800000,901000,999999"));
-cl::opt<bool> ShowHotFuncList(
-    "hot-func-list", cl::init(false),
-    cl::desc("Show profile summary of a list of hot functions"));
-cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
-                               cl::desc("Details for every function"));
-cl::opt<bool> ShowCS("showcs", cl::init(false),
-                     cl::desc("Show context sensitive counts"));
-cl::opt<std::string> ShowFunction("function",
-                                  cl::desc("Details for matching functions"));
-
-cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                    cl::init("-"), cl::desc("Output file"));
-cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
-                          cl::aliasopt(OutputFilename));
-cl::opt<ProfileKinds> ProfileKind(
-    cl::desc("Profile kind:"), cl::init(instr),
-    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
-               clEnumVal(sample, "Sample profile"),
-               clEnumVal(memory, "MemProf memory access profile")));
-cl::opt<uint32_t> TopNFunctions(
-    "topn", cl::init(0),
-    cl::desc("Show the list of functions with the largest internal counts"));
-cl::opt<uint32_t> 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<bool> OnlyListBelow(
-    "list-below-cutoff", cl::init(false),
-    cl::desc("Only output names of functions whose max count values are "
-             "below the cutoff value"));
-cl::opt<bool> ShowProfileSymbolList(
-    "show-prof-sym-list", cl::init(false),
-    cl::desc("Show profile symbol list if it exists in the profile. "));
-cl::opt<bool> ShowSectionInfoOnly(
-    "show-sec-info-only", cl::init(false),
-    cl::desc("Show the information of each section in the sample profile. "
-             "The flag is only usable when the sample profile is in "
-             "extbinary format"));
-cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
-                            cl::desc("Show binary ids in the profile. "));
-cl::opt<bool> ShowTemporalProfTraces(
-    "temporal-profile-traces",
-    cl::desc("Show temporal profile traces in the profile."));
-cl::opt<std::string> DebugInfoFilename(
-    "debug-info", cl::init(""),
-    cl::desc("Read and extract profile metadata from debug info and show "
-             "the functions it found."));
-cl::opt<unsigned> MaxDbgCorrelationWarnings(
-    "max-debug-info-correlation-warnings",
-    cl::desc("The maximum number of warnings to emit when correlating "
-             "profile from debug info (0 = no limit)"),
-    cl::init(5));
-cl::opt<bool>
-    ShowCovered("covered", cl::init(false),
-                cl::desc("Show only the functions that have been executed."));
-cl::opt<std::string> ProfiledBinary(
-    "profiled-binary", cl::init(""),
-    cl::desc("Path to binary from which the profile was collected."));
-cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
-                                 cl::desc("Show profile version. "));
-
-static int showInstrProfile(const std::string &Filename, ShowFormat SFormat,
-                            raw_fd_ostream &OS) {
+static int showInstrProfile(
+    const std::string &Filename, bool ShowCounts, uint32_t TopN,
+    bool ShowIndirectCallTargets, bool ShowMemOPSizes, bool ShowDetailedSummary,
+    std::vector<uint32_t> DetailedSummaryCutoffs, bool ShowAllFunctions,
+    bool ShowCS, uint64_t ValueCutoff, bool OnlyListBelow,
+    const std::string &ShowFunction, bool TextFormat, bool ShowBinaryIds,
+    bool ShowCovered, bool ShowProfileVersion, bool ShowTemporalProfTraces,
+    ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for instr profiles");
   if (SFormat == ShowFormat::Yaml)
@@ -2647,8 +2561,8 @@ static int showInstrProfile(const std::string &Filename, ShowFormat SFormat,
     } else if (OnlyListBelow)
       continue;
 
-    if (TopNFunctions) {
-      if (HottestFuncs.size() == TopNFunctions) {
+    if (TopN) {
+      if (HottestFuncs.size() == TopN) {
         if (HottestFuncs.top().second < FuncMax) {
           HottestFuncs.pop();
           HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax));
@@ -2724,13 +2638,13 @@ static int showInstrProfile(const std::string &Filename, ShowFormat SFormat,
   OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n";
   OS << "Maximum internal block count: " << PS->getMaxInternalCount() << "\n";
 
-  if (TopNFunctions) {
+  if (TopN) {
     std::vector<std::pair<std::string, uint64_t>> SortedHottestFuncs;
     while (!HottestFuncs.empty()) {
       SortedHottestFuncs.emplace_back(HottestFuncs.top());
       HottestFuncs.pop();
     }
-    OS << "Top " << TopNFunctions
+    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";
@@ -2920,8 +2834,13 @@ static int showHotFunctionList(const sampleprof::SampleProfileMap &Profiles,
   return 0;
 }
 
-static int showSampleProfile(const std::string &Filename, ShowFormat SFormat,
-                             raw_fd_ostream &OS) {
+static int showSampleProfile(const std::string &Filename, bool ShowCounts,
+                             uint32_t TopN, bool ShowAllFunctions,
+                             bool ShowDetailedSummary,
+                             const std::string &ShowFunction,
+                             bool ShowProfileSymbolList,
+                             bool ShowSectionInfoOnly, bool ShowHotFuncList,
+                             ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Yaml)
     exitWithError("YAML output is not supported for sample profiles");
   using namespace sampleprof;
@@ -2969,14 +2888,15 @@ static int showSampleProfile(const std::string &Filename, ShowFormat SFormat,
     PS.printDetailedSummary(OS);
   }
 
-  if (ShowHotFuncList || TopNFunctions)
-    showHotFunctionList(Reader->getProfiles(), Reader->getSummary(),
-                        TopNFunctions, OS);
+  if (ShowHotFuncList || TopN)
+    showHotFunctionList(Reader->getProfiles(), Reader->getSummary(), TopN, OS);
 
   return 0;
 }
 
-static int showMemProfProfile(const std::string &Filename, raw_fd_ostream &OS) {
+static int showMemProfProfile(const std::string &Filename,
+                              const std::string &ProfiledBinary,
+                              ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for MemProf");
   auto ReaderOr = llvm::memprof::RawMemProfReader::create(
@@ -2995,7 +2915,10 @@ static int showMemProfProfile(const std::string &Filename, raw_fd_ostream &OS) {
 }
 
 static int showDebugInfoCorrelation(const std::string &Filename,
-                                    raw_fd_ostream &OS) {
+                                    bool ShowDetailedSummary,
+                                    bool ShowProfileSymbolList,
+                                    int MaxDbgCorrelationWarnings,
+                                    ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for debug info correlation");
   std::unique_ptr<InstrProfCorrelator> Correlator;
@@ -3029,15 +2952,139 @@ static int showDebugInfoCorrelation(const std::string &Filename,
   return 0;
 }
 
-static int main(int argc, const char *argv[]) {
+namespace show_options {
+cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"),
+                              cl::sub(ShowSubcommand));
+
+cl::opt<bool> ShowCounts("counts", cl::init(false),
+                         cl::desc("Show counter values for shown functions"),
+                         cl::sub(ShowSubcommand));
+cl::opt<ShowFormat>
+    SFormat("show-format", cl::init(ShowFormat::Text),
+            cl::desc("Emit output in the selected format if supported"),
+            cl::values(clEnumValN(ShowFormat::Text, "text",
+                                  "emit normal text output (default)"),
+                       clEnumValN(ShowFormat::Json, "json", "emit JSON"),
+                       clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")),
+            cl::sub(ShowSubcommand));
+// TODO: Consider replacing this with `--show-format=text-encoding`.
+cl::opt<bool>
+    TextFormat("text", cl::init(false),
+               cl::desc("Show instr profile data in text dump format"),
+               cl::sub(ShowSubcommand));
+cl::opt<bool>
+    JsonFormat("json",
+               cl::desc("Show sample profile data in the JSON format "
+                        "(deprecated, please use --show-format=json)"),
+               cl::sub(ShowSubcommand));
+cl::opt<bool> ShowIndirectCallTargets(
+    "ic-targets", cl::init(false),
+    cl::desc("Show indirect call site target values for shown functions"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowMemOPSizes(
+    "memop-sizes", cl::init(false),
+    cl::desc("Show the profiled sizes of the memory intrinsic calls "
+             "for shown functions"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowDetailedSummary("detailed-summary", cl::init(false),
+                                  cl::desc("Show detailed profile summary"),
+                                  cl::sub(ShowSubcommand));
+cl::list<uint32_t> DetailedSummaryCutoffs(
+    cl::CommaSeparated, "detailed-summary-cutoffs",
+    cl::desc(
+        "Cutoff percentages (times 10000) for generating detailed summary"),
+    cl::value_desc("800000,901000,999999"), cl::sub(ShowSubcommand));
+cl::opt<bool>
+    ShowHotFuncList("hot-func-list", cl::init(false),
+                    cl::desc("Show profile summary of a list of hot functions"),
+                    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
+                               cl::desc("Details for each and every function"),
+                               cl::sub(ShowSubcommand));
+cl::opt<bool> ShowCS("showcs", cl::init(false),
+                     cl::desc("Show context sensitive counts"),
+                     cl::sub(ShowSubcommand));
+cl::opt<std::string> ShowFunction("function",
+                                  cl::desc("Details for matching functions"),
+                                  cl::sub(ShowSubcommand));
+
+cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+                                    cl::init("-"), cl::desc("Output file"),
+                                    cl::sub(ShowSubcommand));
+// NOTE: cl::alias must not have cl::sub(), since aliased option's cl::sub()
+// will be used. llvm::cl::alias::done() method asserts this condition.
+cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
+                          cl::aliasopt(OutputFilename));
+cl::opt<ProfileKinds> ProfileKind(
+    cl::desc("Profile kind:"), cl::sub(ShowSubcommand), cl::init(instr),
+    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
+               clEnumVal(sample, "Sample profile"),
+               clEnumVal(memory, "MemProf memory access profile")));
+cl::opt<uint32_t> TopNFunctions(
+    "topn", cl::init(0),
+    cl::desc("Show the list of functions with the largest internal counts"),
+    cl::sub(ShowSubcommand));
+cl::opt<uint32_t> 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::sub(ShowSubcommand));
+cl::opt<bool> OnlyListBelow(
+    "list-below-cutoff", cl::init(false),
+    cl::desc("Only output names of functions whose max count values are "
+             "below the cutoff value"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowProfileSymbolList(
+    "show-prof-sym-list", cl::init(false),
+    cl::desc("Show profile symbol list if it exists in the profile. "),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowSectionInfoOnly(
+    "show-sec-info-only", cl::init(false),
+    cl::desc("Show the information of each section in the sample profile. "
+             "The flag is only usable when the sample profile is in "
+             "extbinary format"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
+                            cl::desc("Show binary ids in the profile. "),
+                            cl::sub(ShowSubcommand));
+cl::opt<bool> ShowTemporalProfTraces(
+    "temporal-profile-traces",
+    cl::desc("Show temporal profile traces in the profile."),
+    cl::sub(ShowSubcommand));
+cl::opt<std::string> DebugInfoFilename(
+    "debug-info", cl::init(""),
+    cl::desc("Read and extract profile metadata from debug info and show "
+             "the functions it found."),
+    cl::sub(ShowSubcommand));
+cl::opt<unsigned> MaxDbgCorrelationWarnings(
+    "max-debug-info-correlation-warnings",
+    cl::desc("The maximum number of warnings to emit when correlating "
+             "profile from debug info (0 = no limit)"),
+    cl::init(5), cl::sub(ShowSubcommand));
+cl::opt<bool>
+    ShowCovered("covered", cl::init(false),
+                cl::desc("Show only the functions that have been executed."),
+                cl::sub(ShowSubcommand));
+cl::opt<std::string> ProfiledBinary(
+    "profiled-binary", cl::init(""),
+    cl::desc("Path to binary from which the profile was collected."),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
+                                 cl::desc("Show profile version. "),
+                                 cl::sub(ShowSubcommand));
+} // namespace show_options
+
+static int show_main(int argc, const char *argv[]) {
+  using namespace show_options;
   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
+
   if (Filename.empty() && DebugInfoFilename.empty())
     exitWithError(
         "the positional argument '<profdata-file>' is required unless '--" +
         DebugInfoFilename.ArgStr + "' is provided");
 
   if (Filename == OutputFilename) {
-    errs() << sys::path::filename(argv[0])
+    errs() << sys::path::filename(argv[0]) << " " << argv[1]
            << ": Input file name cannot be the same as the output file name!\n";
     return 1;
   }
@@ -3053,17 +3100,25 @@ static int main(int argc, const char *argv[]) {
     WithColor::warning() << "-function argument ignored: showing all functions\n";
 
   if (!DebugInfoFilename.empty())
-    return showDebugInfoCorrelation(DebugInfoFilename, OS);
+    return showDebugInfoCorrelation(DebugInfoFilename, ShowDetailedSummary,
+                                    ShowProfileSymbolList,
+                                    MaxDbgCorrelationWarnings, SFormat, OS);
 
   if (ProfileKind == instr)
-    return showInstrProfile(Filename, SFormat, OS);
+    return showInstrProfile(
+        Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets,
+        ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs,
+        ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction,
+        TextFormat, ShowBinaryIds, ShowCovered, ShowProfileVersion,
+        ShowTemporalProfTraces, SFormat, OS);
   if (ProfileKind == sample)
-    return showSampleProfile(Filename, SFormat, OS);
-  return showMemProfProfile(Filename, SFormat, OS);
+    return showSampleProfile(Filename, ShowCounts, TopNFunctions,
+                             ShowAllFunctions, ShowDetailedSummary,
+                             ShowFunction, ShowProfileSymbolList,
+                             ShowSectionInfoOnly, ShowHotFuncList, SFormat, OS);
+  return showMemProfProfile(Filename, ProfiledBinary, SFormat, OS);
 }
 
-} // namespace show_llvmprofdata
-
 static int order_main(int argc, const char *argv[]) {
   cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
   cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
@@ -3108,7 +3163,6 @@ typedef int (*llvm_profdata_subcommand)(int, const char *[]);
 static std::tuple<StringRef, llvm_profdata_subcommand>
     llvm_profdata_subcommands[] = {
         {"merge", merge_main},
-        {"show", show_llvmprofdata::main},
         {"order", order_main},
         {"overlap", overlap_main},
 };
@@ -3132,6 +3186,13 @@ int llvm_profdata_main(int argc, char **argvNonConst,
       return func(argc - 1, argv + 1);
     }
 
+    // "show" subcommand and its options uses the subcommands supported by
+    // llvm::cl. See this post
+    // (https://lists.llvm.org/pipermail/llvm-dev/2016-June/101804.html) for
+    // a brief introduction.
+    if (strcmp(argv[1], "show") == 0)
+      return show_main(argc, argv);
+
     if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 ||
         strcmp(argv[1], "--help") == 0) {
 



More information about the llvm-commits mailing list