[llvm] [llvm-remarkutil] Add an instruction-mix tool (PR #140598)

Jon Roelofs via llvm-commits llvm-commits at lists.llvm.org
Wed May 21 08:47:48 PDT 2025


https://github.com/jroelofs updated https://github.com/llvm/llvm-project/pull/140598

>From e0dce31ff74e3265cb8ea12a71ecbdbce72357f5 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Mon, 19 May 2025 12:18:12 -0700
Subject: [PATCH 01/17] [llvm-remarkutil] Add an instruction-mix tool

The new tool constructs a histogram of instruction frequencies, optionally
filtered by function name via a regex.  It can display in either a
human-readable table format, or machine-readable CSV.
---
 .../Inputs/instruction-mix.yaml               |  27 ++++
 .../llvm-remarkutil/broken-yaml-remark.test   |   1 +
 .../tools/llvm-remarkutil/empty-file.test     |   5 +
 .../llvm-remarkutil/instruction-mix.test      |  22 +++
 llvm/tools/llvm-remarkutil/CMakeLists.txt     |   1 +
 .../llvm-remarkutil/RemarkInstructionMix.cpp  | 125 ++++++++++++++++++
 6 files changed, 181 insertions(+)
 create mode 100644 llvm/test/tools/llvm-remarkutil/Inputs/instruction-mix.yaml
 create mode 100644 llvm/test/tools/llvm-remarkutil/instruction-mix.test
 create mode 100644 llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp

diff --git a/llvm/test/tools/llvm-remarkutil/Inputs/instruction-mix.yaml b/llvm/test/tools/llvm-remarkutil/Inputs/instruction-mix.yaml
new file mode 100644
index 0000000000000..f798454d317fa
--- /dev/null
+++ b/llvm/test/tools/llvm-remarkutil/Inputs/instruction-mix.yaml
@@ -0,0 +1,27 @@
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        home
+Args:
+  - INST_nop: '1'
+  - INST_add: '3'
+  - INST_mul: '5'
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        homeowner
+Args:
+  - INST_nop: '2'
+  - INST_add: '4'
+  - INST_mul: '6'
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        meow
+Args:
+  - INST_nop: '7'
+  - INST_add: '8'
+  - INST_mul: '9'
+...
diff --git a/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test b/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
index 0f06506603363..464d0b80c4ad0 100644
--- a/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
+++ b/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
@@ -1,5 +1,6 @@
 RUN: not llvm-remarkutil yaml2bitstream %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
 RUN: not llvm-remarkutil instruction-count --parser=yaml %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
+RUN: not llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
 RUN: not llvm-remarkutil annotation-count --parser=yaml --annotation-type=remark %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
 RUN: not llvm-remarkutil count --parser=yaml %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
 
diff --git a/llvm/test/tools/llvm-remarkutil/empty-file.test b/llvm/test/tools/llvm-remarkutil/empty-file.test
index abbf8e02cfa30..bdc5fcf87f7bf 100644
--- a/llvm/test/tools/llvm-remarkutil/empty-file.test
+++ b/llvm/test/tools/llvm-remarkutil/empty-file.test
@@ -1,9 +1,11 @@
 RUN: not llvm-remarkutil yaml2bitstream %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER
 RUN: not llvm-remarkutil instruction-count --parser=yaml %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER
+RUN: not llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER
 RUN: not llvm-remarkutil annotation-count --parser=yaml --annotation-type=remark %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER
 RUN: not llvm-remarkutil count --parser=yaml %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER
 RUN: llvm-remarkutil bitstream2yaml %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=BITSTREAM2YAML
 RUN: llvm-remarkutil instruction-count --parser=bitstream %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=SIZEBITSTREAM
+RUN: llvm-remarkutil instruction-mix --parser=bitstream %p/Inputs/empty-file --report_style=csv -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=MIXBITSTREAM
 RUN: llvm-remarkutil annotation-count --parser=bitstream --annotation-type=remark %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=ANNOTATIONBITSTREAM
 RUN: llvm-remarkutil count --parser=bitstream %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=COUNTBITSTREAM
 
@@ -20,3 +22,6 @@ RUN: llvm-remarkutil count --parser=bitstream %p/Inputs/empty-file -o - 2>&1 | F
 
 ; COUNTBITSTREAM-LABEL: Source,Count
 ; COUNTBITSTREAM-EMPTY:
+
+; MIXBITSTREAM-LABEL: Instruction,Count
+; MIXBITSTREAM-EMPTY:
diff --git a/llvm/test/tools/llvm-remarkutil/instruction-mix.test b/llvm/test/tools/llvm-remarkutil/instruction-mix.test
new file mode 100644
index 0000000000000..8abb760ca37f9
--- /dev/null
+++ b/llvm/test/tools/llvm-remarkutil/instruction-mix.test
@@ -0,0 +1,22 @@
+RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml | FileCheck %s
+RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-mix.yaml | llvm-remarkutil instruction-mix --parser=bitstream | FileCheck %s
+RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=human | FileCheck %s
+RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=csv | FileCheck %s --check-prefix=CSV
+RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --filter=meow | FileCheck %s --check-prefix=MEOW
+
+; CHECK-LABEL: Instruction Count
+; CHECK-NEXT:  ----------- -----
+; CHECK-NEXT:  mul         20
+; CHECK-NEXT:  add         15
+; CHECK-NEXT:  nop         10
+
+; CSV-LABEL: Instruction,Count
+; CSV-NEXT: mul,20
+; CSV-NEXT: add,15
+; CSV-NEXT: nop,10
+
+; MEOW:      Instruction Count
+; MEOW-NEXT: ----------- -----
+; MEOW-NEXT: mul         15
+; MEOW-NEXT: add         12
+; MEOW-NEXT: nop         9
\ No newline at end of file
diff --git a/llvm/tools/llvm-remarkutil/CMakeLists.txt b/llvm/tools/llvm-remarkutil/CMakeLists.txt
index 48aeb9397cda1..ed398ad272024 100644
--- a/llvm/tools/llvm-remarkutil/CMakeLists.txt
+++ b/llvm/tools/llvm-remarkutil/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_tool(llvm-remarkutil
   RemarkConvert.cpp
   RemarkCount.cpp
   RemarkCounter.cpp
+  RemarkInstructionMix.cpp
   RemarkSizeDiff.cpp
   RemarkUtil.cpp
   RemarkUtilHelpers.cpp
diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
new file mode 100644
index 0000000000000..e4373640a75ee
--- /dev/null
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -0,0 +1,125 @@
+
+#include "RemarkUtilHelpers.h"
+#include "RemarkUtilRegistry.h"
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/Regex.h"
+
+#include <numeric>
+
+using namespace llvm;
+using namespace remarks;
+using namespace llvm::remarkutil;
+
+namespace instructionmix {
+
+static cl::SubCommand
+    InstructionMix("instruction-mix",
+                   "Instruction Mix (requires asm-printer remarks)");
+
+static cl::opt<std::string>
+    FunctionFilter("filter", cl::sub(InstructionMix), cl::init(".*"),
+                   cl::value_desc("filter_regex"),
+                   cl::desc("regex to filter functions with"));
+
+enum ReportStyleOptions { human_output, csv_output };
+static cl::opt<ReportStyleOptions> ReportStyle(
+    "report_style", cl::sub(InstructionMix),
+    cl::init(ReportStyleOptions::human_output),
+    cl::desc("Choose the report output format:"),
+    cl::values(clEnumValN(human_output, "human", "Human-readable format"),
+               clEnumValN(csv_output, "csv", "CSV format")));
+
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionMix)
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionMix)
+DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(InstructionMix)
+
+static Error tryInstructionMix() {
+  auto MaybeOF =
+      getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
+  if (!MaybeOF)
+    return MaybeOF.takeError();
+
+  auto OF = std::move(*MaybeOF);
+  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+  if (!MaybeBuf)
+    return MaybeBuf.takeError();
+  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
+  if (!MaybeParser)
+    return MaybeParser.takeError();
+
+  Regex Filter(FunctionFilter);
+
+  // Collect the histogram of instruction counts.
+  std::unordered_map<std::string, unsigned> Histogram;
+  auto &Parser = **MaybeParser;
+  auto MaybeRemark = Parser.next();
+  for (; MaybeRemark; MaybeRemark = Parser.next()) {
+    auto &Remark = **MaybeRemark;
+    if (Remark.RemarkName != "InstructionMix")
+      continue;
+    if (!Filter.match(Remark.FunctionName))
+      continue;
+    for (auto &Arg : Remark.Args) {
+      StringRef Key = Arg.Key;
+      if (!Key.consume_front("INST_"))
+        continue;
+      unsigned Val = 0;
+      bool ParseError = Arg.Val.getAsInteger(10, Val);
+      assert(!ParseError);
+      (void)ParseError;
+      Histogram[std::string(Key)] += Val;
+    }
+  }
+
+  // Sort it.
+  using MixEntry = std::pair<std::string, unsigned>;
+  llvm::SmallVector<MixEntry> Mix(Histogram.begin(), Histogram.end());
+  std::sort(Mix.begin(), Mix.end(), [](const auto &LHS, const auto &RHS) {
+    return LHS.second > RHS.second;
+  });
+
+  // Print the results.
+  switch (ReportStyle) {
+  case human_output: {
+    formatted_raw_ostream FOS(OF->os());
+    size_t MaxMnemonic =
+        std::accumulate(Mix.begin(), Mix.end(), StringRef("Instruction").size(),
+                        [](size_t MaxMnemonic, const MixEntry &Elt) {
+                          return std::max(MaxMnemonic, Elt.first.length());
+                        });
+    unsigned MaxValue = std::accumulate(
+        Mix.begin(), Mix.end(), 0, [](unsigned MaxValue, const MixEntry &Elt) {
+          return std::max(MaxValue, Elt.second);
+        });
+    unsigned ValueWidth = log10(MaxValue) + 1;
+    FOS << "Instruction";
+    FOS.PadToColumn(MaxMnemonic + 1) << "Count\n";
+    FOS << "-----------";
+    FOS.PadToColumn(MaxMnemonic + 1) << "-----\n";
+    for (const auto &[Inst, Count] : Mix) {
+      FOS << Inst;
+      FOS.PadToColumn(MaxMnemonic + 1)
+          << " " << format_decimal(Count, ValueWidth) << "\n";
+    }
+  } break;
+  case csv_output: {
+    OF->os() << "Instruction,Count\n";
+    for (const auto &[Inst, Count] : Mix)
+      OF->os() << Inst << "," << Count << "\n";
+  } break;
+  }
+
+  auto E = MaybeRemark.takeError();
+  if (!E.isA<EndOfFileError>())
+    return E;
+  consumeError(std::move(E));
+  OF->keep();
+  return Error::success();
+}
+
+static CommandRegistration InstructionMixReg(&InstructionMix,
+                                             tryInstructionMix);
+
+} // namespace instructionmix
\ No newline at end of file

>From 27be6e191a578067cc2efca0806d8f14f5590955 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 15:10:16 -0700
Subject: [PATCH 02/17] drop debugloc cl opts

---
 llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
index e4373640a75ee..5a00d0f896576 100644
--- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -33,7 +33,6 @@ static cl::opt<ReportStyleOptions> ReportStyle(
 
 INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionMix)
 INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionMix)
-DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(InstructionMix)
 
 static Error tryInstructionMix() {
   auto MaybeOF =

>From dc263e1bf7c1c36cacb223bfae0a0e13e76bbd46 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 15:23:57 -0700
Subject: [PATCH 03/17] Add regex error handling.

---
 .../test/tools/llvm-remarkutil/instruction-mix.test |  7 +++++--
 llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp | 13 +++++++++----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/llvm/test/tools/llvm-remarkutil/instruction-mix.test b/llvm/test/tools/llvm-remarkutil/instruction-mix.test
index 8abb760ca37f9..e281366ef6781 100644
--- a/llvm/test/tools/llvm-remarkutil/instruction-mix.test
+++ b/llvm/test/tools/llvm-remarkutil/instruction-mix.test
@@ -2,7 +2,8 @@ RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yam
 RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-mix.yaml | llvm-remarkutil instruction-mix --parser=bitstream | FileCheck %s
 RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=human | FileCheck %s
 RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=csv | FileCheck %s --check-prefix=CSV
-RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --filter=meow | FileCheck %s --check-prefix=MEOW
+RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --rfilter=meow | FileCheck %s --check-prefix=MEOW
+RUN: not llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --rfilter=* 2>&1 | FileCheck %s --check-prefix=ERROR
 
 ; CHECK-LABEL: Instruction Count
 ; CHECK-NEXT:  ----------- -----
@@ -19,4 +20,6 @@ RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yam
 ; MEOW-NEXT: ----------- -----
 ; MEOW-NEXT: mul         15
 ; MEOW-NEXT: add         12
-; MEOW-NEXT: nop         9
\ No newline at end of file
+; MEOW-NEXT: nop         9
+
+; ERROR: error: invalid argument '--rfilter=*': repetition-operator operand invalid
\ No newline at end of file
diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
index 5a00d0f896576..146569246af67 100644
--- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -19,9 +19,10 @@ static cl::SubCommand
                    "Instruction Mix (requires asm-printer remarks)");
 
 static cl::opt<std::string>
-    FunctionFilter("filter", cl::sub(InstructionMix), cl::init(".*"),
-                   cl::value_desc("filter_regex"),
-                   cl::desc("regex to filter functions with"));
+    FunctionFilterRE("rfilter", cl::sub(InstructionMix), cl::init(".*"),
+                     cl::ValueOptional,
+                     cl::desc("Optional function name to filter collection by "
+                              "(accepts regular expressions)"));
 
 enum ReportStyleOptions { human_output, csv_output };
 static cl::opt<ReportStyleOptions> ReportStyle(
@@ -48,7 +49,11 @@ static Error tryInstructionMix() {
   if (!MaybeParser)
     return MaybeParser.takeError();
 
-  Regex Filter(FunctionFilter);
+  Regex Filter(FunctionFilterRE);
+  std::string Error;
+  if (!Filter.isValid(Error))
+    return createStringError(make_error_code(std::errc::invalid_argument),
+                             Twine("invalid argument '--rfilter=") + FunctionFilterRE + "': " + Error);
 
   // Collect the histogram of instruction counts.
   std::unordered_map<std::string, unsigned> Histogram;

>From 72cb5d066731b0a80801cb052f8398623ec2d677 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 16:11:37 -0700
Subject: [PATCH 04/17] Use FilterMatcher, and move it to RemarkUtilHelpers.h

---
 .../llvm-remarkutil/instruction-mix.test      | 19 +++++++----
 llvm/tools/llvm-remarkutil/RemarkCounter.cpp  | 30 ++++++++---------
 llvm/tools/llvm-remarkutil/RemarkCounter.h    | 29 ++--------------
 .../llvm-remarkutil/RemarkInstructionMix.cpp  | 23 +++++++++----
 .../tools/llvm-remarkutil/RemarkUtilHelpers.h | 33 +++++++++++++++++++
 5 files changed, 80 insertions(+), 54 deletions(-)

diff --git a/llvm/test/tools/llvm-remarkutil/instruction-mix.test b/llvm/test/tools/llvm-remarkutil/instruction-mix.test
index e281366ef6781..b556a9b500fbd 100644
--- a/llvm/test/tools/llvm-remarkutil/instruction-mix.test
+++ b/llvm/test/tools/llvm-remarkutil/instruction-mix.test
@@ -2,7 +2,8 @@ RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yam
 RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-mix.yaml | llvm-remarkutil instruction-mix --parser=bitstream | FileCheck %s
 RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=human | FileCheck %s
 RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=csv | FileCheck %s --check-prefix=CSV
-RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --rfilter=meow | FileCheck %s --check-prefix=MEOW
+RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --rfilter=meow | FileCheck %s --check-prefix=MEOW-RE
+RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --filter=meow | FileCheck %s --check-prefix=MEOW-EXACT
 RUN: not llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --rfilter=* 2>&1 | FileCheck %s --check-prefix=ERROR
 
 ; CHECK-LABEL: Instruction Count
@@ -16,10 +17,16 @@ RUN: not llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix
 ; CSV-NEXT: add,15
 ; CSV-NEXT: nop,10
 
-; MEOW:      Instruction Count
-; MEOW-NEXT: ----------- -----
-; MEOW-NEXT: mul         15
-; MEOW-NEXT: add         12
-; MEOW-NEXT: nop         9
+; MEOW-RE:      Instruction Count
+; MEOW-RE-NEXT: ----------- -----
+; MEOW-RE-NEXT: mul         15
+; MEOW-RE-NEXT: add         12
+; MEOW-RE-NEXT: nop         9
+
+; MEOW-EXACT:      Instruction Count
+; MEOW-EXACT-NEXT: ----------- -----
+; MEOW-EXACT-NEXT: mul         9
+; MEOW-EXACT-NEXT: add         8
+; MEOW-EXACT-NEXT: nop         7
 
 ; ERROR: error: invalid argument '--rfilter=*': repetition-operator operand invalid
\ No newline at end of file
diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
index 2d9432e41d9c0..c6d97efe5e2f8 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -112,14 +112,14 @@ static unsigned getValForKey(StringRef Key, const Remark &Remark) {
 }
 
 Error Filters::regexArgumentsValid() {
-  if (RemarkNameFilter && RemarkNameFilter->IsRegex)
-    if (auto E = checkRegex(RemarkNameFilter->FilterRE))
+  if (RemarkNameFilter)
+    if (auto E = RemarkNameFilter->isValid())
       return E;
-  if (PassNameFilter && PassNameFilter->IsRegex)
-    if (auto E = checkRegex(PassNameFilter->FilterRE))
+  if (PassNameFilter)
+    if (auto E = PassNameFilter->isValid())
       return E;
-  if (ArgFilter && ArgFilter->IsRegex)
-    if (auto E = checkRegex(ArgFilter->FilterRE))
+  if (ArgFilter)
+    if (auto E = ArgFilter->isValid())
       return E;
   return Error::success();
 }
@@ -254,19 +254,19 @@ Expected<Filters> getRemarkFilter() {
   std::optional<FilterMatcher> RemarkArgFilter;
   std::optional<Type> RemarkType;
   if (!RemarkNameOpt.empty())
-    RemarkNameFilter = {RemarkNameOpt, false};
+    RemarkNameFilter = {RemarkNameOpt, "remark-name", false};
   else if (!RemarkNameOptRE.empty())
-    RemarkNameFilter = {RemarkNameOptRE, true};
+    RemarkNameFilter = {RemarkNameOptRE, "rremark-name", true};
   if (!PassNameOpt.empty())
-    PassNameFilter = {PassNameOpt, false};
+    PassNameFilter = {PassNameOpt, "pass-name", false};
   else if (!PassNameOptRE.empty())
-    PassNameFilter = {PassNameOptRE, true};
+    PassNameFilter = {PassNameOptRE, "rpass-name", true};
   if (RemarkTypeOpt != Type::Failure)
     RemarkType = RemarkTypeOpt;
   if (!RemarkFilterArgByOpt.empty())
-    RemarkArgFilter = {RemarkFilterArgByOpt, false};
+    RemarkArgFilter = {RemarkFilterArgByOpt, "filter-arg-by", false};
   else if (!RemarkArgFilterOptRE.empty())
-    RemarkArgFilter = {RemarkArgFilterOptRE, true};
+    RemarkArgFilter = {RemarkArgFilterOptRE, "rfilter-arg-by", true};
   // Create RemarkFilter.
   return Filters::createRemarkFilter(std::move(RemarkNameFilter),
                                      std::move(PassNameFilter),
@@ -313,12 +313,12 @@ static Error collectRemarks() {
     SmallVector<FilterMatcher, 4> ArgumentsVector;
     if (!Keys.empty()) {
       for (auto &Key : Keys)
-        ArgumentsVector.push_back({Key, false});
+        ArgumentsVector.push_back({Key, "count-by", false});
     } else if (!RKeys.empty())
       for (auto Key : RKeys)
-        ArgumentsVector.push_back({Key, true});
+        ArgumentsVector.push_back({Key, "count-by", true});
     else
-      ArgumentsVector.push_back({".*", true});
+      ArgumentsVector.push_back({".*", "count-by", true});
 
     Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
         GroupByOpt, ArgumentsVector, Buffer, Filter);
diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.h b/llvm/tools/llvm-remarkutil/RemarkCounter.h
index 34d5bff774055..db71123238d0c 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.h
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.h
@@ -45,26 +45,6 @@ inline std::string groupByToStr(GroupBy GroupBy) {
   }
 }
 
-/// Filter object which can be either a string or a regex to match with the
-/// remark properties.
-struct FilterMatcher {
-  Regex FilterRE;
-  std::string FilterStr;
-  bool IsRegex;
-  FilterMatcher(std::string Filter, bool IsRegex) : IsRegex(IsRegex) {
-    if (IsRegex)
-      FilterRE = Regex(Filter);
-    else
-      FilterStr = Filter;
-  }
-
-  bool match(StringRef StringToMatch) const {
-    if (IsRegex)
-      return FilterRE.match(StringToMatch);
-    return FilterStr == StringToMatch.trim().str();
-  }
-};
-
 /// Filter out remarks based on remark properties based on name, pass name,
 /// argument and type.
 struct Filters {
@@ -160,12 +140,9 @@ struct ArgumentCounter : Counter {
                         StringRef Buffer, Filters &Filter) {
     ArgumentCounter AC;
     AC.Group = Group;
-    for (auto &Arg : Arguments) {
-      if (Arg.IsRegex) {
-        if (auto E = checkRegex(Arg.FilterRE))
-          return std::move(E);
-      }
-    }
+    for (auto &Arg : Arguments)
+      if (auto E = Arg.isValid())
+        return E;
     if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
       return std::move(E);
     return AC;
diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
index 146569246af67..e1d6f13f0f581 100644
--- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -19,8 +19,11 @@ static cl::SubCommand
                    "Instruction Mix (requires asm-printer remarks)");
 
 static cl::opt<std::string>
-    FunctionFilterRE("rfilter", cl::sub(InstructionMix), cl::init(".*"),
-                     cl::ValueOptional,
+    FunctionFilter("filter", cl::sub(InstructionMix), cl::ValueOptional,
+                   cl::desc("Optional function name to filter collection by"));
+
+static cl::opt<std::string>
+    FunctionFilterRE("rfilter", cl::sub(InstructionMix), cl::ValueOptional,
                      cl::desc("Optional function name to filter collection by "
                               "(accepts regular expressions)"));
 
@@ -35,6 +38,14 @@ static cl::opt<ReportStyleOptions> ReportStyle(
 INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionMix)
 INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionMix)
 
+static FilterMatcher getRemarkFilter() {
+  if (FunctionFilter.getNumOccurrences())
+    return {FunctionFilter, "filter", false};
+  if (FunctionFilterRE.getNumOccurrences())
+    return {FunctionFilterRE, "rfilter", true};
+  return {".*", "<implicit>", true};
+}
+
 static Error tryInstructionMix() {
   auto MaybeOF =
       getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
@@ -49,11 +60,9 @@ static Error tryInstructionMix() {
   if (!MaybeParser)
     return MaybeParser.takeError();
 
-  Regex Filter(FunctionFilterRE);
-  std::string Error;
-  if (!Filter.isValid(Error))
-    return createStringError(make_error_code(std::errc::invalid_argument),
-                             Twine("invalid argument '--rfilter=") + FunctionFilterRE + "': " + Error);
+  FilterMatcher Filter = getRemarkFilter();
+  if (auto E = Filter.isValid())
+    return E;
 
   // Collect the histogram of instruction counts.
   std::unordered_map<std::string, unsigned> Histogram;
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
index 5d2335224d4c2..a1bebd130c654 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -18,6 +18,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Regex.h"
 #include "llvm/Support/ToolOutputFile.h"
 
 // Keep input + output help + names consistent across the various modes via a
@@ -55,5 +56,37 @@ Expected<std::unique_ptr<ToolOutputFile>>
 getOutputFileWithFlags(StringRef OutputFileName, sys::fs::OpenFlags Flags);
 Expected<std::unique_ptr<ToolOutputFile>>
 getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat);
+
+/// Filter object which can be either a string or a regex to match with the
+/// remark properties.
+class FilterMatcher {
+  Regex FilterRE;
+  std::string FilterStr;
+  std::string Argument;
+  bool IsRegex;
+
+public:
+  FilterMatcher(StringRef Filter, StringRef Argument, bool IsRegex)
+      : FilterRE(Filter), FilterStr(Filter), Argument(Argument),
+        IsRegex(IsRegex) {}
+
+  bool match(StringRef StringToMatch) const {
+    if (IsRegex)
+      return FilterRE.match(StringToMatch);
+    return FilterStr == StringToMatch.trim().str();
+  }
+
+  Error isValid() const {
+    if (!IsRegex)
+      return Error::success();
+    std::string Error;
+    if (FilterRE.isValid(Error))
+      return Error::success();
+    return createStringError(make_error_code(std::errc::invalid_argument),
+                             "invalid argument '--" + Argument + "=" +
+                                 FilterStr + "': " + Error);
+  }
+};
+
 } // namespace remarks
 } // namespace llvm

>From 23daed4fa6b08f50ea032ce08cd74c1dd49fecfc Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 18:14:56 -0700
Subject: [PATCH 05/17] Make invalid states unrepresentable

---
 llvm/tools/llvm-remarkutil/RemarkCounter.cpp  | 65 ++++++++++---------
 llvm/tools/llvm-remarkutil/RemarkCounter.h    | 13 +---
 .../llvm-remarkutil/RemarkInstructionMix.cpp  | 16 ++---
 .../tools/llvm-remarkutil/RemarkUtilHelpers.h | 31 ++++-----
 4 files changed, 62 insertions(+), 63 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
index c6d97efe5e2f8..eb55906937f09 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -111,19 +111,6 @@ static unsigned getValForKey(StringRef Key, const Remark &Remark) {
   return *RemarkArg->getValAsInt();
 }
 
-Error Filters::regexArgumentsValid() {
-  if (RemarkNameFilter)
-    if (auto E = RemarkNameFilter->isValid())
-      return E;
-  if (PassNameFilter)
-    if (auto E = PassNameFilter->isValid())
-      return E;
-  if (ArgFilter)
-    if (auto E = ArgFilter->isValid())
-      return E;
-  return Error::success();
-}
-
 bool Filters::filterRemark(const Remark &Remark) {
   if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
     return false;
@@ -250,23 +237,39 @@ Error RemarkCounter::print(StringRef OutputFileName) {
 Expected<Filters> getRemarkFilter() {
   // Create Filter properties.
   std::optional<FilterMatcher> RemarkNameFilter;
+  if (!RemarkNameOpt.empty())
+    RemarkNameFilter = FilterMatcher::createExact(RemarkNameOpt);
+  else if (!RemarkNameOptRE.empty()){
+    auto FM = FilterMatcher::createRE(RemarkNameOptRE, "rremark-name");
+    if (!FM)
+      return FM.takeError();
+    RemarkNameFilter = std::move(*FM);
+  }
+
   std::optional<FilterMatcher> PassNameFilter;
+  if (!PassNameOpt.empty())
+    PassNameFilter = FilterMatcher::createExact(PassNameOpt);
+  else if (!PassNameOptRE.empty()) {
+    auto FM = FilterMatcher::createRE(PassNameOptRE, "rpass-name");
+    if (!FM)
+      return FM.takeError();
+    PassNameFilter = std::move(*FM);
+  }
+
   std::optional<FilterMatcher> RemarkArgFilter;
+  if (!RemarkFilterArgByOpt.empty())
+    RemarkArgFilter = FilterMatcher::createExact(RemarkFilterArgByOpt);
+  else if (!RemarkArgFilterOptRE.empty()) {
+    auto FM = FilterMatcher::createRE(RemarkArgFilterOptRE, "rfilter-arg-by");
+    if (!FM)
+      return FM.takeError();
+    RemarkArgFilter = std::move(*FM);
+  }
+
   std::optional<Type> RemarkType;
-  if (!RemarkNameOpt.empty())
-    RemarkNameFilter = {RemarkNameOpt, "remark-name", false};
-  else if (!RemarkNameOptRE.empty())
-    RemarkNameFilter = {RemarkNameOptRE, "rremark-name", true};
-  if (!PassNameOpt.empty())
-    PassNameFilter = {PassNameOpt, "pass-name", false};
-  else if (!PassNameOptRE.empty())
-    PassNameFilter = {PassNameOptRE, "rpass-name", true};
   if (RemarkTypeOpt != Type::Failure)
     RemarkType = RemarkTypeOpt;
-  if (!RemarkFilterArgByOpt.empty())
-    RemarkArgFilter = {RemarkFilterArgByOpt, "filter-arg-by", false};
-  else if (!RemarkArgFilterOptRE.empty())
-    RemarkArgFilter = {RemarkArgFilterOptRE, "rfilter-arg-by", true};
+
   // Create RemarkFilter.
   return Filters::createRemarkFilter(std::move(RemarkNameFilter),
                                      std::move(PassNameFilter),
@@ -313,12 +316,16 @@ static Error collectRemarks() {
     SmallVector<FilterMatcher, 4> ArgumentsVector;
     if (!Keys.empty()) {
       for (auto &Key : Keys)
-        ArgumentsVector.push_back({Key, "count-by", false});
+        ArgumentsVector.push_back(FilterMatcher::createExact(Key));
     } else if (!RKeys.empty())
-      for (auto Key : RKeys)
-        ArgumentsVector.push_back({Key, "count-by", true});
+      for (auto Key : RKeys) {
+        auto FM = FilterMatcher::createRE(Key, "count-by");
+        if (!FM)
+          return FM.takeError();
+        ArgumentsVector.push_back(std::move(*FM));
+      }
     else
-      ArgumentsVector.push_back({".*", "count-by", true});
+      ArgumentsVector.push_back(cantFail(FilterMatcher::createRE(".*", "count-by")));
 
     Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
         GroupByOpt, ArgumentsVector, Buffer, Filter);
diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.h b/llvm/tools/llvm-remarkutil/RemarkCounter.h
index db71123238d0c..94f071bbbfa3b 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.h
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.h
@@ -54,7 +54,7 @@ struct Filters {
   std::optional<Type> RemarkTypeFilter;
   /// Returns a filter object if all the arguments provided are valid regex
   /// types otherwise return an error.
-  static Expected<Filters>
+  static Filters
   createRemarkFilter(std::optional<FilterMatcher> RemarkNameFilter,
                      std::optional<FilterMatcher> PassNameFilter,
                      std::optional<FilterMatcher> ArgFilter,
@@ -64,16 +64,10 @@ struct Filters {
     Filter.PassNameFilter = std::move(PassNameFilter);
     Filter.ArgFilter = std::move(ArgFilter);
     Filter.RemarkTypeFilter = std::move(RemarkTypeFilter);
-    if (auto E = Filter.regexArgumentsValid())
-      return std::move(E);
-    return std::move(Filter);
+    return Filter;
   }
   /// Returns true if \p Remark satisfies all the provided filters.
   bool filterRemark(const Remark &Remark);
-
-private:
-  /// Check if arguments can be parsed as valid regex types.
-  Error regexArgumentsValid();
 };
 
 /// Convert Regex string error to an error object.
@@ -140,9 +134,6 @@ struct ArgumentCounter : Counter {
                         StringRef Buffer, Filters &Filter) {
     ArgumentCounter AC;
     AC.Group = Group;
-    for (auto &Arg : Arguments)
-      if (auto E = Arg.isValid())
-        return E;
     if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
       return std::move(E);
     return AC;
diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
index e1d6f13f0f581..0082b208f2e80 100644
--- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -38,12 +38,12 @@ static cl::opt<ReportStyleOptions> ReportStyle(
 INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionMix)
 INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionMix)
 
-static FilterMatcher getRemarkFilter() {
+static Expected<FilterMatcher> getRemarkFilter() {
   if (FunctionFilter.getNumOccurrences())
-    return {FunctionFilter, "filter", false};
+    return FilterMatcher::createExact(FunctionFilter);
   if (FunctionFilterRE.getNumOccurrences())
-    return {FunctionFilterRE, "rfilter", true};
-  return {".*", "<implicit>", true};
+    return FilterMatcher::createRE(FunctionFilterRE, "rfilter");
+  return FilterMatcher::createRE(".*", "<implicit>");
 }
 
 static Error tryInstructionMix() {
@@ -60,9 +60,9 @@ static Error tryInstructionMix() {
   if (!MaybeParser)
     return MaybeParser.takeError();
 
-  FilterMatcher Filter = getRemarkFilter();
-  if (auto E = Filter.isValid())
-    return E;
+  Expected<FilterMatcher> Filter = getRemarkFilter();
+  if (!Filter)
+    return Filter.takeError();
 
   // Collect the histogram of instruction counts.
   std::unordered_map<std::string, unsigned> Histogram;
@@ -72,7 +72,7 @@ static Error tryInstructionMix() {
     auto &Remark = **MaybeRemark;
     if (Remark.RemarkName != "InstructionMix")
       continue;
-    if (!Filter.match(Remark.FunctionName))
+    if (!Filter->match(Remark.FunctionName))
       continue;
     for (auto &Arg : Remark.Args) {
       StringRef Key = Arg.Key;
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
index a1bebd130c654..2cf187f4d1be0 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -62,30 +62,31 @@ getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat);
 class FilterMatcher {
   Regex FilterRE;
   std::string FilterStr;
-  std::string Argument;
   bool IsRegex;
 
+  FilterMatcher(StringRef Filter, bool IsRegex)
+      : FilterRE(Filter), FilterStr(Filter), IsRegex(IsRegex) {}
+
 public:
-  FilterMatcher(StringRef Filter, StringRef Argument, bool IsRegex)
-      : FilterRE(Filter), FilterStr(Filter), Argument(Argument),
-        IsRegex(IsRegex) {}
+  static FilterMatcher createExact(StringRef Filter) {
+    return {Filter, false};
+  }
+
+  static Expected<FilterMatcher> createRE(StringRef Filter, StringRef Argument) {
+    FilterMatcher FM(Filter, true);
+    std::string Error;
+    if (!FM.FilterRE.isValid(Error))
+      return createStringError(make_error_code(std::errc::invalid_argument),
+                               "invalid argument '--" + Argument + "=" +
+                                   Filter + "': " + Error);
+    return std::move(FM);
+  }
 
   bool match(StringRef StringToMatch) const {
     if (IsRegex)
       return FilterRE.match(StringToMatch);
     return FilterStr == StringToMatch.trim().str();
   }
-
-  Error isValid() const {
-    if (!IsRegex)
-      return Error::success();
-    std::string Error;
-    if (FilterRE.isValid(Error))
-      return Error::success();
-    return createStringError(make_error_code(std::errc::invalid_argument),
-                             "invalid argument '--" + Argument + "=" +
-                                 FilterStr + "': " + Error);
-  }
 };
 
 } // namespace remarks

>From baf38411cc5e5c1e161f1e6ff9ad9321e66103bc Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 18:17:53 -0700
Subject: [PATCH 06/17] Add missing file header

---
 llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
index 0082b208f2e80..7cbada1c1ba17 100644
--- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -1,3 +1,14 @@
+//===- RemarkInstructionMix.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic tool to extract instruction mix from asm-printer remarks.
+//
+//===----------------------------------------------------------------------===//
 
 #include "RemarkUtilHelpers.h"
 #include "RemarkUtilRegistry.h"

>From 237deb092fbd3cd46f8bdc7bec89af661e5dbfb4 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 18:19:45 -0700
Subject: [PATCH 07/17] clang-format

---
 llvm/tools/llvm-remarkutil/RemarkCounter.cpp   | 5 +++--
 llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h | 7 +++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
index eb55906937f09..8db8a8d1b33d4 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -239,7 +239,7 @@ Expected<Filters> getRemarkFilter() {
   std::optional<FilterMatcher> RemarkNameFilter;
   if (!RemarkNameOpt.empty())
     RemarkNameFilter = FilterMatcher::createExact(RemarkNameOpt);
-  else if (!RemarkNameOptRE.empty()){
+  else if (!RemarkNameOptRE.empty()) {
     auto FM = FilterMatcher::createRE(RemarkNameOptRE, "rremark-name");
     if (!FM)
       return FM.takeError();
@@ -325,7 +325,8 @@ static Error collectRemarks() {
         ArgumentsVector.push_back(std::move(*FM));
       }
     else
-      ArgumentsVector.push_back(cantFail(FilterMatcher::createRE(".*", "count-by")));
+      ArgumentsVector.push_back(
+          cantFail(FilterMatcher::createRE(".*", "count-by")));
 
     Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
         GroupByOpt, ArgumentsVector, Buffer, Filter);
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
index 2cf187f4d1be0..31a64ce668ed1 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -68,11 +68,10 @@ class FilterMatcher {
       : FilterRE(Filter), FilterStr(Filter), IsRegex(IsRegex) {}
 
 public:
-  static FilterMatcher createExact(StringRef Filter) {
-    return {Filter, false};
-  }
+  static FilterMatcher createExact(StringRef Filter) { return {Filter, false}; }
 
-  static Expected<FilterMatcher> createRE(StringRef Filter, StringRef Argument) {
+  static Expected<FilterMatcher> createRE(StringRef Filter,
+                                          StringRef Argument) {
     FilterMatcher FM(Filter, true);
     std::string Error;
     if (!FM.FilterRE.isValid(Error))

>From fb8bed1ae54035bc946cda43a4858b91f1be28c7 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 18:21:00 -0700
Subject: [PATCH 08/17] EOL whitespace

---
 llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
index 7cbada1c1ba17..4b57f0f48d86e 100644
--- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -146,4 +146,4 @@ static Error tryInstructionMix() {
 static CommandRegistration InstructionMixReg(&InstructionMix,
                                              tryInstructionMix);
 
-} // namespace instructionmix
\ No newline at end of file
+} // namespace instructionmix

>From 8e39094617329ea8b4c08b1a5179f83d3a0f39a2 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 18:29:56 -0700
Subject: [PATCH 09/17] remove now-useless static member ctor

---
 llvm/tools/llvm-remarkutil/RemarkCounter.cpp |  5 ++---
 llvm/tools/llvm-remarkutil/RemarkCounter.h   | 15 +--------------
 2 files changed, 3 insertions(+), 17 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
index 8db8a8d1b33d4..c9806b2ba8a17 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -271,9 +271,8 @@ Expected<Filters> getRemarkFilter() {
     RemarkType = RemarkTypeOpt;
 
   // Create RemarkFilter.
-  return Filters::createRemarkFilter(std::move(RemarkNameFilter),
-                                     std::move(PassNameFilter),
-                                     std::move(RemarkArgFilter), RemarkType);
+  return Filters{std::move(RemarkNameFilter), std::move(PassNameFilter),
+                 std::move(RemarkArgFilter), RemarkType};
 }
 
 Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) {
diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.h b/llvm/tools/llvm-remarkutil/RemarkCounter.h
index 94f071bbbfa3b..1dc5be34853d5 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.h
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.h
@@ -52,20 +52,7 @@ struct Filters {
   std::optional<FilterMatcher> PassNameFilter;
   std::optional<FilterMatcher> ArgFilter;
   std::optional<Type> RemarkTypeFilter;
-  /// Returns a filter object if all the arguments provided are valid regex
-  /// types otherwise return an error.
-  static Filters
-  createRemarkFilter(std::optional<FilterMatcher> RemarkNameFilter,
-                     std::optional<FilterMatcher> PassNameFilter,
-                     std::optional<FilterMatcher> ArgFilter,
-                     std::optional<Type> RemarkTypeFilter) {
-    Filters Filter;
-    Filter.RemarkNameFilter = std::move(RemarkNameFilter);
-    Filter.PassNameFilter = std::move(PassNameFilter);
-    Filter.ArgFilter = std::move(ArgFilter);
-    Filter.RemarkTypeFilter = std::move(RemarkTypeFilter);
-    return Filter;
-  }
+
   /// Returns true if \p Remark satisfies all the provided filters.
   bool filterRemark(const Remark &Remark);
 };

>From 7e8ee10b9a70eb896e3aacaeb33b09ddafa60169 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 18:30:40 -0700
Subject: [PATCH 10/17] rm dead function

---
 llvm/tools/llvm-remarkutil/RemarkCounter.h | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.h b/llvm/tools/llvm-remarkutil/RemarkCounter.h
index 1dc5be34853d5..3b977791d87c2 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.h
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.h
@@ -57,15 +57,6 @@ struct Filters {
   bool filterRemark(const Remark &Remark);
 };
 
-/// Convert Regex string error to an error object.
-inline Error checkRegex(const Regex &Regex) {
-  std::string Error;
-  if (!Regex.isValid(Error))
-    return createStringError(make_error_code(std::errc::invalid_argument),
-                             Twine("Regex: ", Error));
-  return Error::success();
-}
-
 /// Abstract counter class used to define the general required methods for
 /// counting a remark.
 struct Counter {

>From 28a34df08f2fe95029012304e547a526fa43d4a8 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Mon, 19 May 2025 12:18:12 -0700
Subject: [PATCH 11/17] [llvm-remarkutil] Make invalid states un-representable
 in the count tool.

This consolidates some of the error handling around regex arguments to the
tool, and sets up the APIs such that errors must be handled before their usage.
---
 llvm/tools/llvm-remarkutil/RemarkCounter.cpp  | 71 ++++++++++---------
 llvm/tools/llvm-remarkutil/RemarkCounter.h    | 56 +--------------
 .../tools/llvm-remarkutil/RemarkUtilHelpers.h | 33 +++++++++
 3 files changed, 73 insertions(+), 87 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
index 2d9432e41d9c0..c9806b2ba8a17 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -111,19 +111,6 @@ static unsigned getValForKey(StringRef Key, const Remark &Remark) {
   return *RemarkArg->getValAsInt();
 }
 
-Error Filters::regexArgumentsValid() {
-  if (RemarkNameFilter && RemarkNameFilter->IsRegex)
-    if (auto E = checkRegex(RemarkNameFilter->FilterRE))
-      return E;
-  if (PassNameFilter && PassNameFilter->IsRegex)
-    if (auto E = checkRegex(PassNameFilter->FilterRE))
-      return E;
-  if (ArgFilter && ArgFilter->IsRegex)
-    if (auto E = checkRegex(ArgFilter->FilterRE))
-      return E;
-  return Error::success();
-}
-
 bool Filters::filterRemark(const Remark &Remark) {
   if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
     return false;
@@ -250,27 +237,42 @@ Error RemarkCounter::print(StringRef OutputFileName) {
 Expected<Filters> getRemarkFilter() {
   // Create Filter properties.
   std::optional<FilterMatcher> RemarkNameFilter;
+  if (!RemarkNameOpt.empty())
+    RemarkNameFilter = FilterMatcher::createExact(RemarkNameOpt);
+  else if (!RemarkNameOptRE.empty()) {
+    auto FM = FilterMatcher::createRE(RemarkNameOptRE, "rremark-name");
+    if (!FM)
+      return FM.takeError();
+    RemarkNameFilter = std::move(*FM);
+  }
+
   std::optional<FilterMatcher> PassNameFilter;
+  if (!PassNameOpt.empty())
+    PassNameFilter = FilterMatcher::createExact(PassNameOpt);
+  else if (!PassNameOptRE.empty()) {
+    auto FM = FilterMatcher::createRE(PassNameOptRE, "rpass-name");
+    if (!FM)
+      return FM.takeError();
+    PassNameFilter = std::move(*FM);
+  }
+
   std::optional<FilterMatcher> RemarkArgFilter;
+  if (!RemarkFilterArgByOpt.empty())
+    RemarkArgFilter = FilterMatcher::createExact(RemarkFilterArgByOpt);
+  else if (!RemarkArgFilterOptRE.empty()) {
+    auto FM = FilterMatcher::createRE(RemarkArgFilterOptRE, "rfilter-arg-by");
+    if (!FM)
+      return FM.takeError();
+    RemarkArgFilter = std::move(*FM);
+  }
+
   std::optional<Type> RemarkType;
-  if (!RemarkNameOpt.empty())
-    RemarkNameFilter = {RemarkNameOpt, false};
-  else if (!RemarkNameOptRE.empty())
-    RemarkNameFilter = {RemarkNameOptRE, true};
-  if (!PassNameOpt.empty())
-    PassNameFilter = {PassNameOpt, false};
-  else if (!PassNameOptRE.empty())
-    PassNameFilter = {PassNameOptRE, true};
   if (RemarkTypeOpt != Type::Failure)
     RemarkType = RemarkTypeOpt;
-  if (!RemarkFilterArgByOpt.empty())
-    RemarkArgFilter = {RemarkFilterArgByOpt, false};
-  else if (!RemarkArgFilterOptRE.empty())
-    RemarkArgFilter = {RemarkArgFilterOptRE, true};
+
   // Create RemarkFilter.
-  return Filters::createRemarkFilter(std::move(RemarkNameFilter),
-                                     std::move(PassNameFilter),
-                                     std::move(RemarkArgFilter), RemarkType);
+  return Filters{std::move(RemarkNameFilter), std::move(PassNameFilter),
+                 std::move(RemarkArgFilter), RemarkType};
 }
 
 Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) {
@@ -313,12 +315,17 @@ static Error collectRemarks() {
     SmallVector<FilterMatcher, 4> ArgumentsVector;
     if (!Keys.empty()) {
       for (auto &Key : Keys)
-        ArgumentsVector.push_back({Key, false});
+        ArgumentsVector.push_back(FilterMatcher::createExact(Key));
     } else if (!RKeys.empty())
-      for (auto Key : RKeys)
-        ArgumentsVector.push_back({Key, true});
+      for (auto Key : RKeys) {
+        auto FM = FilterMatcher::createRE(Key, "count-by");
+        if (!FM)
+          return FM.takeError();
+        ArgumentsVector.push_back(std::move(*FM));
+      }
     else
-      ArgumentsVector.push_back({".*", true});
+      ArgumentsVector.push_back(
+          cantFail(FilterMatcher::createRE(".*", "count-by")));
 
     Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
         GroupByOpt, ArgumentsVector, Buffer, Filter);
diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.h b/llvm/tools/llvm-remarkutil/RemarkCounter.h
index 34d5bff774055..3b977791d87c2 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.h
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.h
@@ -45,26 +45,6 @@ inline std::string groupByToStr(GroupBy GroupBy) {
   }
 }
 
-/// Filter object which can be either a string or a regex to match with the
-/// remark properties.
-struct FilterMatcher {
-  Regex FilterRE;
-  std::string FilterStr;
-  bool IsRegex;
-  FilterMatcher(std::string Filter, bool IsRegex) : IsRegex(IsRegex) {
-    if (IsRegex)
-      FilterRE = Regex(Filter);
-    else
-      FilterStr = Filter;
-  }
-
-  bool match(StringRef StringToMatch) const {
-    if (IsRegex)
-      return FilterRE.match(StringToMatch);
-    return FilterStr == StringToMatch.trim().str();
-  }
-};
-
 /// Filter out remarks based on remark properties based on name, pass name,
 /// argument and type.
 struct Filters {
@@ -72,39 +52,11 @@ struct Filters {
   std::optional<FilterMatcher> PassNameFilter;
   std::optional<FilterMatcher> ArgFilter;
   std::optional<Type> RemarkTypeFilter;
-  /// Returns a filter object if all the arguments provided are valid regex
-  /// types otherwise return an error.
-  static Expected<Filters>
-  createRemarkFilter(std::optional<FilterMatcher> RemarkNameFilter,
-                     std::optional<FilterMatcher> PassNameFilter,
-                     std::optional<FilterMatcher> ArgFilter,
-                     std::optional<Type> RemarkTypeFilter) {
-    Filters Filter;
-    Filter.RemarkNameFilter = std::move(RemarkNameFilter);
-    Filter.PassNameFilter = std::move(PassNameFilter);
-    Filter.ArgFilter = std::move(ArgFilter);
-    Filter.RemarkTypeFilter = std::move(RemarkTypeFilter);
-    if (auto E = Filter.regexArgumentsValid())
-      return std::move(E);
-    return std::move(Filter);
-  }
+
   /// Returns true if \p Remark satisfies all the provided filters.
   bool filterRemark(const Remark &Remark);
-
-private:
-  /// Check if arguments can be parsed as valid regex types.
-  Error regexArgumentsValid();
 };
 
-/// Convert Regex string error to an error object.
-inline Error checkRegex(const Regex &Regex) {
-  std::string Error;
-  if (!Regex.isValid(Error))
-    return createStringError(make_error_code(std::errc::invalid_argument),
-                             Twine("Regex: ", Error));
-  return Error::success();
-}
-
 /// Abstract counter class used to define the general required methods for
 /// counting a remark.
 struct Counter {
@@ -160,12 +112,6 @@ struct ArgumentCounter : Counter {
                         StringRef Buffer, Filters &Filter) {
     ArgumentCounter AC;
     AC.Group = Group;
-    for (auto &Arg : Arguments) {
-      if (Arg.IsRegex) {
-        if (auto E = checkRegex(Arg.FilterRE))
-          return std::move(E);
-      }
-    }
     if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
       return std::move(E);
     return AC;
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
index 5d2335224d4c2..31a64ce668ed1 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -18,6 +18,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Regex.h"
 #include "llvm/Support/ToolOutputFile.h"
 
 // Keep input + output help + names consistent across the various modes via a
@@ -55,5 +56,37 @@ Expected<std::unique_ptr<ToolOutputFile>>
 getOutputFileWithFlags(StringRef OutputFileName, sys::fs::OpenFlags Flags);
 Expected<std::unique_ptr<ToolOutputFile>>
 getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat);
+
+/// Filter object which can be either a string or a regex to match with the
+/// remark properties.
+class FilterMatcher {
+  Regex FilterRE;
+  std::string FilterStr;
+  bool IsRegex;
+
+  FilterMatcher(StringRef Filter, bool IsRegex)
+      : FilterRE(Filter), FilterStr(Filter), IsRegex(IsRegex) {}
+
+public:
+  static FilterMatcher createExact(StringRef Filter) { return {Filter, false}; }
+
+  static Expected<FilterMatcher> createRE(StringRef Filter,
+                                          StringRef Argument) {
+    FilterMatcher FM(Filter, true);
+    std::string Error;
+    if (!FM.FilterRE.isValid(Error))
+      return createStringError(make_error_code(std::errc::invalid_argument),
+                               "invalid argument '--" + Argument + "=" +
+                                   Filter + "': " + Error);
+    return std::move(FM);
+  }
+
+  bool match(StringRef StringToMatch) const {
+    if (IsRegex)
+      return FilterRE.match(StringToMatch);
+    return FilterStr == StringToMatch.trim().str();
+  }
+};
+
 } // namespace remarks
 } // namespace llvm

>From e5acd0489e9f6f5fc4b5a8c71d765568c180db88 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 19:07:20 -0700
Subject: [PATCH 12/17] add tests for count error handling

---
 llvm/test/tools/llvm-remarkutil/instruction-count.test | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/llvm/test/tools/llvm-remarkutil/instruction-count.test b/llvm/test/tools/llvm-remarkutil/instruction-count.test
index c4bc3e5780e3f..09a9dab026ec2 100644
--- a/llvm/test/tools/llvm-remarkutil/instruction-count.test
+++ b/llvm/test/tools/llvm-remarkutil/instruction-count.test
@@ -2,6 +2,9 @@ RUN: llvm-remarkutil instruction-count --parser=yaml %p/Inputs/instruction-count
 RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml | llvm-remarkutil instruction-count --parser=bitstream | FileCheck %s
 RUN: llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --remark-name="InstructionCount" %p/Inputs/instruction-count.yaml | FileCheck %s --check-prefix=COUNT-CHECK
 RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml  | llvm-remarkutil count --parser=bitstream --count-by=arg --group-by=function --remark-name="InstructionCount" | FileCheck %s --check-prefix=COUNT-CHECK
+RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rremark-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-REMARK-NAME
+RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rpass-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-PASS-NAME
+RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rfilter-arg-by=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-FILTER-ARG-BY
 
 ; CHECK-LABEL: Function,InstructionCount
 ; CHECK: func1,1
@@ -12,3 +15,7 @@ RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml  | llvm-rem
 ; COUNT-CHECK: func1,1
 ; COUNT-CHECK: func2,2
 ; COUNT-CHECK: func3,3
+
+; ERROR-REMARK-NAME: error: invalid argument '--rremark-name=*': repetition-operator operand invalid
+; ERROR-PASS-NAME: error: invalid argument '--rpass-name=*': repetition-operator operand invalid
+; ERROR-FILTER-ARG-BY: error: invalid argument '--rfilter-arg-by=*': repetition-operator operand invalid
\ No newline at end of file

>From 35e835261d789ad778ae5ebdf9e2b435728e16a7 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 19:11:46 -0700
Subject: [PATCH 13/17] simplify new test

---
 llvm/test/tools/llvm-remarkutil/instruction-count.test | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/test/tools/llvm-remarkutil/instruction-count.test b/llvm/test/tools/llvm-remarkutil/instruction-count.test
index 09a9dab026ec2..f521e69a4d5df 100644
--- a/llvm/test/tools/llvm-remarkutil/instruction-count.test
+++ b/llvm/test/tools/llvm-remarkutil/instruction-count.test
@@ -2,9 +2,9 @@ RUN: llvm-remarkutil instruction-count --parser=yaml %p/Inputs/instruction-count
 RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml | llvm-remarkutil instruction-count --parser=bitstream | FileCheck %s
 RUN: llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --remark-name="InstructionCount" %p/Inputs/instruction-count.yaml | FileCheck %s --check-prefix=COUNT-CHECK
 RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml  | llvm-remarkutil count --parser=bitstream --count-by=arg --group-by=function --remark-name="InstructionCount" | FileCheck %s --check-prefix=COUNT-CHECK
-RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rremark-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-REMARK-NAME
-RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rpass-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-PASS-NAME
-RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rfilter-arg-by=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-FILTER-ARG-BY
+RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rremark-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR -DARG=rremark-name
+RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rpass-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR -DARG=rpass-name
+RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rfilter-arg-by=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR -DARG=rfilter-arg-by
 
 ; CHECK-LABEL: Function,InstructionCount
 ; CHECK: func1,1
@@ -16,6 +16,4 @@ RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function
 ; COUNT-CHECK: func2,2
 ; COUNT-CHECK: func3,3
 
-; ERROR-REMARK-NAME: error: invalid argument '--rremark-name=*': repetition-operator operand invalid
-; ERROR-PASS-NAME: error: invalid argument '--rpass-name=*': repetition-operator operand invalid
-; ERROR-FILTER-ARG-BY: error: invalid argument '--rfilter-arg-by=*': repetition-operator operand invalid
\ No newline at end of file
+; ERROR: error: invalid argument '--[[ARG]]=*': repetition-operator operand invalid
\ No newline at end of file

>From 17bd09b2b408abe7254f7c8b450ee53ee167b4ee Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 19:42:59 -0700
Subject: [PATCH 14/17] make it harder to mention the wrong arg name in an
 error

---
 llvm/tools/llvm-remarkutil/RemarkCounter.cpp  | 11 ++++-----
 .../llvm-remarkutil/RemarkUtilHelpers.cpp     | 23 +++++++++++++++++++
 .../tools/llvm-remarkutil/RemarkUtilHelpers.h | 20 ++++++++--------
 3 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
index c9806b2ba8a17..b3a86e359d1ef 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -240,7 +240,7 @@ Expected<Filters> getRemarkFilter() {
   if (!RemarkNameOpt.empty())
     RemarkNameFilter = FilterMatcher::createExact(RemarkNameOpt);
   else if (!RemarkNameOptRE.empty()) {
-    auto FM = FilterMatcher::createRE(RemarkNameOptRE, "rremark-name");
+    auto FM = FilterMatcher::createRE(RemarkNameOptRE);
     if (!FM)
       return FM.takeError();
     RemarkNameFilter = std::move(*FM);
@@ -250,7 +250,7 @@ Expected<Filters> getRemarkFilter() {
   if (!PassNameOpt.empty())
     PassNameFilter = FilterMatcher::createExact(PassNameOpt);
   else if (!PassNameOptRE.empty()) {
-    auto FM = FilterMatcher::createRE(PassNameOptRE, "rpass-name");
+    auto FM = FilterMatcher::createRE(PassNameOptRE);
     if (!FM)
       return FM.takeError();
     PassNameFilter = std::move(*FM);
@@ -260,7 +260,7 @@ Expected<Filters> getRemarkFilter() {
   if (!RemarkFilterArgByOpt.empty())
     RemarkArgFilter = FilterMatcher::createExact(RemarkFilterArgByOpt);
   else if (!RemarkArgFilterOptRE.empty()) {
-    auto FM = FilterMatcher::createRE(RemarkArgFilterOptRE, "rfilter-arg-by");
+    auto FM = FilterMatcher::createRE(RemarkArgFilterOptRE);
     if (!FM)
       return FM.takeError();
     RemarkArgFilter = std::move(*FM);
@@ -318,14 +318,13 @@ static Error collectRemarks() {
         ArgumentsVector.push_back(FilterMatcher::createExact(Key));
     } else if (!RKeys.empty())
       for (auto Key : RKeys) {
-        auto FM = FilterMatcher::createRE(Key, "count-by");
+        auto FM = FilterMatcher::createRE(Key, RKeys);
         if (!FM)
           return FM.takeError();
         ArgumentsVector.push_back(std::move(*FM));
       }
     else
-      ArgumentsVector.push_back(
-          cantFail(FilterMatcher::createRE(".*", "count-by")));
+      ArgumentsVector.push_back(FilterMatcher::createAny());
 
     Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
         GroupByOpt, ArgumentsVector, Buffer, Filter);
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
index c0357161c4f98..153cbd6ca2d91 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
@@ -53,5 +53,28 @@ getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat) {
                                                     ? sys::fs::OF_TextWithCRLF
                                                     : sys::fs::OF_None);
 }
+
+Expected<FilterMatcher>
+FilterMatcher::createRE(const llvm::cl::opt<std::string> &Arg) {
+  return createRE(Arg.ArgStr, Arg);
+}
+
+
+Expected<FilterMatcher>
+FilterMatcher::createRE(StringRef Filter, const cl::list<std::string> &Arg) {
+  return createRE(Arg.ArgStr, Filter);
+}
+
+Expected<FilterMatcher> FilterMatcher::createRE(StringRef Arg,
+                                                StringRef Value) {
+  FilterMatcher FM(Value, true);
+  std::string Error;
+  if (!FM.FilterRE.isValid(Error))
+    return createStringError(make_error_code(std::errc::invalid_argument),
+                             "invalid argument '--" + Arg + "=" + Value +
+                                 "': " + Error);
+  return std::move(FM);
+}
+
 } // namespace remarks
 } // namespace llvm
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
index 31a64ce668ed1..847afbbfa7142 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -15,6 +15,7 @@
 #include "llvm/Remarks/RemarkFormat.h"
 #include "llvm/Remarks/RemarkParser.h"
 #include "llvm/Remarks/YAMLRemarkSerializer.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -67,19 +68,18 @@ class FilterMatcher {
   FilterMatcher(StringRef Filter, bool IsRegex)
       : FilterRE(Filter), FilterStr(Filter), IsRegex(IsRegex) {}
 
+  static Expected<FilterMatcher> createRE(StringRef Arg, StringRef Value);
+
 public:
   static FilterMatcher createExact(StringRef Filter) { return {Filter, false}; }
 
-  static Expected<FilterMatcher> createRE(StringRef Filter,
-                                          StringRef Argument) {
-    FilterMatcher FM(Filter, true);
-    std::string Error;
-    if (!FM.FilterRE.isValid(Error))
-      return createStringError(make_error_code(std::errc::invalid_argument),
-                               "invalid argument '--" + Argument + "=" +
-                                   Filter + "': " + Error);
-    return std::move(FM);
-  }
+  static Expected<FilterMatcher>
+  createRE(const llvm::cl::opt<std::string> &Arg);
+
+  static Expected<FilterMatcher>
+  createRE(StringRef Filter, const cl::list<std::string> &Arg);
+
+  static FilterMatcher createAny() { return {".*", true}; }
 
   bool match(StringRef StringToMatch) const {
     if (IsRegex)

>From c6041736ec2bed64bf88a345d9a599f676843430 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 19:43:23 -0700
Subject: [PATCH 15/17] rm stray whitespace

---
 llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
index 153cbd6ca2d91..72c5735296fcb 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
@@ -59,7 +59,6 @@ FilterMatcher::createRE(const llvm::cl::opt<std::string> &Arg) {
   return createRE(Arg.ArgStr, Arg);
 }
 
-
 Expected<FilterMatcher>
 FilterMatcher::createRE(StringRef Filter, const cl::list<std::string> &Arg) {
   return createRE(Arg.ArgStr, Filter);

>From a063bedd1ced3ef8e05ea349b46f780f639e8a39 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 20 May 2025 19:45:28 -0700
Subject: [PATCH 16/17] fix build after merge

---
 llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
index 4b57f0f48d86e..06d38a206ed24 100644
--- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
@@ -53,8 +53,8 @@ static Expected<FilterMatcher> getRemarkFilter() {
   if (FunctionFilter.getNumOccurrences())
     return FilterMatcher::createExact(FunctionFilter);
   if (FunctionFilterRE.getNumOccurrences())
-    return FilterMatcher::createRE(FunctionFilterRE, "rfilter");
-  return FilterMatcher::createRE(".*", "<implicit>");
+    return FilterMatcher::createRE(FunctionFilterRE);
+  return FilterMatcher::createAny();
 }
 
 static Error tryInstructionMix() {

>From abe8f96eb6498e40167383189d794e32b6b2d318 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Wed, 21 May 2025 08:46:48 -0700
Subject: [PATCH 17/17] clang-format

---
 llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
index 847afbbfa7142..45c9ed054f8cd 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -76,8 +76,8 @@ class FilterMatcher {
   static Expected<FilterMatcher>
   createRE(const llvm::cl::opt<std::string> &Arg);
 
-  static Expected<FilterMatcher>
-  createRE(StringRef Filter, const cl::list<std::string> &Arg);
+  static Expected<FilterMatcher> createRE(StringRef Filter,
+                                          const cl::list<std::string> &Arg);
 
   static FilterMatcher createAny() { return {".*", true}; }
 



More information about the llvm-commits mailing list