Skip to content

[nfc][llvm-profdata] Use cl::Subcommand to organize subcommand and options in llvm-profdata #71328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/Support/CommandLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Support/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
227 changes: 133 additions & 94 deletions llvm/tools/llvm-profdata/llvm-profdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "----";
Expand Down Expand Up @@ -2950,99 +2952,130 @@ 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"));
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

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 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())
Expand All @@ -3051,7 +3084,7 @@ static int show_main(int argc, const char *argv[]) {
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;
}
Expand Down Expand Up @@ -3130,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_main},
{"order", order_main},
{"overlap", overlap_main},
};
Expand All @@ -3154,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) {

Expand Down