xref: /llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.cpp (revision 1ad3180b4a07ccf7cc371882c4e10ec2667adea8)
131c2cf11SZain Jaffal //===- RemarkCounter.cpp --------------------------------------------------===//
231c2cf11SZain Jaffal //
331c2cf11SZain Jaffal // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
431c2cf11SZain Jaffal // See https://llvm.org/LICENSE.txt for license information.
531c2cf11SZain Jaffal // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
631c2cf11SZain Jaffal //
731c2cf11SZain Jaffal //===----------------------------------------------------------------------===//
831c2cf11SZain Jaffal //
931c2cf11SZain Jaffal // Generic tool to count remarks based on properties
1031c2cf11SZain Jaffal //
1131c2cf11SZain Jaffal //===----------------------------------------------------------------------===//
1231c2cf11SZain Jaffal 
1331c2cf11SZain Jaffal #include "RemarkCounter.h"
1431c2cf11SZain Jaffal #include "RemarkUtilRegistry.h"
1531c2cf11SZain Jaffal #include "llvm/Support/CommandLine.h"
1631c2cf11SZain Jaffal #include "llvm/Support/Regex.h"
1731c2cf11SZain Jaffal 
1831c2cf11SZain Jaffal using namespace llvm;
1931c2cf11SZain Jaffal using namespace remarks;
2031c2cf11SZain Jaffal using namespace llvm::remarkutil;
2131c2cf11SZain Jaffal 
2231c2cf11SZain Jaffal static cl::SubCommand CountSub("count",
2331c2cf11SZain Jaffal                                "Collect remarks based on specified criteria.");
2431c2cf11SZain Jaffal 
2531c2cf11SZain Jaffal INPUT_FORMAT_COMMAND_LINE_OPTIONS(CountSub)
2631c2cf11SZain Jaffal INPUT_OUTPUT_COMMAND_LINE_OPTIONS(CountSub)
2731c2cf11SZain Jaffal 
2831c2cf11SZain Jaffal static cl::list<std::string>
2931c2cf11SZain Jaffal     Keys("args", cl::desc("Specify remark argument/s to count by."),
3031c2cf11SZain Jaffal          cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional);
3131c2cf11SZain Jaffal static cl::list<std::string> RKeys(
3231c2cf11SZain Jaffal     "rargs",
3331c2cf11SZain Jaffal     cl::desc(
3431c2cf11SZain Jaffal         "Specify remark argument/s to count (accepts regular expressions)."),
3531c2cf11SZain Jaffal     cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional);
3631c2cf11SZain Jaffal static cl::opt<std::string>
3731c2cf11SZain Jaffal     RemarkNameOpt("remark-name",
3831c2cf11SZain Jaffal                   cl::desc("Optional remark name to filter collection by."),
3931c2cf11SZain Jaffal                   cl::ValueOptional, cl::sub(CountSub));
4031c2cf11SZain Jaffal static cl::opt<std::string>
4131c2cf11SZain Jaffal     PassNameOpt("pass-name", cl::ValueOptional,
4231c2cf11SZain Jaffal                 cl::desc("Optional remark pass name to filter collection by."),
4331c2cf11SZain Jaffal                 cl::sub(CountSub));
4431c2cf11SZain Jaffal 
4531c2cf11SZain Jaffal static cl::opt<std::string> RemarkFilterArgByOpt(
4631c2cf11SZain Jaffal     "filter-arg-by", cl::desc("Optional remark arg to filter collection by."),
4731c2cf11SZain Jaffal     cl::ValueOptional, cl::sub(CountSub));
4831c2cf11SZain Jaffal static cl::opt<std::string>
4931c2cf11SZain Jaffal     RemarkNameOptRE("rremark-name",
5031c2cf11SZain Jaffal                     cl::desc("Optional remark name to filter collection by "
5131c2cf11SZain Jaffal                              "(accepts regular expressions)."),
5231c2cf11SZain Jaffal                     cl::ValueOptional, cl::sub(CountSub));
5331c2cf11SZain Jaffal static cl::opt<std::string>
5431c2cf11SZain Jaffal     RemarkArgFilterOptRE("rfilter-arg-by",
5531c2cf11SZain Jaffal                          cl::desc("Optional remark arg to filter collection by "
5631c2cf11SZain Jaffal                                   "(accepts regular expressions)."),
5731c2cf11SZain Jaffal                          cl::sub(CountSub), cl::ValueOptional);
5831c2cf11SZain Jaffal static cl::opt<std::string>
5931c2cf11SZain Jaffal     PassNameOptRE("rpass-name", cl::ValueOptional,
6031c2cf11SZain Jaffal                   cl::desc("Optional remark pass name to filter collection "
6131c2cf11SZain Jaffal                            "by (accepts regular expressions)."),
6231c2cf11SZain Jaffal                   cl::sub(CountSub));
6331c2cf11SZain Jaffal static cl::opt<Type> RemarkTypeOpt(
6431c2cf11SZain Jaffal     "remark-type", cl::desc("Optional remark type to filter collection by."),
6531c2cf11SZain Jaffal     cl::values(clEnumValN(Type::Unknown, "unknown", "UNKOWN"),
6631c2cf11SZain Jaffal                clEnumValN(Type::Passed, "passed", "PASSED"),
6731c2cf11SZain Jaffal                clEnumValN(Type::Missed, "missed", "MISSED"),
6831c2cf11SZain Jaffal                clEnumValN(Type::Analysis, "analysis", "ANALYSIS"),
6931c2cf11SZain Jaffal                clEnumValN(Type::AnalysisFPCommute, "analysis-fp-commute",
7031c2cf11SZain Jaffal                           "ANALYSIS_FP_COMMUTE"),
7131c2cf11SZain Jaffal                clEnumValN(Type::AnalysisAliasing, "analysis-aliasing",
7231c2cf11SZain Jaffal                           "ANALYSIS_ALIASING"),
7331c2cf11SZain Jaffal                clEnumValN(Type::Failure, "failure", "FAILURE")),
7431c2cf11SZain Jaffal     cl::init(Type::Failure), cl::sub(CountSub));
7531c2cf11SZain Jaffal static cl::opt<CountBy> CountByOpt(
7631c2cf11SZain Jaffal     "count-by", cl::desc("Specify the property to collect remarks by."),
7731c2cf11SZain Jaffal     cl::values(
7831c2cf11SZain Jaffal         clEnumValN(CountBy::REMARK, "remark-name",
7931c2cf11SZain Jaffal                    "Counts individual remarks based on how many of the remark "
8031c2cf11SZain Jaffal                    "exists."),
8131c2cf11SZain Jaffal         clEnumValN(CountBy::ARGUMENT, "arg",
8231c2cf11SZain Jaffal                    "Counts based on the value each specified argument has. The "
8331c2cf11SZain Jaffal                    "argument has to have a number value to be considered.")),
8431c2cf11SZain Jaffal     cl::init(CountBy::REMARK), cl::sub(CountSub));
8531c2cf11SZain Jaffal static cl::opt<GroupBy> GroupByOpt(
8631c2cf11SZain Jaffal     "group-by", cl::desc("Specify the property to group remarks by."),
8731c2cf11SZain Jaffal     cl::values(
8831c2cf11SZain Jaffal         clEnumValN(
8931c2cf11SZain Jaffal             GroupBy::PER_SOURCE, "source",
9031c2cf11SZain Jaffal             "Display the count broken down by the filepath of each remark "
9131c2cf11SZain Jaffal             "emitted. Requires remarks to have DebugLoc information."),
9231c2cf11SZain Jaffal         clEnumValN(GroupBy::PER_FUNCTION, "function",
9331c2cf11SZain Jaffal                    "Breakdown the count by function name."),
9431c2cf11SZain Jaffal         clEnumValN(
9531c2cf11SZain Jaffal             GroupBy::PER_FUNCTION_WITH_DEBUG_LOC, "function-with-loc",
9631c2cf11SZain Jaffal             "Breakdown the count by function name taking into consideration "
9731c2cf11SZain Jaffal             "the filepath info from the DebugLoc of the remark."),
9831c2cf11SZain Jaffal         clEnumValN(GroupBy::TOTAL, "total",
9931c2cf11SZain Jaffal                    "Output the total number corresponding to the count for the "
10031c2cf11SZain Jaffal                    "provided input file.")),
10131c2cf11SZain Jaffal     cl::init(GroupBy::PER_SOURCE), cl::sub(CountSub));
10231c2cf11SZain Jaffal 
10331c2cf11SZain Jaffal /// Look for matching argument with \p Key in \p Remark and return the parsed
10431c2cf11SZain Jaffal /// integer value or 0 if it is has no integer value.
10531c2cf11SZain Jaffal static unsigned getValForKey(StringRef Key, const Remark &Remark) {
10631c2cf11SZain Jaffal   auto *RemarkArg = find_if(Remark.Args, [&Key](const Argument &Arg) {
10731c2cf11SZain Jaffal     return Arg.Key == Key && Arg.isValInt();
10831c2cf11SZain Jaffal   });
10931c2cf11SZain Jaffal   if (RemarkArg == Remark.Args.end())
11031c2cf11SZain Jaffal     return 0;
11131c2cf11SZain Jaffal   return *RemarkArg->getValAsInt();
11231c2cf11SZain Jaffal }
11331c2cf11SZain Jaffal 
11431c2cf11SZain Jaffal Error Filters::regexArgumentsValid() {
11531c2cf11SZain Jaffal   if (RemarkNameFilter && RemarkNameFilter->IsRegex)
11631c2cf11SZain Jaffal     if (auto E = checkRegex(RemarkNameFilter->FilterRE))
11731c2cf11SZain Jaffal       return E;
11831c2cf11SZain Jaffal   if (PassNameFilter && PassNameFilter->IsRegex)
11931c2cf11SZain Jaffal     if (auto E = checkRegex(PassNameFilter->FilterRE))
12031c2cf11SZain Jaffal       return E;
12131c2cf11SZain Jaffal   if (ArgFilter && ArgFilter->IsRegex)
12231c2cf11SZain Jaffal     if (auto E = checkRegex(ArgFilter->FilterRE))
12331c2cf11SZain Jaffal       return E;
12431c2cf11SZain Jaffal   return Error::success();
12531c2cf11SZain Jaffal }
12631c2cf11SZain Jaffal 
12731c2cf11SZain Jaffal bool Filters::filterRemark(const Remark &Remark) {
12831c2cf11SZain Jaffal   if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
12931c2cf11SZain Jaffal     return false;
13031c2cf11SZain Jaffal   if (PassNameFilter && !PassNameFilter->match(Remark.PassName))
13131c2cf11SZain Jaffal     return false;
13231c2cf11SZain Jaffal   if (RemarkTypeFilter)
13331c2cf11SZain Jaffal     return *RemarkTypeFilter == Remark.RemarkType;
13431c2cf11SZain Jaffal   if (ArgFilter) {
13531c2cf11SZain Jaffal     if (!any_of(Remark.Args,
13631c2cf11SZain Jaffal                 [this](Argument Arg) { return ArgFilter->match(Arg.Val); }))
13731c2cf11SZain Jaffal       return false;
13831c2cf11SZain Jaffal   }
13931c2cf11SZain Jaffal   return true;
14031c2cf11SZain Jaffal }
14131c2cf11SZain Jaffal 
14231c2cf11SZain Jaffal Error ArgumentCounter::getAllMatchingArgumentsInRemark(
14331c2cf11SZain Jaffal     StringRef Buffer, ArrayRef<FilterMatcher> Arguments, Filters &Filter) {
14431c2cf11SZain Jaffal   auto MaybeParser = createRemarkParser(InputFormat, Buffer);
14531c2cf11SZain Jaffal   if (!MaybeParser)
14631c2cf11SZain Jaffal     return MaybeParser.takeError();
14731c2cf11SZain Jaffal   auto &Parser = **MaybeParser;
14831c2cf11SZain Jaffal   auto MaybeRemark = Parser.next();
14931c2cf11SZain Jaffal   for (; MaybeRemark; MaybeRemark = Parser.next()) {
15031c2cf11SZain Jaffal     auto &Remark = **MaybeRemark;
15131c2cf11SZain Jaffal     // Only collect keys from remarks included in the filter.
15231c2cf11SZain Jaffal     if (!Filter.filterRemark(Remark))
15331c2cf11SZain Jaffal       continue;
15431c2cf11SZain Jaffal     for (auto &Key : Arguments) {
15531c2cf11SZain Jaffal       for (Argument Arg : Remark.Args)
15631c2cf11SZain Jaffal         if (Key.match(Arg.Key) && Arg.isValInt())
15731c2cf11SZain Jaffal           ArgumentSetIdxMap.insert({Arg.Key, ArgumentSetIdxMap.size()});
15831c2cf11SZain Jaffal     }
15931c2cf11SZain Jaffal   }
16031c2cf11SZain Jaffal 
16131c2cf11SZain Jaffal   auto E = MaybeRemark.takeError();
16231c2cf11SZain Jaffal   if (!E.isA<EndOfFileError>())
16331c2cf11SZain Jaffal     return E;
16431c2cf11SZain Jaffal   consumeError(std::move(E));
16531c2cf11SZain Jaffal   return Error::success();
16631c2cf11SZain Jaffal }
16731c2cf11SZain Jaffal 
16831c2cf11SZain Jaffal std::optional<std::string> Counter::getGroupByKey(const Remark &Remark) {
1690603737aSFangrui Song   switch (Group) {
17031c2cf11SZain Jaffal   case GroupBy::PER_FUNCTION:
17131c2cf11SZain Jaffal     return Remark.FunctionName.str();
17231c2cf11SZain Jaffal   case GroupBy::TOTAL:
17331c2cf11SZain Jaffal     return "Total";
17431c2cf11SZain Jaffal   case GroupBy::PER_SOURCE:
17531c2cf11SZain Jaffal   case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:
17631c2cf11SZain Jaffal     if (!Remark.Loc.has_value())
17731c2cf11SZain Jaffal       return std::nullopt;
17831c2cf11SZain Jaffal 
1790603737aSFangrui Song     if (Group == GroupBy::PER_FUNCTION_WITH_DEBUG_LOC)
18031c2cf11SZain Jaffal       return Remark.Loc->SourceFilePath.str() + ":" + Remark.FunctionName.str();
18131c2cf11SZain Jaffal     return Remark.Loc->SourceFilePath.str();
18231c2cf11SZain Jaffal   }
1834f469450SMartin Storsjö   llvm_unreachable("Fully covered switch above!");
18431c2cf11SZain Jaffal }
18531c2cf11SZain Jaffal 
18631c2cf11SZain Jaffal void ArgumentCounter::collect(const Remark &Remark) {
18731c2cf11SZain Jaffal   SmallVector<unsigned, 4> Row(ArgumentSetIdxMap.size());
18831c2cf11SZain Jaffal   std::optional<std::string> GroupByKey = getGroupByKey(Remark);
18931c2cf11SZain Jaffal   // Early return if we don't have a value
19031c2cf11SZain Jaffal   if (!GroupByKey)
19131c2cf11SZain Jaffal     return;
19231c2cf11SZain Jaffal   auto GroupVal = *GroupByKey;
19331c2cf11SZain Jaffal   CountByKeysMap.insert({GroupVal, Row});
19431c2cf11SZain Jaffal   for (auto [Key, Idx] : ArgumentSetIdxMap) {
19531c2cf11SZain Jaffal     auto Count = getValForKey(Key, Remark);
19631c2cf11SZain Jaffal     CountByKeysMap[GroupVal][Idx] += Count;
19731c2cf11SZain Jaffal   }
19831c2cf11SZain Jaffal }
19931c2cf11SZain Jaffal 
20031c2cf11SZain Jaffal void RemarkCounter::collect(const Remark &Remark) {
201*1ad3180bSKazu Hirata   if (std::optional<std::string> Key = getGroupByKey(Remark))
202*1ad3180bSKazu Hirata     ++CountedByRemarksMap[*Key];
20331c2cf11SZain Jaffal }
20431c2cf11SZain Jaffal 
20531c2cf11SZain Jaffal Error ArgumentCounter::print(StringRef OutputFileName) {
20631c2cf11SZain Jaffal   auto MaybeOF =
20731c2cf11SZain Jaffal       getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
20831c2cf11SZain Jaffal   if (!MaybeOF)
20931c2cf11SZain Jaffal     return MaybeOF.takeError();
21031c2cf11SZain Jaffal 
21131c2cf11SZain Jaffal   auto OF = std::move(*MaybeOF);
2120603737aSFangrui Song   OF->os() << groupByToStr(Group) << ",";
21331c2cf11SZain Jaffal   unsigned Idx = 0;
21431c2cf11SZain Jaffal   for (auto [Key, _] : ArgumentSetIdxMap) {
21531c2cf11SZain Jaffal     OF->os() << Key;
21631c2cf11SZain Jaffal     if (Idx != ArgumentSetIdxMap.size() - 1)
21731c2cf11SZain Jaffal       OF->os() << ",";
21831c2cf11SZain Jaffal     Idx++;
21931c2cf11SZain Jaffal   }
22031c2cf11SZain Jaffal   OF->os() << "\n";
22131c2cf11SZain Jaffal   for (auto [Header, CountVector] : CountByKeysMap) {
22231c2cf11SZain Jaffal     OF->os() << Header << ",";
22331c2cf11SZain Jaffal     unsigned Idx = 0;
22431c2cf11SZain Jaffal     for (auto Count : CountVector) {
22531c2cf11SZain Jaffal       OF->os() << Count;
22631c2cf11SZain Jaffal       if (Idx != ArgumentSetIdxMap.size() - 1)
22731c2cf11SZain Jaffal         OF->os() << ",";
22831c2cf11SZain Jaffal       Idx++;
22931c2cf11SZain Jaffal     }
23031c2cf11SZain Jaffal     OF->os() << "\n";
23131c2cf11SZain Jaffal   }
23231c2cf11SZain Jaffal   return Error::success();
23331c2cf11SZain Jaffal }
23431c2cf11SZain Jaffal 
23531c2cf11SZain Jaffal Error RemarkCounter::print(StringRef OutputFileName) {
23631c2cf11SZain Jaffal   auto MaybeOF =
23731c2cf11SZain Jaffal       getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
23831c2cf11SZain Jaffal   if (!MaybeOF)
23931c2cf11SZain Jaffal     return MaybeOF.takeError();
24031c2cf11SZain Jaffal 
24131c2cf11SZain Jaffal   auto OF = std::move(*MaybeOF);
2420603737aSFangrui Song   OF->os() << groupByToStr(Group) << ","
24331c2cf11SZain Jaffal            << "Count\n";
24431c2cf11SZain Jaffal   for (auto [Key, Count] : CountedByRemarksMap)
24531c2cf11SZain Jaffal     OF->os() << Key << "," << Count << "\n";
24631c2cf11SZain Jaffal   OF->keep();
24731c2cf11SZain Jaffal   return Error::success();
24831c2cf11SZain Jaffal }
24931c2cf11SZain Jaffal 
25031c2cf11SZain Jaffal Expected<Filters> getRemarkFilter() {
25131c2cf11SZain Jaffal   // Create Filter properties.
25231c2cf11SZain Jaffal   std::optional<FilterMatcher> RemarkNameFilter;
25331c2cf11SZain Jaffal   std::optional<FilterMatcher> PassNameFilter;
25431c2cf11SZain Jaffal   std::optional<FilterMatcher> RemarkArgFilter;
25531c2cf11SZain Jaffal   std::optional<Type> RemarkType;
25631c2cf11SZain Jaffal   if (!RemarkNameOpt.empty())
25731c2cf11SZain Jaffal     RemarkNameFilter = {RemarkNameOpt, false};
25831c2cf11SZain Jaffal   else if (!RemarkNameOptRE.empty())
25931c2cf11SZain Jaffal     RemarkNameFilter = {RemarkNameOptRE, true};
26031c2cf11SZain Jaffal   if (!PassNameOpt.empty())
26131c2cf11SZain Jaffal     PassNameFilter = {PassNameOpt, false};
26231c2cf11SZain Jaffal   else if (!PassNameOptRE.empty())
26331c2cf11SZain Jaffal     PassNameFilter = {PassNameOptRE, true};
26431c2cf11SZain Jaffal   if (RemarkTypeOpt != Type::Failure)
26531c2cf11SZain Jaffal     RemarkType = RemarkTypeOpt;
26631c2cf11SZain Jaffal   if (!RemarkFilterArgByOpt.empty())
26731c2cf11SZain Jaffal     RemarkArgFilter = {RemarkFilterArgByOpt, false};
26831c2cf11SZain Jaffal   else if (!RemarkArgFilterOptRE.empty())
26931c2cf11SZain Jaffal     RemarkArgFilter = {RemarkArgFilterOptRE, true};
27031c2cf11SZain Jaffal   // Create RemarkFilter.
27131c2cf11SZain Jaffal   return Filters::createRemarkFilter(std::move(RemarkNameFilter),
27231c2cf11SZain Jaffal                                      std::move(PassNameFilter),
27331c2cf11SZain Jaffal                                      std::move(RemarkArgFilter), RemarkType);
27431c2cf11SZain Jaffal }
27531c2cf11SZain Jaffal 
27631c2cf11SZain Jaffal Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) {
27731c2cf11SZain Jaffal   // Create Parser.
27831c2cf11SZain Jaffal   auto MaybeParser = createRemarkParser(InputFormat, Buffer);
27931c2cf11SZain Jaffal   if (!MaybeParser)
28031c2cf11SZain Jaffal     return MaybeParser.takeError();
28131c2cf11SZain Jaffal   auto &Parser = **MaybeParser;
28231c2cf11SZain Jaffal   auto MaybeRemark = Parser.next();
28331c2cf11SZain Jaffal   for (; MaybeRemark; MaybeRemark = Parser.next()) {
28431c2cf11SZain Jaffal     const Remark &Remark = **MaybeRemark;
28531c2cf11SZain Jaffal     if (Filter.filterRemark(Remark))
28631c2cf11SZain Jaffal       Counter.collect(Remark);
28731c2cf11SZain Jaffal   }
28831c2cf11SZain Jaffal 
28931c2cf11SZain Jaffal   if (auto E = Counter.print(OutputFileName))
29031c2cf11SZain Jaffal     return E;
29131c2cf11SZain Jaffal   auto E = MaybeRemark.takeError();
29231c2cf11SZain Jaffal   if (!E.isA<EndOfFileError>())
29331c2cf11SZain Jaffal     return E;
29431c2cf11SZain Jaffal   consumeError(std::move(E));
29531c2cf11SZain Jaffal   return Error::success();
29631c2cf11SZain Jaffal }
29731c2cf11SZain Jaffal 
29831c2cf11SZain Jaffal static Error collectRemarks() {
29931c2cf11SZain Jaffal   // Create a parser for the user-specified input format.
30031c2cf11SZain Jaffal   auto MaybeBuf = getInputMemoryBuffer(InputFileName);
30131c2cf11SZain Jaffal   if (!MaybeBuf)
30231c2cf11SZain Jaffal     return MaybeBuf.takeError();
30331c2cf11SZain Jaffal   StringRef Buffer = (*MaybeBuf)->getBuffer();
30431c2cf11SZain Jaffal   auto MaybeFilter = getRemarkFilter();
30531c2cf11SZain Jaffal   if (!MaybeFilter)
30631c2cf11SZain Jaffal     return MaybeFilter.takeError();
30731c2cf11SZain Jaffal   auto &Filter = *MaybeFilter;
30831c2cf11SZain Jaffal   if (CountByOpt == CountBy::REMARK) {
30931c2cf11SZain Jaffal     RemarkCounter RC(GroupByOpt);
31031c2cf11SZain Jaffal     if (auto E = useCollectRemark(Buffer, RC, Filter))
31131c2cf11SZain Jaffal       return E;
31231c2cf11SZain Jaffal   } else if (CountByOpt == CountBy::ARGUMENT) {
31331c2cf11SZain Jaffal     SmallVector<FilterMatcher, 4> ArgumentsVector;
31431c2cf11SZain Jaffal     if (!Keys.empty()) {
31531c2cf11SZain Jaffal       for (auto &Key : Keys)
31631c2cf11SZain Jaffal         ArgumentsVector.push_back({Key, false});
31731c2cf11SZain Jaffal     } else if (!RKeys.empty())
31831c2cf11SZain Jaffal       for (auto Key : RKeys)
31931c2cf11SZain Jaffal         ArgumentsVector.push_back({Key, true});
32031c2cf11SZain Jaffal     else
32131c2cf11SZain Jaffal       ArgumentsVector.push_back({".*", true});
32231c2cf11SZain Jaffal 
32331c2cf11SZain Jaffal     Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
32431c2cf11SZain Jaffal         GroupByOpt, ArgumentsVector, Buffer, Filter);
32531c2cf11SZain Jaffal     if (!AC)
32631c2cf11SZain Jaffal       return AC.takeError();
32731c2cf11SZain Jaffal     if (auto E = useCollectRemark(Buffer, *AC, Filter))
32831c2cf11SZain Jaffal       return E;
32931c2cf11SZain Jaffal   }
33031c2cf11SZain Jaffal   return Error::success();
33131c2cf11SZain Jaffal }
33231c2cf11SZain Jaffal 
33331c2cf11SZain Jaffal static CommandRegistration CountReg(&CountSub, collectRemarks);
334