Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -221,9 +227,27 @@ 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 =
!remarksAllFlag.empty() || !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 remarksAllFlag = "";
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
Expand Down
1 change: 1 addition & 0 deletions mlir/lib/Tools/mlir-opt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ add_mlir_library(MLIROptLib
MLIRPluginsLib
MLIRSupport
MLIRIRDL
MLIRRemarkStreamer
)
104 changes: 95 additions & 9 deletions mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,19 @@
#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"
#include "mlir/Tools/ParseUtilities.h"
#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"
Expand Down Expand Up @@ -204,6 +207,46 @@ 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{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a using namespace llvm and mlir above, so no need to qualify these here (and also inconsistent with ones just below and above).

"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> remarksAll(
"remarks",
cl::desc("Show all remarks: passed, missed, failed, analysis"),
cl::location(remarksAllFlag), cl::init(""), 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);
Expand Down Expand Up @@ -241,23 +284,23 @@ class DiagnosticFilter : public ScopedDiagnosticHandler {
setHandler([verbosityLevel, showNotes](Diagnostic &diag) {
auto severity = diag.getSeverity();
switch (severity) {
case DiagnosticSeverity::Error:
case mlir::DiagnosticSeverity::Error:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why were these changes needed?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conflict with the LLVM class of the same name I believe (there is an added include to LLVM)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is the reason exactly

// 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
Expand Down Expand Up @@ -462,6 +505,49 @@ performActions(raw_ostream &os,

context->enableMultithreading(wasThreadingEnabled);

// Set up optimization remarks.
if (config.shouldEmitRemarks()) {
auto combine = [](const std::string &a, const std::string &b) {
if (a.empty())
return b;
if (b.empty())
return a;
return a + "|" + b;
};

remark::RemarkCategories cats{
combine(config.remarksAllFlag, config.remarksPassedFlag),
combine(config.remarksAllFlag, config.remarksMissedFlag),
combine(config.remarksAllFlag, config.remarksAnalyseFlag),
combine(config.remarksAllFlag, config.remarksFailedFlag)};

mlir::MLIRContext &ctx = *context;

switch (config.remarkFormatFlag) {
case REMARK_FORMAT_STDOUT:
if (failed(mlir::remark::enableOptimizationRemarks(
ctx, nullptr, cats, true /*printAsEmitRemarks*/)))
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());
Expand Down Expand Up @@ -523,8 +609,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);
Expand Down Expand Up @@ -669,9 +755,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 "
Expand Down
48 changes: 48 additions & 0 deletions mlir/test/Pass/remarks.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// RUN: mlir-opt %s --test-remark-pipeline --remarks-passed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-PASSED
// RUN: mlir-opt %s --test-remark-pipeline --remarks-missed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-MISSED
// RUN: mlir-opt %s --test-remark-pipeline --remarks-failed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-FAILED
// RUN: mlir-opt %s --test-remark-pipeline --remarks-analyse="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ANALYSIS
// RUN: mlir-opt %s --test-remark-pipeline --remarks="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL
// RUN: mlir-opt %s --test-remark-pipeline --remarks="category-1" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL1
module @foo {
"test.op"() : () -> ()
"test.op2"() : () -> ()
}


// CHECK-PASSED: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
// CHECK-PASSED: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
// CHECK-PASSED: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"

// CHECK-MISSED:remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-MISSED:remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-MISSED:remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"

// CHECK-FAILED: remarks.mlir:8:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
// CHECK-FAILED: remarks.mlir:9:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
// CHECK-FAILED: remarks.mlir:7:1: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"

// CHECK-ANALYSIS: remarks.mlir:8:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
// CHECK-ANALYSIS: remarks.mlir:9:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
// CHECK-ANALYSIS: remarks.mlir:7:1: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"


// CHECK-ALL: remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:8:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:8:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
// CHECK-ALL: remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:9:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:9:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
// CHECK-ALL: remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:7:1: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL: remarks.mlir:7:1: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"

// CHECK-ALL1: remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL1: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL1: remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL1: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL1: remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
// CHECK-ALL1: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
1 change: 1 addition & 0 deletions mlir/test/lib/Pass/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_mlir_library(MLIRTestPass
TestConvertToSPIRVPass.cpp
TestDynamicPipeline.cpp
TestPassManager.cpp
TestRemarksPipeline.cpp
TestSPIRVCPURunnerPipeline.cpp
TestVulkanRunnerPipeline.cpp

Expand Down
80 changes: 80 additions & 0 deletions mlir/test/lib/Pass/TestRemarksPipeline.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===------ TestRemarkPipeline.cpp --- dynamic pipeline test pass --------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass to test the dynamic pipeline feature.
//
//===----------------------------------------------------------------------===//

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/Remarks.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"

using namespace mlir;

namespace {

class TestRemarkPipelinePass
: public PassWrapper<TestRemarkPipelinePass, OperationPass<>> {
public:
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestRemarkPipelinePass)

StringRef getArgument() const final { return "test-remark-pipeline"; }
StringRef getDescription() const final {
return "Tests the remark pipeline feature";
}
void getDependentDialects(DialectRegistry &registry) const override {
OpPassManager pm(ModuleOp::getOperationName(),
OpPassManager::Nesting::Implicit);

pm.getDependentDialects(registry);
}

TestRemarkPipelinePass() = default;

void runOnOperation() override {

getOperation()->walk([](Operation *op) {
Location loc = op->getLoc();
mlir::remark::missed(
loc,
remark::RemarkOpts::name("test-remark").category("category-1-missed"))
<< remark::add("This is a test missed remark")
<< remark::reason("because we are testing the remark pipeline")
<< remark::suggest("try using the remark pipeline feature");

mlir::remark::passed(
loc,
remark::RemarkOpts::name("test-remark").category("category-1-passed"))
<< remark::add("This is a test passed remark")
<< remark::reason("because we are testing the remark pipeline")
<< remark::suggest("try using the remark pipeline feature");

mlir::remark::failed(
loc,
remark::RemarkOpts::name("test-remark").category("category-2-failed"))
<< remark::add("This is a test failed remark")
<< remark::reason("because we are testing the remark pipeline")
<< remark::suggest("try using the remark pipeline feature");

mlir::remark::analysis(loc, remark::RemarkOpts::name("test-remark")
.category("category-2-analysis"))
<< remark::add("This is a test analysis remark");
});
}
};
} // namespace

namespace mlir {
namespace test {
void registerTestRemarkPipelinePass() {
PassRegistration<TestRemarkPipelinePass>();
}
} // namespace test
} // namespace mlir
2 changes: 2 additions & 0 deletions mlir/tools/mlir-opt/mlir-opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void registerTestDiagnosticsPass();
void registerTestDiagnosticsMetadataPass();
void registerTestDominancePass();
void registerTestDynamicPipelinePass();
void registerTestRemarkPipelinePass();
void registerTestEmulateNarrowTypePass();
void registerTestFooAnalysisPass();
void registerTestComposeSubView();
Expand Down Expand Up @@ -243,6 +244,7 @@ void registerTestPasses() {
mlir::test::registerTestDiagnosticsMetadataPass();
mlir::test::registerTestDominancePass();
mlir::test::registerTestDynamicPipelinePass();
mlir::test::registerTestRemarkPipelinePass();
mlir::test::registerTestEmulateNarrowTypePass();
mlir::test::registerTestFooAnalysisPass();
mlir::test::registerTestComposeSubView();
Expand Down
2 changes: 1 addition & 1 deletion mlir/unittests/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ add_mlir_unittest(MLIRIRTests
MemrefLayoutTest.cpp
OperationSupportTest.cpp
PatternMatchTest.cpp
RemarkTest.cpp
RemarkTest.cpp
ShapedTypeTest.cpp
SymbolTableTest.cpp
TypeTest.cpp
Expand Down