[llvm] 6e6a3d8 - [llvm-remarkutil] Introduce filter command (#159784)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 24 07:07:41 PDT 2025
Author: Tobias Stadler
Date: 2025-09-24T15:07:37+01:00
New Revision: 6e6a3d83245e3fbd5f51a6457b5ee492cb84db2b
URL: https://github.com/llvm/llvm-project/commit/6e6a3d83245e3fbd5f51a6457b5ee492cb84db2b
DIFF: https://github.com/llvm/llvm-project/commit/6e6a3d83245e3fbd5f51a6457b5ee492cb84db2b.diff
LOG: [llvm-remarkutil] Introduce filter command (#159784)
Add a filter command to llvm-remarkutil. This can be used to extract
remarks for a certain function, pass, type, etc. from a large remarks
file to a new remarks file. This uses the same filter arguments as the
count command.
Depends on #156715. Thanks to this change, we don't need to buffer all
remarks before reserializing them, so we should be able to process
arbitrarily large files.
Pull Request: https://github.com/llvm/llvm-project/pull/159784
Added:
llvm/test/tools/llvm-remarkutil/Inputs/filter.yaml
llvm/test/tools/llvm-remarkutil/filter.test
llvm/tools/llvm-remarkutil/RemarkFilter.cpp
Modified:
llvm/test/tools/llvm-remarkutil/broken-bitstream-remark-magic.test
llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test
llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
llvm/test/tools/llvm-remarkutil/empty-file.test
llvm/tools/llvm-remarkutil/CMakeLists.txt
llvm/tools/llvm-remarkutil/RemarkCounter.cpp
llvm/tools/llvm-remarkutil/RemarkCounter.h
llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-remarkutil/Inputs/filter.yaml b/llvm/test/tools/llvm-remarkutil/Inputs/filter.yaml
new file mode 100644
index 0000000000000..89def7fc4c0e5
--- /dev/null
+++ b/llvm/test/tools/llvm-remarkutil/Inputs/filter.yaml
@@ -0,0 +1,28 @@
+--- !Passed
+Pass: pass1
+Name: Remark1
+DebugLoc: { File: 'path/to/func1.c', Line: 1, Column: 2 }
+Function: func1
+Args:
+ - String: ' text'
+ - arg1: argval1
+...
+--- !Missed
+Pass: pass2
+Name: Remark2
+DebugLoc: { File: 'path/to/func2.c', Line: 1, Column: 2 }
+Function: func2
+Args:
+ - String: ' text'
+ - arg2: argval2
+...
+--- !Analysis
+Pass: pass3
+Name: Remark3
+DebugLoc: { File: 'path/to/func3.c', Line: 1, Column: 2 }
+Function: func3
+Args:
+ - String: ' text'
+ - arg3: argval3
+ DebugLoc: { File: 'path/to/func3.c', Line: 2, Column: 2 }
+...
diff --git a/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark-magic.test b/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark-magic.test
index f469eadc07f99..c21dbd72a2a18 100644
--- a/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark-magic.test
+++ b/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark-magic.test
@@ -2,5 +2,6 @@ RUN: not llvm-remarkutil instruction-count %p/Inputs/broken-remark-magic.bitstre
RUN: not llvm-remarkutil instruction-mix %p/Inputs/broken-remark-magic.bitstream -o - 2>&1 | FileCheck %s
RUN: not llvm-remarkutil annotation-count --annotation-type=remark %p/Inputs/broken-remark-magic.bitstream -o - 2>&1 | FileCheck %s
RUN: not llvm-remarkutil count %p/Inputs/broken-remark-magic.bitstream -o - 2>&1 | FileCheck %s
+RUN: not llvm-remarkutil filter %p/Inputs/broken-remark-magic.bitstream -o - 2>&1 | FileCheck %s
CHECK: error: Automatic detection of remark format failed. Unknown magic number: '1234'
diff --git a/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test b/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test
index 78011aece08f7..339f082d4825b 100644
--- a/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test
+++ b/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test
@@ -2,5 +2,6 @@ RUN: not llvm-remarkutil bitstream2yaml %p/Inputs/broken-remark -o - 2>&1 | File
RUN: not llvm-remarkutil instruction-count --parser=bitstream %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
RUN: not llvm-remarkutil annotation-count --parser=bitstream --annotation-type=remark %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
RUN: not llvm-remarkutil count --parser=bitstream %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
+RUN: not llvm-remarkutil filter --parser=bitstream %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
CHECK: error: Unknown magic number: expecting RMRK, got --- .
diff --git a/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test b/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
index 464d0b80c4ad0..9da3de4034b0f 100644
--- a/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
+++ b/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
@@ -3,5 +3,6 @@ RUN: not llvm-remarkutil instruction-count --parser=yaml %p/Inputs/broken-remark
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
+RUN: not llvm-remarkutil filter --parser=yaml %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s
CHECK: error: Type, Pass, Name or Function missing
diff --git a/llvm/test/tools/llvm-remarkutil/empty-file.test b/llvm/test/tools/llvm-remarkutil/empty-file.test
index d9820a088ea8f..9b2b000e9c24b 100644
--- a/llvm/test/tools/llvm-remarkutil/empty-file.test
+++ b/llvm/test/tools/llvm-remarkutil/empty-file.test
@@ -3,16 +3,19 @@ RUN: not llvm-remarkutil instruction-count --parser=yaml %p/Inputs/empty-file -o
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: not llvm-remarkutil filter --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
+RUN: llvm-remarkutil filter --parser=bitstream %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=FILTERBITSTREAM
; Parser format auto-detection should treat empty files as bitstream files
RUN: llvm-remarkutil instruction-count %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=SIZEBITSTREAM
RUN: llvm-remarkutil instruction-mix %p/Inputs/empty-file --report_style=csv -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=MIXBITSTREAM
RUN: llvm-remarkutil annotation-count --annotation-type=remark %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=ANNOTATIONBITSTREAM
RUN: llvm-remarkutil count %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=COUNTBITSTREAM
+RUN: llvm-remarkutil filter %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=FILTERBITSTREAM
; YAMLPARSER: error: document root is not of mapping type.
@@ -30,3 +33,5 @@ RUN: llvm-remarkutil count %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow
; MIXBITSTREAM-LABEL: Instruction,Count
; MIXBITSTREAM-EMPTY:
+
+; FILTERBITSTREAM-NOT: {{.}}
diff --git a/llvm/test/tools/llvm-remarkutil/filter.test b/llvm/test/tools/llvm-remarkutil/filter.test
new file mode 100644
index 0000000000000..8304b9f0129a8
--- /dev/null
+++ b/llvm/test/tools/llvm-remarkutil/filter.test
@@ -0,0 +1,59 @@
+RUN: llvm-remarkutil filter %p/Inputs/filter.yaml |
diff %p/Inputs/filter.yaml -
+RUN: llvm-remarkutil filter --rfunction=func %p/Inputs/filter.yaml |
diff %p/Inputs/filter.yaml -
+RUN: llvm-remarkutil filter --rremark-name=Remark %p/Inputs/filter.yaml |
diff %p/Inputs/filter.yaml -
+RUN: llvm-remarkutil filter --rpass-name=pass %p/Inputs/filter.yaml |
diff %p/Inputs/filter.yaml -
+RUN: llvm-remarkutil filter --rfilter-arg-by=argval %p/Inputs/filter.yaml |
diff %p/Inputs/filter.yaml -
+
+RUN: llvm-remarkutil filter --rfunction=unc1 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK1
+RUN: llvm-remarkutil filter --rremark-name=ark3 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK3
+RUN: llvm-remarkutil filter --rpass-name=s1 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK1
+RUN: llvm-remarkutil filter --filter-arg-by=argval2 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK2
+RUN: llvm-remarkutil filter --function=func1 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK1
+RUN: llvm-remarkutil filter --pass-name=pass2 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK2
+RUN: llvm-remarkutil filter --remark-name=Remark3 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK3
+RUN: llvm-remarkutil filter --function=func1 --pass-name=pass1 --remark-name=Remark1 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK1
+RUN: llvm-remarkutil filter --remark-type=passed %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK1
+RUN: llvm-remarkutil filter --remark-type=missed %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK2
+RUN: llvm-remarkutil filter --remark-type=analysis %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK3
+
+RUN: llvm-remarkutil yaml2bitstream -o %t.opt.bitstream %p/Inputs/filter.yaml
+RUN: llvm-remarkutil filter --function=func1 %t.opt.bitstream | FileCheck %s --strict-whitespace --check-prefix=REMARK1
+
+RUN: llvm-remarkutil filter --function=func1 %t.opt.bitstream -o %t.r1.opt.bitstream
+RUN: llvm-remarkutil bitstream2yaml %t.r1.opt.bitstream | FileCheck %s --strict-whitespace --check-prefix=REMARK1
+
+RUN: llvm-remarkutil filter --function=func %p/Inputs/filter.yaml | FileCheck %s --allow-empty --strict-whitespace --check-prefix=EMPTY
+
+; REMARK1: --- !Passed
+; REMARK1-NEXT: Pass: pass1
+; REMARK1-NEXT: Name: Remark1
+; REMARK1-NEXT: DebugLoc: { File: 'path/to/func1.c', Line: 1, Column: 2 }
+; REMARK1-NEXT: Function: func1
+; REMARK1-NEXT: Args:
+; REMARK1-NEXT: - String: ' text'
+; REMARK1-NEXT: - arg1: argval1
+; REMARK1-NEXT: ...
+; REMARK1-NOT: {{.}}
+; REMARK2: --- !Missed
+; REMARK2-NEXT: Pass: pass2
+; REMARK2-NEXT: Name: Remark2
+; REMARK2-NEXT: DebugLoc: { File: 'path/to/func2.c', Line: 1, Column: 2 }
+; REMARK2-NEXT: Function: func2
+; REMARK2-NEXT: Args:
+; REMARK2-NEXT: - String: ' text'
+; REMARK2-NEXT: - arg2: argval2
+; REMARK2-NEXT: ...
+; REMARK2-NOT: {{.}}
+; REMARK3: --- !Analysis
+; REMARK3-NEXT: Pass: pass3
+; REMARK3-NEXT: Name: Remark3
+; REMARK3-NEXT: DebugLoc: { File: 'path/to/func3.c', Line: 1, Column: 2 }
+; REMARK3-NEXT: Function: func3
+; REMARK3-NEXT: Args:
+; REMARK3-NEXT: - String: ' text'
+; REMARK3-NEXT: - arg3: argval3
+; REMARK3-NEXT: DebugLoc: { File: 'path/to/func3.c', Line: 2, Column: 2 }
+; REMARK3-NEXT: ...
+; REMARK3-NOT: {{.}}
+
+; EMPTY-NOT: {{.}}
diff --git a/llvm/tools/llvm-remarkutil/CMakeLists.txt b/llvm/tools/llvm-remarkutil/CMakeLists.txt
index ed398ad272024..c6e9334d87c04 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
+ RemarkFilter.cpp
RemarkInstructionMix.cpp
RemarkSizeDiff.cpp
RemarkUtil.cpp
diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
index 7d5c84815b3bb..2e842c8c2d72e 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -25,6 +25,9 @@ static cl::SubCommand CountSub("count",
INPUT_FORMAT_COMMAND_LINE_OPTIONS(CountSub)
INPUT_OUTPUT_COMMAND_LINE_OPTIONS(CountSub)
+REMARK_FILTER_COMMAND_LINE_OPTIONS(CountSub)
+
+REMARK_FILTER_SETUP_FUNC()
static cl::list<std::string>
Keys("args", cl::desc("Specify remark argument/s to count by."),
@@ -34,45 +37,7 @@ static cl::list<std::string> RKeys(
cl::desc(
"Specify remark argument/s to count (accepts regular expressions)."),
cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional);
-static cl::opt<std::string>
- RemarkNameOpt("remark-name",
- cl::desc("Optional remark name to filter collection by."),
- cl::ValueOptional, cl::sub(CountSub));
-static cl::opt<std::string>
- PassNameOpt("pass-name", cl::ValueOptional,
- cl::desc("Optional remark pass name to filter collection by."),
- cl::sub(CountSub));
-static cl::opt<std::string> RemarkFilterArgByOpt(
- "filter-arg-by", cl::desc("Optional remark arg to filter collection by."),
- cl::ValueOptional, cl::sub(CountSub));
-static cl::opt<std::string>
- RemarkNameOptRE("rremark-name",
- cl::desc("Optional remark name to filter collection by "
- "(accepts regular expressions)."),
- cl::ValueOptional, cl::sub(CountSub));
-static cl::opt<std::string>
- RemarkArgFilterOptRE("rfilter-arg-by",
- cl::desc("Optional remark arg to filter collection by "
- "(accepts regular expressions)."),
- cl::sub(CountSub), cl::ValueOptional);
-static cl::opt<std::string>
- PassNameOptRE("rpass-name", cl::ValueOptional,
- cl::desc("Optional remark pass name to filter collection "
- "by (accepts regular expressions)."),
- cl::sub(CountSub));
-static cl::opt<Type> RemarkTypeOpt(
- "remark-type", cl::desc("Optional remark type to filter collection by."),
- cl::values(clEnumValN(Type::Unknown, "unknown", "UNKOWN"),
- clEnumValN(Type::Passed, "passed", "PASSED"),
- clEnumValN(Type::Missed, "missed", "MISSED"),
- clEnumValN(Type::Analysis, "analysis", "ANALYSIS"),
- clEnumValN(Type::AnalysisFPCommute, "analysis-fp-commute",
- "ANALYSIS_FP_COMMUTE"),
- clEnumValN(Type::AnalysisAliasing, "analysis-aliasing",
- "ANALYSIS_ALIASING"),
- clEnumValN(Type::Failure, "failure", "FAILURE")),
- cl::init(Type::Failure), cl::sub(CountSub));
static cl::opt<CountBy> CountByOpt(
"count-by", cl::desc("Specify the property to collect remarks by."),
cl::values(
@@ -112,21 +77,6 @@ static unsigned getValForKey(StringRef Key, const Remark &Remark) {
return *RemarkArg->getValAsInt();
}
-bool Filters::filterRemark(const Remark &Remark) {
- if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
- return false;
- if (PassNameFilter && !PassNameFilter->match(Remark.PassName))
- return false;
- if (RemarkTypeFilter)
- return *RemarkTypeFilter == Remark.RemarkType;
- if (ArgFilter) {
- if (!any_of(Remark.Args,
- [this](Argument Arg) { return ArgFilter->match(Arg.Val); }))
- return false;
- }
- return true;
-}
-
Error ArgumentCounter::getAllMatchingArgumentsInRemark(
StringRef Buffer, ArrayRef<FilterMatcher> Arguments, Filters &Filter) {
auto MaybeParser = createRemarkParser(InputFormat, Buffer);
@@ -223,33 +173,6 @@ Error RemarkCounter::print(StringRef OutputFileName) {
return Error::success();
}
-Expected<Filters> getRemarkFilter() {
- // Create Filter properties.
- auto MaybeRemarkNameFilter =
- FilterMatcher::createExactOrRE(RemarkNameOpt, RemarkNameOptRE);
- if (!MaybeRemarkNameFilter)
- return MaybeRemarkNameFilter.takeError();
-
- auto MaybePassNameFilter =
- FilterMatcher::createExactOrRE(PassNameOpt, PassNameOptRE);
- if (!MaybePassNameFilter)
- return MaybePassNameFilter.takeError();
-
- auto MaybeRemarkArgFilter = FilterMatcher::createExactOrRE(
- RemarkFilterArgByOpt, RemarkArgFilterOptRE);
- if (!MaybeRemarkArgFilter)
- return MaybeRemarkArgFilter.takeError();
-
- std::optional<Type> RemarkType;
- if (RemarkTypeOpt != Type::Failure)
- RemarkType = RemarkTypeOpt;
-
- // Create RemarkFilter.
- return Filters{std::move(*MaybeRemarkNameFilter),
- std::move(*MaybePassNameFilter),
- std::move(*MaybeRemarkArgFilter), RemarkType};
-}
-
Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) {
// Create Parser.
auto MaybeParser = createRemarkParser(InputFormat, Buffer);
@@ -278,7 +201,7 @@ static Error collectRemarks() {
if (!MaybeBuf)
return MaybeBuf.takeError();
StringRef Buffer = (*MaybeBuf)->getBuffer();
- auto MaybeFilter = getRemarkFilter();
+ auto MaybeFilter = getRemarkFilters();
if (!MaybeFilter)
return MaybeFilter.takeError();
auto &Filter = *MaybeFilter;
diff --git a/llvm/tools/llvm-remarkutil/RemarkCounter.h b/llvm/tools/llvm-remarkutil/RemarkCounter.h
index 3b977791d87c2..69e552e3742ec 100644
--- a/llvm/tools/llvm-remarkutil/RemarkCounter.h
+++ b/llvm/tools/llvm-remarkutil/RemarkCounter.h
@@ -14,6 +14,7 @@
#include "RemarkUtilHelpers.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/Support/Regex.h"
+#include <map>
namespace llvm {
namespace remarks {
@@ -45,18 +46,6 @@ inline std::string groupByToStr(GroupBy GroupBy) {
}
}
-/// Filter out remarks based on remark properties based on name, pass name,
-/// argument and type.
-struct Filters {
- std::optional<FilterMatcher> RemarkNameFilter;
- std::optional<FilterMatcher> PassNameFilter;
- std::optional<FilterMatcher> ArgFilter;
- std::optional<Type> RemarkTypeFilter;
-
- /// Returns true if \p Remark satisfies all the provided filters.
- bool filterRemark(const Remark &Remark);
-};
-
/// Abstract counter class used to define the general required methods for
/// counting a remark.
struct Counter {
diff --git a/llvm/tools/llvm-remarkutil/RemarkFilter.cpp b/llvm/tools/llvm-remarkutil/RemarkFilter.cpp
new file mode 100644
index 0000000000000..acfef6608677c
--- /dev/null
+++ b/llvm/tools/llvm-remarkutil/RemarkFilter.cpp
@@ -0,0 +1,84 @@
+//===- RemarkFilter.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 filter remarks
+//
+//===----------------------------------------------------------------------===//
+
+#include "RemarkUtilHelpers.h"
+#include "RemarkUtilRegistry.h"
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Regex.h"
+
+using namespace llvm;
+using namespace remarks;
+using namespace llvm::remarkutil;
+
+namespace filter {
+
+static cl::SubCommand FilterSub("filter",
+ "Filter remarks based on specified criteria.");
+
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(FilterSub)
+OUTPUT_FORMAT_COMMAND_LINE_OPTIONS(FilterSub)
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(FilterSub)
+REMARK_FILTER_COMMAND_LINE_OPTIONS(FilterSub)
+
+REMARK_FILTER_SETUP_FUNC()
+
+static Error tryFilter() {
+ auto MaybeFilter = getRemarkFilters();
+ if (!MaybeFilter)
+ return MaybeFilter.takeError();
+ Filters &Filter = *MaybeFilter;
+
+ auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+ if (!MaybeBuf)
+ return MaybeBuf.takeError();
+ auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
+ if (!MaybeParser)
+ return MaybeParser.takeError();
+ auto &Parser = **MaybeParser;
+
+ Format SerializerFormat = OutputFormat;
+ if (SerializerFormat == Format::Auto) {
+ SerializerFormat = Parser.ParserFormat;
+ if (OutputFileName.empty() || OutputFileName == "-")
+ SerializerFormat = Format::YAML;
+ }
+
+ auto MaybeOF = getOutputFileForRemarks(OutputFileName, SerializerFormat);
+ if (!MaybeOF)
+ return MaybeOF.takeError();
+ auto OF = std::move(*MaybeOF);
+
+ auto MaybeSerializer = createRemarkSerializer(SerializerFormat, OF->os());
+ if (!MaybeSerializer)
+ return MaybeSerializer.takeError();
+ auto &Serializer = **MaybeSerializer;
+
+ auto MaybeRemark = Parser.next();
+ for (; MaybeRemark; MaybeRemark = Parser.next()) {
+ Remark &Remark = **MaybeRemark;
+ if (!Filter.filterRemark(Remark))
+ continue;
+ Serializer.emit(Remark);
+ }
+
+ auto E = MaybeRemark.takeError();
+ if (!E.isA<EndOfFileError>())
+ return E;
+ consumeError(std::move(E));
+ OF->keep();
+ return Error::success();
+}
+
+static CommandRegistration FilterReg(&FilterSub, tryFilter);
+
+} // namespace filter
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
index ad6c46eceb8f2..be529480e7d24 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
@@ -92,5 +92,22 @@ FilterMatcher::createExactOrRE(const llvm::cl::opt<std::string> &ExactArg,
return std::nullopt;
}
+bool Filters::filterRemark(const Remark &Remark) {
+ if (FunctionFilter && !FunctionFilter->match(Remark.FunctionName))
+ return false;
+ if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
+ return false;
+ if (PassNameFilter && !PassNameFilter->match(Remark.PassName))
+ return false;
+ if (RemarkTypeFilter)
+ return *RemarkTypeFilter == Remark.RemarkType;
+ if (ArgFilter) {
+ if (!any_of(Remark.Args,
+ [this](Argument Arg) { return ArgFilter->match(Arg.Val); }))
+ return false;
+ }
+ return true;
+}
+
} // namespace remarks
} // namespace llvm
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
index 894ac8354e18b..0dd550765c1c6 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -9,12 +9,11 @@
// Helpers for remark utilites
//
//===----------------------------------------------------------------------===//
-#include "llvm-c/Remarks.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Remarks/Remark.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Remarks/RemarkParser.h"
-#include "llvm/Remarks/YAMLRemarkSerializer.h"
+#include "llvm/Remarks/RemarkSerializer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
@@ -43,6 +42,16 @@
clEnumValN(Format::Bitstream, "bitstream", "Bitstream")), \
cl::sub(SUBOPT));
+#define OUTPUT_FORMAT_COMMAND_LINE_OPTIONS(SUBOPT) \
+ static cl::opt<Format> OutputFormat( \
+ "serializer", cl::init(Format::Auto), \
+ cl::desc("Output remark format to serialize"), \
+ cl::values(clEnumValN(Format::Auto, "auto", \
+ "Follow the parser format (default)"), \
+ clEnumValN(Format::YAML, "yaml", "YAML"), \
+ clEnumValN(Format::Bitstream, "bitstream", "Bitstream")), \
+ cl::sub(SUBOPT));
+
#define DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(SUBOPT) \
static cl::opt<bool> UseDebugLoc( \
"use-debug-loc", \
@@ -52,6 +61,87 @@
"number)"), \
cl::init(false), cl::sub(SUBOPT));
+#define REMARK_FILTER_COMMAND_LINE_OPTIONS(SUBOPT) \
+ static cl::opt<std::string> FunctionOpt( \
+ "function", cl::sub(SUBOPT), cl::ValueOptional, \
+ cl::desc("Optional function name to filter collection by.")); \
+ static cl::opt<std::string> FunctionOptRE( \
+ "rfunction", cl::sub(SUBOPT), cl::ValueOptional, \
+ cl::desc("Optional function name to filter collection by " \
+ "(accepts regular expressions).")); \
+ static cl::opt<std::string> RemarkNameOpt( \
+ "remark-name", \
+ cl::desc("Optional remark name to filter collection by."), \
+ cl::ValueOptional, cl::sub(SUBOPT)); \
+ static cl::opt<std::string> RemarkNameOptRE( \
+ "rremark-name", \
+ cl::desc("Optional remark name to filter collection by " \
+ "(accepts regular expressions)."), \
+ cl::ValueOptional, cl::sub(SUBOPT)); \
+ static cl::opt<std::string> PassNameOpt( \
+ "pass-name", cl::ValueOptional, \
+ cl::desc("Optional remark pass name to filter collection by."), \
+ cl::sub(SUBOPT)); \
+ static cl::opt<std::string> PassNameOptRE( \
+ "rpass-name", cl::ValueOptional, \
+ cl::desc("Optional remark pass name to filter collection " \
+ "by (accepts regular expressions)."), \
+ cl::sub(SUBOPT)); \
+ static cl::opt<Type> RemarkTypeOpt( \
+ "remark-type", \
+ cl::desc("Optional remark type to filter collection by."), \
+ cl::values(clEnumValN(Type::Unknown, "unknown", "UNKOWN"), \
+ clEnumValN(Type::Passed, "passed", "PASSED"), \
+ clEnumValN(Type::Missed, "missed", "MISSED"), \
+ clEnumValN(Type::Analysis, "analysis", "ANALYSIS"), \
+ clEnumValN(Type::AnalysisFPCommute, "analysis-fp-commute", \
+ "ANALYSIS_FP_COMMUTE"), \
+ clEnumValN(Type::AnalysisAliasing, "analysis-aliasing", \
+ "ANALYSIS_ALIASING"), \
+ clEnumValN(Type::Failure, "failure", "FAILURE")), \
+ cl::sub(SUBOPT)); \
+ static cl::opt<std::string> RemarkFilterArgByOpt( \
+ "filter-arg-by", \
+ cl::desc("Optional remark arg to filter collection by."), \
+ cl::ValueOptional, cl::sub(SUBOPT)); \
+ static cl::opt<std::string> RemarkArgFilterOptRE( \
+ "rfilter-arg-by", \
+ cl::desc("Optional remark arg to filter collection by " \
+ "(accepts regular expressions)."), \
+ cl::sub(SUBOPT), cl::ValueOptional);
+
+#define REMARK_FILTER_SETUP_FUNC() \
+ static Expected<Filters> getRemarkFilters() { \
+ auto MaybeFunctionFilter = \
+ FilterMatcher::createExactOrRE(FunctionOpt, FunctionOptRE); \
+ if (!MaybeFunctionFilter) \
+ return MaybeFunctionFilter.takeError(); \
+ \
+ auto MaybeRemarkNameFilter = \
+ FilterMatcher::createExactOrRE(RemarkNameOpt, RemarkNameOptRE); \
+ if (!MaybeRemarkNameFilter) \
+ return MaybeRemarkNameFilter.takeError(); \
+ \
+ auto MaybePassNameFilter = \
+ FilterMatcher::createExactOrRE(PassNameOpt, PassNameOptRE); \
+ if (!MaybePassNameFilter) \
+ return MaybePassNameFilter.takeError(); \
+ \
+ auto MaybeRemarkArgFilter = FilterMatcher::createExactOrRE( \
+ RemarkFilterArgByOpt, RemarkArgFilterOptRE); \
+ if (!MaybeRemarkArgFilter) \
+ return MaybeRemarkArgFilter.takeError(); \
+ \
+ std::optional<Type> TypeFilter; \
+ if (RemarkTypeOpt.getNumOccurrences()) \
+ TypeFilter = RemarkTypeOpt.getValue(); \
+ \
+ return Filters{std::move(*MaybeFunctionFilter), \
+ std::move(*MaybeRemarkNameFilter), \
+ std::move(*MaybePassNameFilter), \
+ std::move(*MaybeRemarkArgFilter), TypeFilter}; \
+ }
+
namespace llvm {
namespace remarks {
Expected<std::unique_ptr<MemoryBuffer>>
@@ -95,5 +185,18 @@ class FilterMatcher {
}
};
+/// Filter out remarks based on remark properties (function, remark name, pass
+/// name, argument values and type).
+struct Filters {
+ std::optional<FilterMatcher> FunctionFilter;
+ std::optional<FilterMatcher> RemarkNameFilter;
+ std::optional<FilterMatcher> PassNameFilter;
+ std::optional<FilterMatcher> ArgFilter;
+ std::optional<Type> RemarkTypeFilter;
+
+ /// Returns true if \p Remark satisfies all the provided filters.
+ bool filterRemark(const Remark &Remark);
+};
+
} // namespace remarks
} // namespace llvm
More information about the llvm-commits
mailing list