[llvm] [clang] [clang-tools-extra] [nfc][llvm-profdata] Use cl::Subcommand to organize subcommand and options in llvm-profdata (PR #71328)

Mingming Liu via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 13 15:53:46 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/6] [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/6] 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) {
 

>From c9bdcf96a25c321685a8ee3a8a2844fd624a32d7 Mon Sep 17 00:00:00 2001
From: Mingming Liu <mingmingl at google.com>
Date: Wed, 8 Nov 2023 09:59:56 -0800
Subject: [PATCH 3/6] resolve feedback

---
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 306 ++++++++++-----------
 1 file changed, 139 insertions(+), 167 deletions(-)

diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index fd00798b8bc959e..fdf841a9f88b2df 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -2401,6 +2401,127 @@ struct ValueSitesStats {
 };
 } // namespace
 
+namespace show {
+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));
+
 static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK,
                                   ValueSitesStats &Stats, raw_fd_ostream &OS,
                                   InstrProfSymtab *Symtab) {
@@ -2449,14 +2570,7 @@ 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) {
+static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for instr profiles");
   if (SFormat == ShowFormat::Yaml)
@@ -2561,8 +2675,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));
@@ -2638,13 +2752,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";
@@ -2834,13 +2948,7 @@ 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(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Yaml)
     exitWithError("YAML output is not supported for sample profiles");
   using namespace sampleprof;
@@ -2888,15 +2996,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(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for MemProf");
   auto ReaderOr = llvm::memprof::RawMemProfReader::create(
@@ -2914,11 +3021,7 @@ static int showMemProfProfile(const std::string &Filename,
   return 0;
 }
 
-static int showDebugInfoCorrelation(const std::string &Filename,
-                                    bool ShowDetailedSummary,
-                                    bool ShowProfileSymbolList,
-                                    int MaxDbgCorrelationWarnings,
-                                    ShowFormat SFormat, raw_fd_ostream &OS) {
+static int showDebugInfoCorrelation(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;
@@ -2952,130 +3055,7 @@ static int showDebugInfoCorrelation(const std::string &Filename,
   return 0;
 }
 
-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())
@@ -3100,25 +3080,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(SFormat, 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(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(SFormat, OS);
+  return showMemProfProfile(SFormat, OS);
 }
 
+} // namespace show
+
 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"),
@@ -3191,7 +3163,7 @@ int llvm_profdata_main(int argc, char **argvNonConst,
     // (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);
+      return show::show_main(argc, argv);
 
     if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 ||
         strcmp(argv[1], "--help") == 0) {

>From 770e16741913b1e42a39ea70fa0a6c1b1a2c91e1 Mon Sep 17 00:00:00 2001
From: Mingming Liu <mingmingl at google.com>
Date: Fri, 10 Nov 2023 15:51:18 -0800
Subject: [PATCH 4/6] Refactor llvm-profdata to use cl::subcommand

---
 llvm/test/tools/llvm-profdata/errors.test  |   2 +-
 llvm/test/tools/llvm-profdata/version.test |   1 -
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 630 ++++++++++-----------
 3 files changed, 303 insertions(+), 330 deletions(-)

diff --git a/llvm/test/tools/llvm-profdata/errors.test b/llvm/test/tools/llvm-profdata/errors.test
index bd7d491b9a6b6af..6cf2a5ffac6e2f3 100644
--- a/llvm/test/tools/llvm-profdata/errors.test
+++ b/llvm/test/tools/llvm-profdata/errors.test
@@ -5,4 +5,4 @@ RUN: not llvm-profdata show file -o file 2>&1 | FileCheck %s --check-prefix SHOW
 SHOW-OUT: Input file name cannot be the same as the output file name!
 
 RUN: not llvm-profdata 2>&1 | FileCheck %s --check-prefix EMPTY
-EMPTY: No command specified!
+EMPTY: No subcommand specified!
diff --git a/llvm/test/tools/llvm-profdata/version.test b/llvm/test/tools/llvm-profdata/version.test
index 773c43870734540..fb247fad3a92aea 100644
--- a/llvm/test/tools/llvm-profdata/version.test
+++ b/llvm/test/tools/llvm-profdata/version.test
@@ -1,4 +1,3 @@
 # RUN: llvm-profdata --version | FileCheck %s
 
-# CHECK: llvm-profdata
 # CHECK: LLVM version {{.*}}
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index fdf841a9f88b2df..9aa3e4b04ee0a92 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -47,7 +47,20 @@
 
 using namespace llvm;
 
-cl::SubCommand ShowSubcommand("show", "show profile data");
+// https://llvm.org/docs/CommandGuide/llvm-profdata.html has documentations
+// on each subcommand.
+cl::SubCommand
+    ShowSubcommand("show",
+                   "Takes a profile data file and displays the profiles");
+cl::SubCommand
+    OrderSubcommand("order",
+                    "Reads temporal profiling traces from a "
+                    "profile and outputs a function order that reduces the "
+                    "number of page faults for those traces");
+cl::SubCommand
+    OverlapSubcommand("overlap",
+                      "Computes and displays the overlap between two profiles");
+cl::SubCommand MergeSubcommand("merge", "Merges profiles");
 
 // We use this string to indicate that there are
 // multiple static functions map to the same name.
@@ -437,13 +450,195 @@ static void writeInstrProfile(StringRef OutputFilename,
   }
 }
 
-static void
-mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename,
-                  SymbolRemapper *Remapper, StringRef OutputFilename,
-                  ProfileFormat OutputFormat, uint64_t TraceReservoirSize,
-                  uint64_t MaxTraceLength, int MaxDbgCorrelationWarnings,
-                  bool OutputSparse, unsigned NumThreads, FailureMode FailMode,
-                  const StringRef ProfiledBinary) {
+// Common options.
+cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+                                    cl::init("-"), cl::desc("Output file"),
+                                    cl::sub(ShowSubcommand),
+                                    cl::sub(OrderSubcommand),
+                                    cl::sub(OverlapSubcommand),
+                                    cl::sub(MergeSubcommand));
+// 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));
+
+// Options common to at least two commands.
+cl::opt<ProfileKinds> ProfileKind(
+    cl::desc("Profile kind:"), cl::sub(MergeSubcommand),
+    cl::sub(OverlapSubcommand), cl::init(instr),
+    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
+               clEnumVal(sample, "Sample profile")));
+cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"),
+                              cl::sub(ShowSubcommand),
+                              cl::sub(OrderSubcommand));
+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::sub(MergeSubcommand), cl::sub(ShowSubcommand), cl::init(5));
+cl::opt<std::string> ProfiledBinary(
+    "profiled-binary", cl::init(""),
+    cl::desc("Path to binary from which the profile was collected."),
+    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
+cl::opt<std::string> DebugInfoFilename(
+    "debug-info", cl::init(""),
+    cl::desc(
+        "For show, read and extract profile metadata from debug info and show "
+        "the functions it found. For merge, use the provided debug info to "
+        "correlate the raw profile."),
+    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
+
+// Options specific to merge subcommand.
+cl::list<std::string> InputFilenames(cl::Positional, cl::sub(MergeSubcommand),
+                                     cl::desc("<filename...>"));
+cl::list<std::string> WeightedInputFilenames("weighted-input",
+                                             cl::sub(MergeSubcommand),
+                                             cl::desc("<weight>,<filename>"));
+cl::opt<ProfileFormat> OutputFormat(
+    cl::desc("Format of output profile"), cl::sub(MergeSubcommand),
+    cl::init(PF_Ext_Binary),
+    cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding"),
+               clEnumValN(PF_Ext_Binary, "extbinary",
+                          "Extensible binary encoding "
+                          "(default)"),
+               clEnumValN(PF_Text, "text", "Text encoding"),
+               clEnumValN(PF_GCC, "gcc",
+                          "GCC encoding (only meaningful for -sample)")));
+cl::opt<std::string>
+    InputFilenamesFile("input-files", cl::init(""), cl::sub(MergeSubcommand),
+                       cl::desc("Path to file containing newline-separated "
+                                "[<weight>,]<filename> entries"));
+cl::alias InputFilenamesFileA("f", cl::desc("Alias for --input-files"),
+                              cl::aliasopt(InputFilenamesFile));
+cl::opt<bool> DumpInputFileList(
+    "dump-input-file-list", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Dump the list of input files and their weights, then exit"));
+cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
+                                   cl::sub(MergeSubcommand),
+                                   cl::desc("Symbol remapping file"));
+cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
+                         cl::aliasopt(RemappingFile));
+cl::opt<bool>
+    UseMD5("use-md5", cl::init(false), cl::Hidden,
+           cl::desc("Choose to use MD5 to represent string in name table (only "
+                    "meaningful for -extbinary)"),
+           cl::sub(MergeSubcommand));
+cl::opt<bool> CompressAllSections(
+    "compress-all-sections", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Compress all sections when writing the profile (only "
+             "meaningful for -extbinary)"));
+cl::opt<bool> SampleMergeColdContext(
+    "sample-merge-cold-context", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc(
+        "Merge context sample profiles whose count is below cold threshold"));
+cl::opt<bool> SampleTrimColdContext(
+    "sample-trim-cold-context", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc(
+        "Trim context sample profiles whose count is below cold threshold"));
+cl::opt<uint32_t> SampleColdContextFrameDepth(
+    "sample-frame-depth-for-cold-context", cl::init(1),
+    cl::sub(MergeSubcommand),
+    cl::desc("Keep the last K frames while merging cold profile. 1 means the "
+             "context-less base profile"));
+cl::opt<size_t> OutputSizeLimit(
+    "output-size-limit", cl::init(0), cl::Hidden, cl::sub(MergeSubcommand),
+    cl::desc("Trim cold functions until profile size is below specified "
+             "limit in bytes. This uses a heursitic and functions may be "
+             "excessively trimmed"));
+cl::opt<bool> GenPartialProfile(
+    "gen-partial-profile", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
+cl::opt<std::string> SupplInstrWithSample(
+    "supplement-instr-with-sample", cl::init(""), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Supplement an instr profile with sample profile, to correct "
+             "the profile unrepresentativeness issue. The sample "
+             "profile is the input of the flag. Output will be in instr "
+             "format (The flag only works with -instr)"));
+cl::opt<float> ZeroCounterThreshold(
+    "zero-counter-threshold", cl::init(0.7), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("For the function which is cold in instr profile but hot in "
+             "sample profile, if the ratio of the number of zero counters "
+             "divided by the total number of counters is above the "
+             "threshold, the profile of the function will be regarded as "
+             "being harmful for performance and will be dropped."));
+cl::opt<unsigned> SupplMinSizeThreshold(
+    "suppl-min-size-threshold", cl::init(10), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("If the size of a function is smaller than the threshold, "
+             "assume it can be inlined by PGO early inliner and it won't "
+             "be adjusted based on sample profile."));
+cl::opt<unsigned> InstrProfColdThreshold(
+    "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("User specified cold threshold for instr profile which will "
+             "override the cold threshold got from profile summary. "));
+// WARNING: This reservoir size value is propagated to any input indexed
+// profiles for simplicity. Changing this value between invocations could
+// result in sample bias.
+cl::opt<uint64_t> TemporalProfTraceReservoirSize(
+    "temporal-profile-trace-reservoir-size", cl::init(100),
+    cl::sub(MergeSubcommand),
+    cl::desc("The maximum number of stored temporal profile traces (default: "
+             "100)"));
+cl::opt<uint64_t> TemporalProfMaxTraceLength(
+    "temporal-profile-max-trace-length", cl::init(10000),
+    cl::sub(MergeSubcommand),
+    cl::desc("The maximum length of a single temporal profile trace "
+             "(default: 10000)"));
+
+cl::opt<FailureMode>
+    FailMode("failure-mode", cl::init(failIfAnyAreInvalid),
+             cl::desc("Failure mode:"), cl::sub(MergeSubcommand),
+             cl::values(clEnumValN(warnOnly, "warn",
+                                   "Do not fail and just print warnings."),
+                        clEnumValN(failIfAnyAreInvalid, "any",
+                                   "Fail if any profile is invalid."),
+                        clEnumValN(failIfAllAreInvalid, "all",
+                                   "Fail only if all profiles are invalid.")));
+
+cl::opt<bool> OutputSparse(
+    "sparse", cl::init(false), cl::sub(MergeSubcommand),
+    cl::desc("Generate a sparse profile (only meaningful for -instr)"));
+cl::opt<unsigned> NumThreads(
+    "num-threads", cl::init(0), cl::sub(MergeSubcommand),
+    cl::desc("Number of merge threads to use (default: autodetect)"));
+cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
+                      cl::aliasopt(NumThreads));
+
+cl::opt<std::string> ProfileSymbolListFile(
+    "prof-sym-list", cl::init(""), cl::sub(MergeSubcommand),
+    cl::desc("Path to file containing the list of function symbols "
+             "used to populate profile symbol list"));
+
+cl::opt<SampleProfileLayout> ProfileLayout(
+    "convert-sample-profile-layout",
+    cl::desc("Convert the generated profile to a profile with a new layout"),
+    cl::sub(MergeSubcommand), cl::init(SPL_None),
+    cl::values(
+        clEnumValN(SPL_Nest, "nest",
+                   "Nested profile, the input should be CS flat profile"),
+        clEnumValN(SPL_Flat, "flat",
+                   "Profile with nested inlinee flatten out")));
+
+cl::opt<bool> DropProfileSymbolList(
+    "drop-profile-symbol-list", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
+             "(only meaningful for -sample)"));
+
+static void mergeInstrProfile(const WeightedFileVector &Inputs,
+                              SymbolRemapper *Remapper,
+                              int MaxDbgCorrelationWarnings,
+                              const StringRef ProfiledBinary) {
+  const uint64_t TraceReservoirSize = TemporalProfTraceReservoirSize.getValue();
+  const uint64_t MaxTraceLength = TemporalProfMaxTraceLength.getValue();
   if (OutputFormat == PF_Compact_Binary)
     exitWithError("Compact Binary is deprecated");
   if (OutputFormat != PF_Binary && OutputFormat != PF_Ext_Binary &&
@@ -877,11 +1072,11 @@ adjustInstrProfile(std::unique_ptr<WriterContext> &WC,
 /// should be dropped. \p InstrProfColdThreshold is the user specified
 /// cold threshold which will override the cold threshold got from the
 /// instr profile summary.
-static void supplementInstrProfile(
-    const WeightedFileVector &Inputs, StringRef SampleFilename,
-    StringRef OutputFilename, ProfileFormat OutputFormat, bool OutputSparse,
-    unsigned SupplMinSizeThreshold, float ZeroCounterThreshold,
-    unsigned InstrProfColdThreshold) {
+static void supplementInstrProfile(const WeightedFileVector &Inputs,
+                                   StringRef SampleFilename, bool OutputSparse,
+                                   unsigned SupplMinSizeThreshold,
+                                   float ZeroCounterThreshold,
+                                   unsigned InstrProfColdThreshold) {
   if (OutputFilename.compare("-") == 0)
     exitWithError("cannot write indexed profdata format to stdout");
   if (Inputs.size() != 1)
@@ -1014,15 +1209,10 @@ static void handleExtBinaryWriter(sampleprof::SampleProfileWriter &Writer,
   }
 }
 
-static void
-mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
-                   StringRef OutputFilename, ProfileFormat OutputFormat,
-                   StringRef ProfileSymbolListFile, bool CompressAllSections,
-                   bool UseMD5, bool GenPartialProfile,
-                   SampleProfileLayout ProfileLayout,
-                   bool SampleMergeColdContext, bool SampleTrimColdContext,
-                   bool SampleColdContextFrameDepth, FailureMode FailMode,
-                   bool DropProfileSymbolList, size_t OutputSizeLimit) {
+static void mergeSampleProfile(const WeightedFileVector &Inputs,
+                               SymbolRemapper *Remapper,
+                               StringRef ProfileSymbolListFile,
+                               size_t OutputSizeLimit) {
   using namespace sampleprof;
   SampleProfileMap ProfileMap;
   SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers;
@@ -1193,147 +1383,6 @@ static void parseInputFilenamesFile(MemoryBuffer *Buffer,
 }
 
 static int merge_main(int argc, const char *argv[]) {
-  cl::list<std::string> InputFilenames(cl::Positional,
-                                       cl::desc("<filename...>"));
-  cl::list<std::string> WeightedInputFilenames("weighted-input",
-                                               cl::desc("<weight>,<filename>"));
-  cl::opt<std::string> InputFilenamesFile(
-      "input-files", cl::init(""),
-      cl::desc("Path to file containing newline-separated "
-               "[<weight>,]<filename> entries"));
-  cl::alias InputFilenamesFileA("f", cl::desc("Alias for --input-files"),
-                                cl::aliasopt(InputFilenamesFile));
-  cl::opt<bool> DumpInputFileList(
-      "dump-input-file-list", cl::init(false), cl::Hidden,
-      cl::desc("Dump the list of input files and their weights, then exit"));
-  cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
-                                     cl::desc("Symbol remapping file"));
-  cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
-                           cl::aliasopt(RemappingFile));
-  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")));
-  cl::opt<ProfileFormat> OutputFormat(
-      cl::desc("Format of output profile"), cl::init(PF_Ext_Binary),
-      cl::values(
-          clEnumValN(PF_Binary, "binary", "Binary encoding"),
-          clEnumValN(PF_Ext_Binary, "extbinary", "Extensible binary encoding "
-                     "(default)"),
-          clEnumValN(PF_Text, "text", "Text encoding"),
-          clEnumValN(PF_GCC, "gcc",
-                     "GCC encoding (only meaningful for -sample)")));
-  cl::opt<FailureMode> FailureMode(
-      "failure-mode", cl::init(failIfAnyAreInvalid), cl::desc("Failure mode:"),
-      cl::values(
-          clEnumValN(warnOnly, "warn", "Do not fail and just print warnings."),
-          clEnumValN(failIfAnyAreInvalid, "any",
-                     "Fail if any profile is invalid."),
-          clEnumValN(failIfAllAreInvalid, "all",
-                     "Fail only if all profiles are invalid.")));
-  cl::opt<bool> OutputSparse("sparse", cl::init(false),
-      cl::desc("Generate a sparse profile (only meaningful for -instr)"));
-  cl::opt<unsigned> NumThreads(
-      "num-threads", cl::init(0),
-      cl::desc("Number of merge threads to use (default: autodetect)"));
-  cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
-                        cl::aliasopt(NumThreads));
-  cl::opt<std::string> ProfileSymbolListFile(
-      "prof-sym-list", cl::init(""),
-      cl::desc("Path to file containing the list of function symbols "
-               "used to populate profile symbol list"));
-  cl::opt<bool> CompressAllSections(
-      "compress-all-sections", cl::init(false), cl::Hidden,
-      cl::desc("Compress all sections when writing the profile (only "
-               "meaningful for -extbinary)"));
-  cl::opt<bool> UseMD5(
-      "use-md5", cl::init(false), cl::Hidden,
-      cl::desc("Choose to use MD5 to represent string in name table (only "
-               "meaningful for -extbinary)"));
-  cl::opt<bool> SampleMergeColdContext(
-      "sample-merge-cold-context", cl::init(false), cl::Hidden,
-      cl::desc(
-          "Merge context sample profiles whose count is below cold threshold"));
-  cl::opt<bool> SampleTrimColdContext(
-      "sample-trim-cold-context", cl::init(false), cl::Hidden,
-      cl::desc(
-          "Trim context sample profiles whose count is below cold threshold"));
-  cl::opt<uint32_t> SampleColdContextFrameDepth(
-      "sample-frame-depth-for-cold-context", cl::init(1),
-      cl::desc("Keep the last K frames while merging cold profile. 1 means the "
-               "context-less base profile"));
-  cl::opt<size_t> OutputSizeLimit(
-      "output-size-limit", cl::init(0), cl::Hidden,
-      cl::desc("Trim cold functions until profile size is below specified "
-               "limit in bytes. This uses a heursitic and functions may be "
-               "excessively trimmed"));
-  cl::opt<bool> GenPartialProfile(
-      "gen-partial-profile", cl::init(false), cl::Hidden,
-      cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
-  cl::opt<std::string> SupplInstrWithSample(
-      "supplement-instr-with-sample", cl::init(""), cl::Hidden,
-      cl::desc("Supplement an instr profile with sample profile, to correct "
-               "the profile unrepresentativeness issue. The sample "
-               "profile is the input of the flag. Output will be in instr "
-               "format (The flag only works with -instr)"));
-  cl::opt<float> ZeroCounterThreshold(
-      "zero-counter-threshold", cl::init(0.7), cl::Hidden,
-      cl::desc("For the function which is cold in instr profile but hot in "
-               "sample profile, if the ratio of the number of zero counters "
-               "divided by the total number of counters is above the "
-               "threshold, the profile of the function will be regarded as "
-               "being harmful for performance and will be dropped."));
-  cl::opt<unsigned> SupplMinSizeThreshold(
-      "suppl-min-size-threshold", cl::init(10), cl::Hidden,
-      cl::desc("If the size of a function is smaller than the threshold, "
-               "assume it can be inlined by PGO early inliner and it won't "
-               "be adjusted based on sample profile."));
-  cl::opt<unsigned> InstrProfColdThreshold(
-      "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
-      cl::desc("User specified cold threshold for instr profile which will "
-               "override the cold threshold got from profile summary. "));
-  cl::opt<SampleProfileLayout> ProfileLayout(
-      "convert-sample-profile-layout",
-      cl::desc("Convert the generated profile to a profile with a new layout"),
-      cl::init(SPL_None),
-      cl::values(
-          clEnumValN(SPL_Nest, "nest",
-                     "Nested profile, the input should be CS flat profile"),
-          clEnumValN(SPL_Flat, "flat",
-                     "Profile with nested inlinee flatten out")));
-  cl::opt<std::string> DebugInfoFilename(
-      "debug-info", cl::init(""),
-      cl::desc("Use the provided debug info to correlate the raw profile."));
-  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<std::string> ProfiledBinary(
-      "profiled-binary", cl::init(""),
-      cl::desc("Path to binary from which the profile was collected."));
-  cl::opt<bool> DropProfileSymbolList(
-      "drop-profile-symbol-list", cl::init(false), cl::Hidden,
-      cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
-               "(only meaningful for -sample)"));
-  // WARNING: This reservoir size value is propagated to any input indexed
-  // profiles for simplicity. Changing this value between invocations could
-  // result in sample bias.
-  cl::opt<uint64_t> TemporalProfTraceReservoirSize(
-      "temporal-profile-trace-reservoir-size", cl::init(100),
-      cl::desc("The maximum number of stored temporal profile traces (default: "
-               "100)"));
-  cl::opt<uint64_t> TemporalProfMaxTraceLength(
-      "temporal-profile-max-trace-length", cl::init(10000),
-      cl::desc("The maximum length of a single temporal profile trace "
-               "(default: 10000)"));
-
-  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
-
   WeightedFileVector WeightedInputs;
   for (StringRef Filename : InputFilenames)
     addWeightedInput(WeightedInputs, {std::string(Filename), 1});
@@ -1347,7 +1396,7 @@ static int merge_main(int argc, const char *argv[]) {
 
   if (WeightedInputs.empty())
     exitWithError("no input files specified. See " +
-                  sys::path::filename(argv[0]) + " -help");
+                  sys::path::filename(argv[0]) + " " + argv[1] + " -help");
 
   if (DumpInputFileList) {
     for (auto &WF : WeightedInputs)
@@ -1364,28 +1413,55 @@ static int merge_main(int argc, const char *argv[]) {
       exitWithError(
           "-supplement-instr-with-sample can only work with -instr. ");
 
-    supplementInstrProfile(WeightedInputs, SupplInstrWithSample, OutputFilename,
-                           OutputFormat, OutputSparse, SupplMinSizeThreshold,
-                           ZeroCounterThreshold, InstrProfColdThreshold);
+    supplementInstrProfile(WeightedInputs, SupplInstrWithSample, OutputSparse,
+                           SupplMinSizeThreshold, ZeroCounterThreshold,
+                           InstrProfColdThreshold);
     return 0;
   }
 
   if (ProfileKind == instr)
-    mergeInstrProfile(WeightedInputs, DebugInfoFilename, Remapper.get(),
-                      OutputFilename, OutputFormat,
-                      TemporalProfTraceReservoirSize,
-                      TemporalProfMaxTraceLength, MaxDbgCorrelationWarnings,
-                      OutputSparse, NumThreads, FailureMode, ProfiledBinary);
+    mergeInstrProfile(WeightedInputs, Remapper.get(), MaxDbgCorrelationWarnings,
+                      ProfiledBinary);
   else
-    mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename,
-                       OutputFormat, ProfileSymbolListFile, CompressAllSections,
-                       UseMD5, GenPartialProfile, ProfileLayout,
-                       SampleMergeColdContext, SampleTrimColdContext,
-                       SampleColdContextFrameDepth, FailureMode,
-                       DropProfileSymbolList, OutputSizeLimit);
+    mergeSampleProfile(WeightedInputs, Remapper.get(), ProfileSymbolListFile,
+                       OutputSizeLimit);
   return 0;
 }
 
+// Overlap options.
+cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
+                                  cl::desc("<base profile file>"),
+                                  cl::sub(OverlapSubcommand));
+cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
+                                  cl::desc("<test profile file>"),
+                                  cl::sub(OverlapSubcommand));
+
+cl::opt<unsigned long long> SimilarityCutoff(
+    "similarity-cutoff", cl::init(0),
+    cl::desc("For sample profiles, list function names (with calling context "
+             "for csspgo) for overlapped functions "
+             "with similarities below the cutoff (percentage times 10000)."),
+    cl::sub(OverlapSubcommand));
+
+cl::opt<bool> IsCS(
+    "cs", cl::init(false),
+    cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."),
+    cl::sub(OverlapSubcommand));
+
+cl::opt<std::string> FuncNameFilter(
+    "function",
+    cl::desc("Details for matching functions. For overlapping CSSPGO, this "
+             "takes a function name with calling context."),
+    cl::sub(ShowSubcommand), cl::sub(OverlapSubcommand));
+
+cl::opt<unsigned long long> OverlapValueCutoff(
+    "value-cutoff", cl::init(-1),
+    cl::desc(
+        "Function level overlap information for every function (with calling "
+        "context for csspgo) in test "
+        "profile with max count value greater then the parameter value"),
+    cl::sub(OverlapSubcommand));
+
 /// Computer the overlap b/w profile BaseFilename and profile TestFilename.
 static void overlapInstrProfile(const std::string &BaseFilename,
                                 const std::string &TestFilename,
@@ -2341,49 +2417,18 @@ void overlapSampleProfile(const std::string &BaseFilename,
 }
 
 static int overlap_main(int argc, const char *argv[]) {
-  cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
-                                    cl::desc("<base profile file>"));
-  cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
-                                    cl::desc("<test profile file>"));
-  cl::opt<std::string> Output("output", cl::value_desc("output"), cl::init("-"),
-                              cl::desc("Output file"));
-  cl::alias OutputA("o", cl::desc("Alias for --output"), cl::aliasopt(Output));
-  cl::opt<bool> IsCS(
-      "cs", cl::init(false),
-      cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."));
-  cl::opt<unsigned long long> ValueCutoff(
-      "value-cutoff", cl::init(-1),
-      cl::desc(
-          "Function level overlap information for every function (with calling "
-          "context for csspgo) in test "
-          "profile with max count value greater then the parameter value"));
-  cl::opt<std::string> FuncNameFilter(
-      "function",
-      cl::desc("Function level overlap information for matching functions. For "
-               "CSSPGO this takes a a function name with calling context"));
-  cl::opt<unsigned long long> SimilarityCutoff(
-      "similarity-cutoff", cl::init(0),
-      cl::desc("For sample profiles, list function names (with calling context "
-               "for csspgo) for overlapped functions "
-               "with similarities below the cutoff (percentage times 10000)."));
-  cl::opt<ProfileKinds> ProfileKind(
-      cl::desc("Profile kind:"), cl::init(instr),
-      cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
-                 clEnumVal(sample, "Sample profile")));
-  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data overlap tool\n");
-
   std::error_code EC;
-  raw_fd_ostream OS(Output.data(), EC, sys::fs::OF_TextWithCRLF);
+  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
   if (EC)
-    exitWithErrorCode(EC, Output);
+    exitWithErrorCode(EC, OutputFilename);
 
   if (ProfileKind == instr)
     overlapInstrProfile(BaseFilename, TestFilename,
-                        OverlapFuncFilters{ValueCutoff, FuncNameFilter}, OS,
-                        IsCS);
+                        OverlapFuncFilters{OverlapValueCutoff, FuncNameFilter},
+                        OS, IsCS);
   else
     overlapSampleProfile(BaseFilename, TestFilename,
-                         OverlapFuncFilters{ValueCutoff, FuncNameFilter},
+                         OverlapFuncFilters{OverlapValueCutoff, FuncNameFilter},
                          SimilarityCutoff, OS);
 
   return 0;
@@ -2401,21 +2446,20 @@ struct ValueSitesStats {
 };
 } // namespace
 
-namespace show {
-cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"),
-                              cl::sub(ShowSubcommand));
-
+// Options unique to show subcommand.
+// TODO: Consider creating a template class ShowOption to factor out the common
+// cl::sub in cl::opt constructor.
 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::sub(ShowSubcommand),
             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));
+                       clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")));
 // TODO: Consider replacing this with `--show-format=text-encoding`.
 cl::opt<bool>
     TextFormat("text", cl::init(false),
@@ -2453,19 +2497,9 @@ cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
 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::opt<ProfileKinds> ShowProfileKind(
+    cl::desc("Profile kind supported by show:"), cl::sub(ShowSubcommand),
+    cl::init(instr),
     cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
                clEnumVal(sample, "Sample profile"),
                clEnumVal(memory, "MemProf memory access profile")));
@@ -2473,7 +2507,7 @@ 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(
+cl::opt<uint32_t> ShowValueCutoff(
     "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)"),
@@ -2500,24 +2534,12 @@ 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));
@@ -2604,7 +2626,7 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
 
   if (!TextFormat && OnlyListBelow) {
     OS << "The list of functions with the maximum counter less than "
-       << ValueCutoff << ":\n";
+       << ShowValueCutoff << ":\n";
   }
 
   // Add marker so that IR-level instrumentation round-trips properly.
@@ -2618,7 +2640,7 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
         continue;
     }
     bool Show = ShowAllFunctions ||
-                (!ShowFunction.empty() && Func.Name.contains(ShowFunction));
+                (!FuncNameFilter.empty() && Func.Name.contains(FuncNameFilter));
 
     bool doTextFormatDump = (Show && TextFormat);
 
@@ -2665,7 +2687,7 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
       FuncSum += Func.Counts[I];
     }
 
-    if (FuncMax < ValueCutoff) {
+    if (FuncMax < ShowValueCutoff) {
       ++BelowCutoffFunctions;
       if (OnlyListBelow) {
         OS << "  " << Func.Name << ": (Max = " << FuncMax
@@ -2740,13 +2762,13 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (IsIR)
     OS << "  entry_first = " << Reader->instrEntryBBEnabled();
   OS << "\n";
-  if (ShowAllFunctions || !ShowFunction.empty())
+  if (ShowAllFunctions || !FuncNameFilter.empty())
     OS << "Functions shown: " << ShownFunctions << "\n";
   OS << "Total functions: " << PS->getNumFunctions() << "\n";
-  if (ValueCutoff > 0) {
-    OS << "Number of functions with maximum count (< " << ValueCutoff
+  if (ShowValueCutoff > 0) {
+    OS << "Number of functions with maximum count (< " << ShowValueCutoff
        << "): " << BelowCutoffFunctions << "\n";
-    OS << "Number of functions with maximum count (>= " << ValueCutoff
+    OS << "Number of functions with maximum count (>= " << ShowValueCutoff
        << "): " << PS->getNumFunctions() - BelowCutoffFunctions << "\n";
   }
   OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n";
@@ -2968,7 +2990,7 @@ static int showSampleProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (std::error_code EC = Reader->read())
     exitWithErrorCode(EC, Filename);
 
-  if (ShowAllFunctions || ShowFunction.empty()) {
+  if (ShowAllFunctions || FuncNameFilter.empty()) {
     if (SFormat == ShowFormat::Json)
       Reader->dumpJson(OS);
     else
@@ -2980,7 +3002,7 @@ static int showSampleProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
           "be printed");
 
     // TODO: parse context string to support filtering by contexts.
-    FunctionSamples *FS = Reader->getSamplesFor(StringRef(ShowFunction));
+    FunctionSamples *FS = Reader->getSamplesFor(StringRef(FuncNameFilter));
     Reader->dumpFunctionProfile(FS ? *FS : FunctionSamples(), OS);
   }
 
@@ -3021,7 +3043,8 @@ static int showMemProfProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   return 0;
 }
 
-static int showDebugInfoCorrelation(ShowFormat SFormat, raw_fd_ostream &OS) {
+static int showDebugInfoCorrelation(const std::string &Filename,
+                                    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;
@@ -3056,8 +3079,6 @@ static int showDebugInfoCorrelation(ShowFormat SFormat, raw_fd_ostream &OS) {
 }
 
 static int show_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 '--" +
@@ -3076,29 +3097,20 @@ static int show_main(int argc, const char *argv[]) {
   if (EC)
     exitWithErrorCode(EC, OutputFilename);
 
-  if (ShowAllFunctions && !ShowFunction.empty())
+  if (ShowAllFunctions && !FuncNameFilter.empty())
     WithColor::warning() << "-function argument ignored: showing all functions\n";
 
   if (!DebugInfoFilename.empty())
-    return showDebugInfoCorrelation(SFormat, OS);
+    return showDebugInfoCorrelation(DebugInfoFilename, SFormat, OS);
 
-  if (ProfileKind == instr)
+  if (ShowProfileKind == instr)
     return showInstrProfile(SFormat, OS);
-  if (ProfileKind == sample)
+  if (ShowProfileKind == sample)
     return showSampleProfile(SFormat, OS);
   return showMemProfProfile(SFormat, OS);
 }
 
-} // namespace show
-
 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"),
-                                      cl::init("-"), cl::desc("Output file"));
-  cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
-                            cl::aliasopt(OutputFilename));
-  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data order\n");
-
   std::error_code EC;
   raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
   if (EC)
@@ -3130,72 +3142,34 @@ static int order_main(int argc, const char *argv[]) {
   return 0;
 }
 
-typedef int (*llvm_profdata_subcommand)(int, const char *[]);
-
-static std::tuple<StringRef, llvm_profdata_subcommand>
-    llvm_profdata_subcommands[] = {
-        {"merge", merge_main},
-        {"order", order_main},
-        {"overlap", overlap_main},
-};
-
 int llvm_profdata_main(int argc, char **argvNonConst,
                        const llvm::ToolContext &) {
   const char **argv = const_cast<const char **>(argvNonConst);
   InitLLVM X(argc, argv);
 
   StringRef ProgName(sys::path::filename(argv[0]));
-  if (argc > 1) {
 
-    llvm_profdata_subcommand func = nullptr;
-    for (auto [subcmd_name, subcmd_action] : llvm_profdata_subcommands)
-      if (subcmd_name == argv[1])
-        func = subcmd_action;
+  if (argc < 2) {
+    errs() << ProgName
+           << ": No subcommand specified! Run llvm-profata --help for usage.\n";
+    return 1;
+  }
 
-    if (func) {
-      std::string Invocation(ProgName.str() + " " + argv[1]);
-      argv[1] = Invocation.c_str();
-      return func(argc - 1, argv + 1);
-    }
+  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data\n");
 
-    // "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::show_main(argc, argv);
-
-    if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 ||
-        strcmp(argv[1], "--help") == 0) {
-
-      errs() << "OVERVIEW: LLVM profile data tools\n\n"
-             << "USAGE: " << ProgName << " <command> [args...]\n"
-             << "USAGE: " << ProgName << " <command> -help\n\n"
-             << "See each individual command --help for more details.\n"
-             << "Available commands: "
-             << join(map_range(llvm_profdata_subcommands,
-                               [](auto const &KV) { return std::get<0>(KV); }),
-                     ", ")
-             << "\n";
-      return 0;
-    }
+  if (ShowSubcommand)
+    return show_main(argc, argv);
 
-    if (strcmp(argv[1], "--version") == 0) {
-      outs() << ProgName << '\n';
-      cl::PrintVersionMessage();
-      return 0;
-    }
-  }
+  if (OrderSubcommand)
+    return order_main(argc, argv);
 
-  if (argc < 2)
-    errs() << ProgName << ": No command specified!\n";
-  else
-    errs() << ProgName << ": Unknown command!\n";
+  if (OverlapSubcommand)
+    return overlap_main(argc, argv);
+
+  if (MergeSubcommand)
+    return merge_main(argc, argv);
 
-  errs() << "USAGE: " << ProgName << " <"
-         << join(map_range(llvm_profdata_subcommands,
-                           [](auto const &KV) { return std::get<0>(KV); }),
-                 "|")
-         << "> [args...]\n";
+  errs() << ProgName
+         << ": Unknown command. Run llvm-profdata --help for usage.\n";
   return 1;
 }

>From 6fc1bfa4df1914f1ff00a464cc513b234bc01013 Mon Sep 17 00:00:00 2001
From: Mingming Liu <mingmingl at google.com>
Date: Fri, 10 Nov 2023 16:21:02 -0800
Subject: [PATCH 5/6] undo one-line added during debugging

---
 llvm/include/llvm/Support/CommandLine.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index ab62607b2a307e5..58ef176551b6852 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) {}
 
-  void apply(Option &O) const { O.addSubCommand(Sub); }
+  template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
 };
 
 // Specify a callback function to be called when an option is seen.

>From 0f3951d810e85e434d17bf0acb853203ebb70496 Mon Sep 17 00:00:00 2001
From: Mingming Liu <mingmingl at google.com>
Date: Mon, 13 Nov 2023 15:51:35 -0800
Subject: [PATCH 6/6] resolve feedback

---
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 848 +++++++++++----------
 1 file changed, 429 insertions(+), 419 deletions(-)

diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 9aa3e4b04ee0a92..bb058873604508b 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -49,18 +49,343 @@ using namespace llvm;
 
 // https://llvm.org/docs/CommandGuide/llvm-profdata.html has documentations
 // on each subcommand.
-cl::SubCommand
-    ShowSubcommand("show",
-                   "Takes a profile data file and displays the profiles");
-cl::SubCommand
-    OrderSubcommand("order",
-                    "Reads temporal profiling traces from a "
-                    "profile and outputs a function order that reduces the "
-                    "number of page faults for those traces");
-cl::SubCommand
-    OverlapSubcommand("overlap",
-                      "Computes and displays the overlap between two profiles");
-cl::SubCommand MergeSubcommand("merge", "Merges profiles");
+cl::SubCommand ShowSubcommand(
+    "show",
+    "Takes a profile data file and displays the profiles. See detailed "
+    "documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-show");
+cl::SubCommand OrderSubcommand(
+    "order",
+    "Reads temporal profiling traces from a profile and outputs a function "
+    "order that reduces the number of page faults for those traces. See "
+    "detailed documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-order");
+cl::SubCommand OverlapSubcommand(
+    "overlap",
+    "Computes and displays the overlap between two profiles. See detailed "
+    "documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-overlap");
+cl::SubCommand MergeSubcommand(
+    "merge",
+    "Takes several profiles and merge them together. See detailed "
+    "documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-merge");
+
+// Common options.
+cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+                                    cl::init("-"), cl::desc("Output file"),
+                                    cl::sub(ShowSubcommand),
+                                    cl::sub(OrderSubcommand),
+                                    cl::sub(OverlapSubcommand),
+                                    cl::sub(MergeSubcommand));
+// 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));
+
+// Options common to at least two commands.
+cl::opt<ProfileKinds> ProfileKind(
+    cl::desc("Profile kind:"), cl::sub(MergeSubcommand),
+    cl::sub(OverlapSubcommand), cl::init(instr),
+    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
+               clEnumVal(sample, "Sample profile")));
+cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"),
+                              cl::sub(ShowSubcommand),
+                              cl::sub(OrderSubcommand));
+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::sub(MergeSubcommand), cl::sub(ShowSubcommand), cl::init(5));
+cl::opt<std::string> ProfiledBinary(
+    "profiled-binary", cl::init(""),
+    cl::desc("Path to binary from which the profile was collected."),
+    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
+cl::opt<std::string> DebugInfoFilename(
+    "debug-info", cl::init(""),
+    cl::desc(
+        "For show, read and extract profile metadata from debug info and show "
+        "the functions it found. For merge, use the provided debug info to "
+        "correlate the raw profile."),
+    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
+cl::opt<std::string> FuncNameFilter(
+    "function",
+    cl::desc("Details for matching functions. For overlapping CSSPGO, this "
+             "takes a function name with calling context."),
+    cl::sub(ShowSubcommand), cl::sub(OverlapSubcommand));
+
+// TODO: Consider creating a template class (e.g., MergeOption, ShowOption) to
+// factor out the common cl::sub in cl::opt constructor for subcommand-specific
+// options.
+
+// Options specific to merge subcommand.
+cl::list<std::string> InputFilenames(cl::Positional, cl::sub(MergeSubcommand),
+                                     cl::desc("<filename...>"));
+cl::list<std::string> WeightedInputFilenames("weighted-input",
+                                             cl::sub(MergeSubcommand),
+                                             cl::desc("<weight>,<filename>"));
+cl::opt<ProfileFormat> OutputFormat(
+    cl::desc("Format of output profile"), cl::sub(MergeSubcommand),
+    cl::init(PF_Ext_Binary),
+    cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding"),
+               clEnumValN(PF_Ext_Binary, "extbinary",
+                          "Extensible binary encoding "
+                          "(default)"),
+               clEnumValN(PF_Text, "text", "Text encoding"),
+               clEnumValN(PF_GCC, "gcc",
+                          "GCC encoding (only meaningful for -sample)")));
+cl::opt<std::string>
+    InputFilenamesFile("input-files", cl::init(""), cl::sub(MergeSubcommand),
+                       cl::desc("Path to file containing newline-separated "
+                                "[<weight>,]<filename> entries"));
+cl::alias InputFilenamesFileA("f", cl::desc("Alias for --input-files"),
+                              cl::aliasopt(InputFilenamesFile));
+cl::opt<bool> DumpInputFileList(
+    "dump-input-file-list", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Dump the list of input files and their weights, then exit"));
+cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
+                                   cl::sub(MergeSubcommand),
+                                   cl::desc("Symbol remapping file"));
+cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
+                         cl::aliasopt(RemappingFile));
+cl::opt<bool>
+    UseMD5("use-md5", cl::init(false), cl::Hidden,
+           cl::desc("Choose to use MD5 to represent string in name table (only "
+                    "meaningful for -extbinary)"),
+           cl::sub(MergeSubcommand));
+cl::opt<bool> CompressAllSections(
+    "compress-all-sections", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Compress all sections when writing the profile (only "
+             "meaningful for -extbinary)"));
+cl::opt<bool> SampleMergeColdContext(
+    "sample-merge-cold-context", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc(
+        "Merge context sample profiles whose count is below cold threshold"));
+cl::opt<bool> SampleTrimColdContext(
+    "sample-trim-cold-context", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc(
+        "Trim context sample profiles whose count is below cold threshold"));
+cl::opt<uint32_t> SampleColdContextFrameDepth(
+    "sample-frame-depth-for-cold-context", cl::init(1),
+    cl::sub(MergeSubcommand),
+    cl::desc("Keep the last K frames while merging cold profile. 1 means the "
+             "context-less base profile"));
+cl::opt<size_t> OutputSizeLimit(
+    "output-size-limit", cl::init(0), cl::Hidden, cl::sub(MergeSubcommand),
+    cl::desc("Trim cold functions until profile size is below specified "
+             "limit in bytes. This uses a heursitic and functions may be "
+             "excessively trimmed"));
+cl::opt<bool> GenPartialProfile(
+    "gen-partial-profile", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
+cl::opt<std::string> SupplInstrWithSample(
+    "supplement-instr-with-sample", cl::init(""), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Supplement an instr profile with sample profile, to correct "
+             "the profile unrepresentativeness issue. The sample "
+             "profile is the input of the flag. Output will be in instr "
+             "format (The flag only works with -instr)"));
+cl::opt<float> ZeroCounterThreshold(
+    "zero-counter-threshold", cl::init(0.7), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("For the function which is cold in instr profile but hot in "
+             "sample profile, if the ratio of the number of zero counters "
+             "divided by the total number of counters is above the "
+             "threshold, the profile of the function will be regarded as "
+             "being harmful for performance and will be dropped."));
+cl::opt<unsigned> SupplMinSizeThreshold(
+    "suppl-min-size-threshold", cl::init(10), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("If the size of a function is smaller than the threshold, "
+             "assume it can be inlined by PGO early inliner and it won't "
+             "be adjusted based on sample profile."));
+cl::opt<unsigned> InstrProfColdThreshold(
+    "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("User specified cold threshold for instr profile which will "
+             "override the cold threshold got from profile summary. "));
+// WARNING: This reservoir size value is propagated to any input indexed
+// profiles for simplicity. Changing this value between invocations could
+// result in sample bias.
+cl::opt<uint64_t> TemporalProfTraceReservoirSize(
+    "temporal-profile-trace-reservoir-size", cl::init(100),
+    cl::sub(MergeSubcommand),
+    cl::desc("The maximum number of stored temporal profile traces (default: "
+             "100)"));
+cl::opt<uint64_t> TemporalProfMaxTraceLength(
+    "temporal-profile-max-trace-length", cl::init(10000),
+    cl::sub(MergeSubcommand),
+    cl::desc("The maximum length of a single temporal profile trace "
+             "(default: 10000)"));
+
+cl::opt<FailureMode>
+    FailMode("failure-mode", cl::init(failIfAnyAreInvalid),
+             cl::desc("Failure mode:"), cl::sub(MergeSubcommand),
+             cl::values(clEnumValN(warnOnly, "warn",
+                                   "Do not fail and just print warnings."),
+                        clEnumValN(failIfAnyAreInvalid, "any",
+                                   "Fail if any profile is invalid."),
+                        clEnumValN(failIfAllAreInvalid, "all",
+                                   "Fail only if all profiles are invalid.")));
+
+cl::opt<bool> OutputSparse(
+    "sparse", cl::init(false), cl::sub(MergeSubcommand),
+    cl::desc("Generate a sparse profile (only meaningful for -instr)"));
+cl::opt<unsigned> NumThreads(
+    "num-threads", cl::init(0), cl::sub(MergeSubcommand),
+    cl::desc("Number of merge threads to use (default: autodetect)"));
+cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
+                      cl::aliasopt(NumThreads));
+
+cl::opt<std::string> ProfileSymbolListFile(
+    "prof-sym-list", cl::init(""), cl::sub(MergeSubcommand),
+    cl::desc("Path to file containing the list of function symbols "
+             "used to populate profile symbol list"));
+
+cl::opt<SampleProfileLayout> ProfileLayout(
+    "convert-sample-profile-layout",
+    cl::desc("Convert the generated profile to a profile with a new layout"),
+    cl::sub(MergeSubcommand), cl::init(SPL_None),
+    cl::values(
+        clEnumValN(SPL_Nest, "nest",
+                   "Nested profile, the input should be CS flat profile"),
+        clEnumValN(SPL_Flat, "flat",
+                   "Profile with nested inlinee flatten out")));
+
+cl::opt<bool> DropProfileSymbolList(
+    "drop-profile-symbol-list", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
+             "(only meaningful for -sample)"));
+
+// Options specific to overlap subcommand.
+cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
+                                  cl::desc("<base profile file>"),
+                                  cl::sub(OverlapSubcommand));
+cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
+                                  cl::desc("<test profile file>"),
+                                  cl::sub(OverlapSubcommand));
+
+cl::opt<unsigned long long> SimilarityCutoff(
+    "similarity-cutoff", cl::init(0),
+    cl::desc("For sample profiles, list function names (with calling context "
+             "for csspgo) for overlapped functions "
+             "with similarities below the cutoff (percentage times 10000)."),
+    cl::sub(OverlapSubcommand));
+
+cl::opt<bool> IsCS(
+    "cs", cl::init(false),
+    cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."),
+    cl::sub(OverlapSubcommand));
+
+cl::opt<unsigned long long> OverlapValueCutoff(
+    "value-cutoff", cl::init(-1),
+    cl::desc(
+        "Function level overlap information for every function (with calling "
+        "context for csspgo) in test "
+        "profile with max count value greater then the parameter value"),
+    cl::sub(OverlapSubcommand));
+
+// Options unique to show subcommand.
+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::sub(ShowSubcommand),
+            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::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<ProfileKinds> ShowProfileKind(
+    cl::desc("Profile kind supported by show:"), 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> ShowValueCutoff(
+    "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<bool>
+    ShowCovered("covered", cl::init(false),
+                cl::desc("Show only the functions that have been executed."),
+                cl::sub(ShowSubcommand));
+
+cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
+                                 cl::desc("Show profile version. "),
+                                 cl::sub(ShowSubcommand));
 
 // We use this string to indicate that there are
 // multiple static functions map to the same name.
@@ -352,286 +677,103 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
       WC->Errors.emplace_back(make_error<InstrProfError>(ErrCode, Msg),
                               Filename);
     return;
-  }
-
-  auto Reader = std::move(ReaderOrErr.get());
-  if (Error E = WC->Writer.mergeProfileKind(Reader->getProfileKind())) {
-    consumeError(std::move(E));
-    WC->Errors.emplace_back(
-        make_error<StringError>(
-            "Merge IR generated profile with Clang generated profile.",
-            std::error_code()),
-        Filename);
-    return;
-  }
-
-  for (auto &I : *Reader) {
-    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) {
-        consumeError(std::move(E));
-        return;
-      }
-      Reported = true;
-      // Only show hint the first time an error occurs.
-      auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
-      std::unique_lock<std::mutex> ErrGuard{WC->ErrLock};
-      bool firstTime = WC->WriterErrorCodes.insert(ErrCode).second;
-      handleMergeWriterError(make_error<InstrProfError>(ErrCode, Msg),
-                             Input.Filename, FuncName, firstTime);
-    });
-  }
-
-  if (Reader->hasTemporalProfile()) {
-    auto &Traces = Reader->getTemporalProfTraces(Input.Weight);
-    if (!Traces.empty())
-      WC->Writer.addTemporalProfileTraces(
-          Traces, Reader->getTemporalProfTraceStreamSize());
-  }
-  if (Reader->hasError()) {
-    if (Error E = Reader->getError()) {
-      WC->Errors.emplace_back(std::move(E), Filename);
-      return;
-    }
-  }
-
-  std::vector<llvm::object::BuildID> BinaryIds;
-  if (Error E = Reader->readBinaryIds(BinaryIds)) {
-    WC->Errors.emplace_back(std::move(E), Filename);
-    return;
-  }
-  WC->Writer.addBinaryIds(BinaryIds);
-
-  if (ReaderWarning) {
-    WC->Errors.emplace_back(std::move(ReaderWarning->first),
-                            ReaderWarning->second);
-  }
-}
-
-/// Merge the \p Src writer context into \p Dst.
-static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
-  for (auto &ErrorPair : Src->Errors)
-    Dst->Errors.push_back(std::move(ErrorPair));
-  Src->Errors.clear();
-
-  if (Error E = Dst->Writer.mergeProfileKind(Src->Writer.getProfileKind()))
-    exitWithError(std::move(E));
-
-  Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
-    auto [ErrorCode, Msg] = InstrProfError::take(std::move(E));
-    std::unique_lock<std::mutex> ErrGuard{Dst->ErrLock};
-    bool firstTime = Dst->WriterErrorCodes.insert(ErrorCode).second;
-    if (firstTime)
-      warn(toString(make_error<InstrProfError>(ErrorCode, Msg)));
-  });
-}
-
-static void writeInstrProfile(StringRef OutputFilename,
-                              ProfileFormat OutputFormat,
-                              InstrProfWriter &Writer) {
-  std::error_code EC;
-  raw_fd_ostream Output(OutputFilename.data(), EC,
-                        OutputFormat == PF_Text ? sys::fs::OF_TextWithCRLF
-                                                : sys::fs::OF_None);
-  if (EC)
-    exitWithErrorCode(EC, OutputFilename);
-
-  if (OutputFormat == PF_Text) {
-    if (Error E = Writer.writeText(Output))
-      warn(std::move(E));
-  } else {
-    if (Output.is_displayed())
-      exitWithError("cannot write a non-text format profile to the terminal");
-    if (Error E = Writer.write(Output))
-      warn(std::move(E));
-  }
-}
-
-// Common options.
-cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                    cl::init("-"), cl::desc("Output file"),
-                                    cl::sub(ShowSubcommand),
-                                    cl::sub(OrderSubcommand),
-                                    cl::sub(OverlapSubcommand),
-                                    cl::sub(MergeSubcommand));
-// 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));
-
-// Options common to at least two commands.
-cl::opt<ProfileKinds> ProfileKind(
-    cl::desc("Profile kind:"), cl::sub(MergeSubcommand),
-    cl::sub(OverlapSubcommand), cl::init(instr),
-    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
-               clEnumVal(sample, "Sample profile")));
-cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"),
-                              cl::sub(ShowSubcommand),
-                              cl::sub(OrderSubcommand));
-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::sub(MergeSubcommand), cl::sub(ShowSubcommand), cl::init(5));
-cl::opt<std::string> ProfiledBinary(
-    "profiled-binary", cl::init(""),
-    cl::desc("Path to binary from which the profile was collected."),
-    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
-cl::opt<std::string> DebugInfoFilename(
-    "debug-info", cl::init(""),
-    cl::desc(
-        "For show, read and extract profile metadata from debug info and show "
-        "the functions it found. For merge, use the provided debug info to "
-        "correlate the raw profile."),
-    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
-
-// Options specific to merge subcommand.
-cl::list<std::string> InputFilenames(cl::Positional, cl::sub(MergeSubcommand),
-                                     cl::desc("<filename...>"));
-cl::list<std::string> WeightedInputFilenames("weighted-input",
-                                             cl::sub(MergeSubcommand),
-                                             cl::desc("<weight>,<filename>"));
-cl::opt<ProfileFormat> OutputFormat(
-    cl::desc("Format of output profile"), cl::sub(MergeSubcommand),
-    cl::init(PF_Ext_Binary),
-    cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding"),
-               clEnumValN(PF_Ext_Binary, "extbinary",
-                          "Extensible binary encoding "
-                          "(default)"),
-               clEnumValN(PF_Text, "text", "Text encoding"),
-               clEnumValN(PF_GCC, "gcc",
-                          "GCC encoding (only meaningful for -sample)")));
-cl::opt<std::string>
-    InputFilenamesFile("input-files", cl::init(""), cl::sub(MergeSubcommand),
-                       cl::desc("Path to file containing newline-separated "
-                                "[<weight>,]<filename> entries"));
-cl::alias InputFilenamesFileA("f", cl::desc("Alias for --input-files"),
-                              cl::aliasopt(InputFilenamesFile));
-cl::opt<bool> DumpInputFileList(
-    "dump-input-file-list", cl::init(false), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("Dump the list of input files and their weights, then exit"));
-cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
-                                   cl::sub(MergeSubcommand),
-                                   cl::desc("Symbol remapping file"));
-cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
-                         cl::aliasopt(RemappingFile));
-cl::opt<bool>
-    UseMD5("use-md5", cl::init(false), cl::Hidden,
-           cl::desc("Choose to use MD5 to represent string in name table (only "
-                    "meaningful for -extbinary)"),
-           cl::sub(MergeSubcommand));
-cl::opt<bool> CompressAllSections(
-    "compress-all-sections", cl::init(false), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("Compress all sections when writing the profile (only "
-             "meaningful for -extbinary)"));
-cl::opt<bool> SampleMergeColdContext(
-    "sample-merge-cold-context", cl::init(false), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc(
-        "Merge context sample profiles whose count is below cold threshold"));
-cl::opt<bool> SampleTrimColdContext(
-    "sample-trim-cold-context", cl::init(false), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc(
-        "Trim context sample profiles whose count is below cold threshold"));
-cl::opt<uint32_t> SampleColdContextFrameDepth(
-    "sample-frame-depth-for-cold-context", cl::init(1),
-    cl::sub(MergeSubcommand),
-    cl::desc("Keep the last K frames while merging cold profile. 1 means the "
-             "context-less base profile"));
-cl::opt<size_t> OutputSizeLimit(
-    "output-size-limit", cl::init(0), cl::Hidden, cl::sub(MergeSubcommand),
-    cl::desc("Trim cold functions until profile size is below specified "
-             "limit in bytes. This uses a heursitic and functions may be "
-             "excessively trimmed"));
-cl::opt<bool> GenPartialProfile(
-    "gen-partial-profile", cl::init(false), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
-cl::opt<std::string> SupplInstrWithSample(
-    "supplement-instr-with-sample", cl::init(""), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("Supplement an instr profile with sample profile, to correct "
-             "the profile unrepresentativeness issue. The sample "
-             "profile is the input of the flag. Output will be in instr "
-             "format (The flag only works with -instr)"));
-cl::opt<float> ZeroCounterThreshold(
-    "zero-counter-threshold", cl::init(0.7), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("For the function which is cold in instr profile but hot in "
-             "sample profile, if the ratio of the number of zero counters "
-             "divided by the total number of counters is above the "
-             "threshold, the profile of the function will be regarded as "
-             "being harmful for performance and will be dropped."));
-cl::opt<unsigned> SupplMinSizeThreshold(
-    "suppl-min-size-threshold", cl::init(10), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("If the size of a function is smaller than the threshold, "
-             "assume it can be inlined by PGO early inliner and it won't "
-             "be adjusted based on sample profile."));
-cl::opt<unsigned> InstrProfColdThreshold(
-    "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("User specified cold threshold for instr profile which will "
-             "override the cold threshold got from profile summary. "));
-// WARNING: This reservoir size value is propagated to any input indexed
-// profiles for simplicity. Changing this value between invocations could
-// result in sample bias.
-cl::opt<uint64_t> TemporalProfTraceReservoirSize(
-    "temporal-profile-trace-reservoir-size", cl::init(100),
-    cl::sub(MergeSubcommand),
-    cl::desc("The maximum number of stored temporal profile traces (default: "
-             "100)"));
-cl::opt<uint64_t> TemporalProfMaxTraceLength(
-    "temporal-profile-max-trace-length", cl::init(10000),
-    cl::sub(MergeSubcommand),
-    cl::desc("The maximum length of a single temporal profile trace "
-             "(default: 10000)"));
+  }
 
-cl::opt<FailureMode>
-    FailMode("failure-mode", cl::init(failIfAnyAreInvalid),
-             cl::desc("Failure mode:"), cl::sub(MergeSubcommand),
-             cl::values(clEnumValN(warnOnly, "warn",
-                                   "Do not fail and just print warnings."),
-                        clEnumValN(failIfAnyAreInvalid, "any",
-                                   "Fail if any profile is invalid."),
-                        clEnumValN(failIfAllAreInvalid, "all",
-                                   "Fail only if all profiles are invalid.")));
+  auto Reader = std::move(ReaderOrErr.get());
+  if (Error E = WC->Writer.mergeProfileKind(Reader->getProfileKind())) {
+    consumeError(std::move(E));
+    WC->Errors.emplace_back(
+        make_error<StringError>(
+            "Merge IR generated profile with Clang generated profile.",
+            std::error_code()),
+        Filename);
+    return;
+  }
 
-cl::opt<bool> OutputSparse(
-    "sparse", cl::init(false), cl::sub(MergeSubcommand),
-    cl::desc("Generate a sparse profile (only meaningful for -instr)"));
-cl::opt<unsigned> NumThreads(
-    "num-threads", cl::init(0), cl::sub(MergeSubcommand),
-    cl::desc("Number of merge threads to use (default: autodetect)"));
-cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
-                      cl::aliasopt(NumThreads));
+  for (auto &I : *Reader) {
+    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) {
+        consumeError(std::move(E));
+        return;
+      }
+      Reported = true;
+      // Only show hint the first time an error occurs.
+      auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
+      std::unique_lock<std::mutex> ErrGuard{WC->ErrLock};
+      bool firstTime = WC->WriterErrorCodes.insert(ErrCode).second;
+      handleMergeWriterError(make_error<InstrProfError>(ErrCode, Msg),
+                             Input.Filename, FuncName, firstTime);
+    });
+  }
 
-cl::opt<std::string> ProfileSymbolListFile(
-    "prof-sym-list", cl::init(""), cl::sub(MergeSubcommand),
-    cl::desc("Path to file containing the list of function symbols "
-             "used to populate profile symbol list"));
+  if (Reader->hasTemporalProfile()) {
+    auto &Traces = Reader->getTemporalProfTraces(Input.Weight);
+    if (!Traces.empty())
+      WC->Writer.addTemporalProfileTraces(
+          Traces, Reader->getTemporalProfTraceStreamSize());
+  }
+  if (Reader->hasError()) {
+    if (Error E = Reader->getError()) {
+      WC->Errors.emplace_back(std::move(E), Filename);
+      return;
+    }
+  }
 
-cl::opt<SampleProfileLayout> ProfileLayout(
-    "convert-sample-profile-layout",
-    cl::desc("Convert the generated profile to a profile with a new layout"),
-    cl::sub(MergeSubcommand), cl::init(SPL_None),
-    cl::values(
-        clEnumValN(SPL_Nest, "nest",
-                   "Nested profile, the input should be CS flat profile"),
-        clEnumValN(SPL_Flat, "flat",
-                   "Profile with nested inlinee flatten out")));
+  std::vector<llvm::object::BuildID> BinaryIds;
+  if (Error E = Reader->readBinaryIds(BinaryIds)) {
+    WC->Errors.emplace_back(std::move(E), Filename);
+    return;
+  }
+  WC->Writer.addBinaryIds(BinaryIds);
 
-cl::opt<bool> DropProfileSymbolList(
-    "drop-profile-symbol-list", cl::init(false), cl::Hidden,
-    cl::sub(MergeSubcommand),
-    cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
-             "(only meaningful for -sample)"));
+  if (ReaderWarning) {
+    WC->Errors.emplace_back(std::move(ReaderWarning->first),
+                            ReaderWarning->second);
+  }
+}
+
+/// Merge the \p Src writer context into \p Dst.
+static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
+  for (auto &ErrorPair : Src->Errors)
+    Dst->Errors.push_back(std::move(ErrorPair));
+  Src->Errors.clear();
+
+  if (Error E = Dst->Writer.mergeProfileKind(Src->Writer.getProfileKind()))
+    exitWithError(std::move(E));
+
+  Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
+    auto [ErrorCode, Msg] = InstrProfError::take(std::move(E));
+    std::unique_lock<std::mutex> ErrGuard{Dst->ErrLock};
+    bool firstTime = Dst->WriterErrorCodes.insert(ErrorCode).second;
+    if (firstTime)
+      warn(toString(make_error<InstrProfError>(ErrorCode, Msg)));
+  });
+}
+
+static void writeInstrProfile(StringRef OutputFilename,
+                              ProfileFormat OutputFormat,
+                              InstrProfWriter &Writer) {
+  std::error_code EC;
+  raw_fd_ostream Output(OutputFilename.data(), EC,
+                        OutputFormat == PF_Text ? sys::fs::OF_TextWithCRLF
+                                                : sys::fs::OF_None);
+  if (EC)
+    exitWithErrorCode(EC, OutputFilename);
+
+  if (OutputFormat == PF_Text) {
+    if (Error E = Writer.writeText(Output))
+      warn(std::move(E));
+  } else {
+    if (Output.is_displayed())
+      exitWithError("cannot write a non-text format profile to the terminal");
+    if (Error E = Writer.write(Output))
+      warn(std::move(E));
+  }
+}
 
 static void mergeInstrProfile(const WeightedFileVector &Inputs,
                               SymbolRemapper *Remapper,
@@ -1428,40 +1570,6 @@ static int merge_main(int argc, const char *argv[]) {
   return 0;
 }
 
-// Overlap options.
-cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
-                                  cl::desc("<base profile file>"),
-                                  cl::sub(OverlapSubcommand));
-cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
-                                  cl::desc("<test profile file>"),
-                                  cl::sub(OverlapSubcommand));
-
-cl::opt<unsigned long long> SimilarityCutoff(
-    "similarity-cutoff", cl::init(0),
-    cl::desc("For sample profiles, list function names (with calling context "
-             "for csspgo) for overlapped functions "
-             "with similarities below the cutoff (percentage times 10000)."),
-    cl::sub(OverlapSubcommand));
-
-cl::opt<bool> IsCS(
-    "cs", cl::init(false),
-    cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."),
-    cl::sub(OverlapSubcommand));
-
-cl::opt<std::string> FuncNameFilter(
-    "function",
-    cl::desc("Details for matching functions. For overlapping CSSPGO, this "
-             "takes a function name with calling context."),
-    cl::sub(ShowSubcommand), cl::sub(OverlapSubcommand));
-
-cl::opt<unsigned long long> OverlapValueCutoff(
-    "value-cutoff", cl::init(-1),
-    cl::desc(
-        "Function level overlap information for every function (with calling "
-        "context for csspgo) in test "
-        "profile with max count value greater then the parameter value"),
-    cl::sub(OverlapSubcommand));
-
 /// Computer the overlap b/w profile BaseFilename and profile TestFilename.
 static void overlapInstrProfile(const std::string &BaseFilename,
                                 const std::string &TestFilename,
@@ -2446,104 +2554,6 @@ struct ValueSitesStats {
 };
 } // namespace
 
-// Options unique to show subcommand.
-// TODO: Consider creating a template class ShowOption to factor out the common
-// cl::sub in cl::opt constructor.
-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::sub(ShowSubcommand),
-            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::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<ProfileKinds> ShowProfileKind(
-    cl::desc("Profile kind supported by show:"), 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> ShowValueCutoff(
-    "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<bool>
-    ShowCovered("covered", cl::init(false),
-                cl::desc("Show only the functions that have been executed."),
-                cl::sub(ShowSubcommand));
-
-cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
-                                 cl::desc("Show profile version. "),
-                                 cl::sub(ShowSubcommand));
-
 static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK,
                                   ValueSitesStats &Stats, raw_fd_ostream &OS,
                                   InstrProfSymtab *Symtab) {



More information about the cfe-commits mailing list