[Mlir-commits] [mlir] [MLIR] Add remark flags to mlir-opt (PR #156825)
Guray Ozen
llvmlistbot at llvm.org
Thu Sep 4 01:27:34 PDT 2025
https://github.com/grypp created https://github.com/llvm/llvm-project/pull/156825
Adds remark flags to `mlir-opt`:
```
Remark Options:
Filter remarks by regular expression (llvm::Regex syntax).
--remark-format=<value> - Specify the format for remark output.
=emitRemark - Print as emitRemark to command-line
=yaml - Print yaml file
=bitstream - Print bitstream file
--remarks-analyse=<string> - Show analysis remarks
--remarks-failed=<string> - Show failed remarks
--remarks-missed=<string> - Show missed remarks
--remarks-passed=<string> - Show passed remarks
```
>From a3e2893fd9dc72f0bfabd5be414c2b666367787b Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Thu, 4 Sep 2025 10:26:33 +0200
Subject: [PATCH] [MLIR] Add remark flags to mlir-opt
---
.../include/mlir/Tools/mlir-opt/MlirOptMain.h | 22 +++++
mlir/lib/Tools/mlir-opt/CMakeLists.txt | 1 +
mlir/lib/Tools/mlir-opt/MlirOptMain.cpp | 88 +++++++++++++++++--
mlir/unittests/IR/CMakeLists.txt | 2 +-
4 files changed, 103 insertions(+), 10 deletions(-)
diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
index 94231227599c9..dc6a6a1c3cc42 100644
--- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
+++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
@@ -38,6 +38,12 @@ enum class VerbosityLevel {
ErrorsWarningsAndRemarks
};
+using RemarkFormat = enum {
+ REMARK_FORMAT_STDOUT,
+ REMARK_FORMAT_YAML,
+ REMARK_FORMAT_BITSTREAM,
+};
+
/// Configuration options for the mlir-opt tool.
/// This is intended to help building tools like mlir-opt by collecting the
/// supported options.
@@ -221,9 +227,25 @@ class MlirOptMainConfig {
}
bool shouldVerifyRoundtrip() const { return verifyRoundtripFlag; }
+ /// Checks if any remark filters are set.
+ bool shouldEmitRemarks() const {
+ // Emit all remarks only when no filters are specified.
+ const bool hasFilters =
+ !remarksPassedFlag.empty() || !remarksFailedFlag.empty() ||
+ !remarksMissedFlag.empty() || !remarksAnalyseFlag.empty();
+ return hasFilters;
+ }
+
/// Reproducer file generation (no crash required).
StringRef getReproducerFilename() const { return generateReproducerFileFlag; }
+ /// Remark options
+ RemarkFormat remarkFormatFlag;
+ std::string remarksPassedFlag = "";
+ std::string remarksFailedFlag = "";
+ std::string remarksMissedFlag = "";
+ std::string remarksAnalyseFlag = "";
+
protected:
/// Allow operation with no registered dialects.
/// This option is for convenience during testing only and discouraged in
diff --git a/mlir/lib/Tools/mlir-opt/CMakeLists.txt b/mlir/lib/Tools/mlir-opt/CMakeLists.txt
index f24d4c60174ee..858c9c1f97f9c 100644
--- a/mlir/lib/Tools/mlir-opt/CMakeLists.txt
+++ b/mlir/lib/Tools/mlir-opt/CMakeLists.txt
@@ -13,4 +13,5 @@ add_mlir_library(MLIROptLib
MLIRPluginsLib
MLIRSupport
MLIRIRDL
+ MLIRRemarkStreamer
)
diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
index de714d8b740af..c456540cc1793 100644
--- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
+++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
@@ -23,9 +23,11 @@
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Remarks.h"
#include "mlir/Parser/Parser.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Pass/PassRegistry.h"
+#include "mlir/Remark/RemarkStreamer.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Support/Timing.h"
#include "mlir/Support/ToolUtilities.h"
@@ -33,6 +35,7 @@
#include "mlir/Tools/Plugins/DialectPlugin.h"
#include "mlir/Tools/Plugins/PassPlugin.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LogicalResult.h"
@@ -204,6 +207,41 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
cl::location(generateReproducerFileFlag), cl::init(""),
cl::value_desc("filename"));
+ static cl::OptionCategory remarkCategory(
+ "Remark Options",
+ "Filter remarks by regular expression (llvm::Regex syntax).");
+
+ static llvm::cl::opt<RemarkFormat, /*ExternalStorage=*/true> remarkFormat{
+ "remark-format",
+ llvm::cl::desc("Specify the format for remark output."),
+ cl::location(remarkFormatFlag),
+ llvm::cl::value_desc("format"),
+ llvm::cl::init(REMARK_FORMAT_STDOUT),
+ llvm::cl::values(
+ clEnumValN(REMARK_FORMAT_STDOUT, "emitRemark",
+ "Print as emitRemark to command-line"),
+ clEnumValN(REMARK_FORMAT_YAML, "yaml", "Print yaml file"),
+ clEnumValN(REMARK_FORMAT_BITSTREAM, "bitstream",
+ "Print bitstream file")),
+ llvm::cl::cat(remarkCategory)};
+
+ static cl::opt<std::string, /*ExternalStorage=*/true> remarksPassed(
+ "remarks-passed", cl::desc("Show passed remarks"),
+ cl::location(remarksPassedFlag), cl::init(""), cl::cat(remarkCategory));
+
+ static cl::opt<std::string, /*ExternalStorage=*/true> remarksFailed(
+ "remarks-failed", cl::desc("Show failed remarks"),
+ cl::location(remarksFailedFlag), cl::init(""), cl::cat(remarkCategory));
+
+ static cl::opt<std::string, /*ExternalStorage=*/true> remarksMissed(
+ "remarks-missed", cl::desc("Show missed remarks"),
+ cl::location(remarksMissedFlag), cl::init(""), cl::cat(remarkCategory));
+
+ static cl::opt<std::string, /*ExternalStorage=*/true> remarksAnalyse(
+ "remarks-analyse", cl::desc("Show analysis remarks"),
+ cl::location(remarksAnalyseFlag), cl::init(""),
+ cl::cat(remarkCategory));
+
/// Set the callback to load a pass plugin.
passPlugins.setCallback([&](const std::string &pluginPath) {
auto plugin = PassPlugin::load(pluginPath);
@@ -241,23 +279,23 @@ class DiagnosticFilter : public ScopedDiagnosticHandler {
setHandler([verbosityLevel, showNotes](Diagnostic &diag) {
auto severity = diag.getSeverity();
switch (severity) {
- case DiagnosticSeverity::Error:
+ case mlir::DiagnosticSeverity::Error:
// failure indicates that the error is not handled by the filter and
// goes through to the default handler. Therefore, the error can be
// successfully printed.
return failure();
- case DiagnosticSeverity::Warning:
+ case mlir::DiagnosticSeverity::Warning:
if (verbosityLevel == VerbosityLevel::ErrorsOnly)
return success();
else
return failure();
- case DiagnosticSeverity::Remark:
+ case mlir::DiagnosticSeverity::Remark:
if (verbosityLevel == VerbosityLevel::ErrorsOnly ||
verbosityLevel == VerbosityLevel::ErrorsAndWarnings)
return success();
else
return failure();
- case DiagnosticSeverity::Note:
+ case mlir::DiagnosticSeverity::Note:
if (showNotes)
return failure();
else
@@ -462,6 +500,38 @@ performActions(raw_ostream &os,
context->enableMultithreading(wasThreadingEnabled);
+ // Set up optimization remarks.
+ if (config.shouldEmitRemarks()) {
+ remark::RemarkCategories cats{
+ config.remarksPassedFlag, config.remarksFailedFlag,
+ config.remarksMissedFlag, config.remarksAnalyseFlag};
+
+ mlir::MLIRContext &ctx = *context;
+
+ switch (config.remarkFormatFlag) {
+ case REMARK_FORMAT_STDOUT:
+ if (failed(mlir::remark::enableOptimizationRemarks(ctx, nullptr, cats)))
+ return failure();
+ break;
+
+ case REMARK_FORMAT_YAML: {
+ constexpr llvm::StringLiteral file{"mlir-remarks.yaml"};
+ if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
+ ctx, file, llvm::remarks::Format::YAML, cats)))
+ return failure();
+ break;
+ }
+
+ case REMARK_FORMAT_BITSTREAM: {
+ constexpr llvm::StringLiteral File{"mlir-remarks.bitstream"};
+ if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
+ ctx, File, llvm::remarks::Format::Bitstream, cats)))
+ return failure();
+ break;
+ }
+ }
+ }
+
// Prepare the pass manager, applying command-line and reproducer options.
PassManager pm(op.get()->getName(), PassManager::Nesting::Implicit);
pm.enableVerifier(config.shouldVerifyPasses());
@@ -523,8 +593,8 @@ processBuffer(raw_ostream &os, std::unique_ptr<MemoryBuffer> ownedBuffer,
SMLoc());
sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
- // Create a context just for the current buffer. Disable threading on creation
- // since we'll inject the thread-pool separately.
+ // Create a context just for the current buffer. Disable threading on
+ // creation since we'll inject the thread-pool separately.
MLIRContext context(registry, MLIRContext::Threading::DISABLED);
if (threadPool)
context.setThreadPool(*threadPool);
@@ -669,9 +739,9 @@ LogicalResult mlir::MlirOptMain(int argc, char **argv,
if (config.shouldListPasses())
return printRegisteredPassesAndReturn();
- // When reading from stdin and the input is a tty, it is often a user mistake
- // and the process "appears to be stuck". Print a message to let the user know
- // about it!
+ // When reading from stdin and the input is a tty, it is often a user
+ // mistake and the process "appears to be stuck". Print a message to let the
+ // user know about it!
if (inputFilename == "-" &&
sys::Process::FileDescriptorIsDisplayed(fileno(stdin)))
llvm::errs() << "(processing input from stdin now, hit ctrl-c/ctrl-d to "
diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt
index 75cd2d65ef5a1..dd3b110dcd295 100644
--- a/mlir/unittests/IR/CMakeLists.txt
+++ b/mlir/unittests/IR/CMakeLists.txt
@@ -14,7 +14,7 @@ add_mlir_unittest(MLIRIRTests
MemrefLayoutTest.cpp
OperationSupportTest.cpp
PatternMatchTest.cpp
- RemarkTest.cpp
+ RemarkTest.cpp
ShapedTypeTest.cpp
SymbolTableTest.cpp
TypeTest.cpp
More information about the Mlir-commits
mailing list