Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
44 changes: 44 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,15 +227,53 @@ 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 =
!getRemarksAllFilter().empty() || !getRemarksPassedFilter().empty() ||
!getRemarksFailedFilter().empty() ||
!getRemarksMissedFilter().empty() || !getRemarksAnalyseFilter().empty();
return hasFilters;
}

/// Reproducer file generation (no crash required).
StringRef getReproducerFilename() const { return generateReproducerFileFlag; }

/// Set the reproducer output filename
RemarkFormat getRemarkFormat() const { return remarkFormatFlag; }
/// Set the remark format to use.
std::string getRemarksAllFilter() const { return remarksAllFilterFlag; }
/// Set the remark output file.
std::string getRemarksOutputFile() const { return remarksOutputFileFlag; }
/// Set the remark passed filters.
std::string getRemarksPassedFilter() const { return remarksPassedFilterFlag; }
/// Set the remark failed filters.
std::string getRemarksFailedFilter() const { return remarksFailedFilterFlag; }
/// Set the remark missed filters.
std::string getRemarksMissedFilter() const { return remarksMissedFilterFlag; }
/// Set the remark analyse filters.
std::string getRemarksAnalyseFilter() const {
return remarksAnalyseFilterFlag;
}

protected:
/// Allow operation with no registered dialects.
/// This option is for convenience during testing only and discouraged in
/// general.
bool allowUnregisteredDialectsFlag = false;

/// Remark format
RemarkFormat remarkFormatFlag;
Copy link
Collaborator

Choose a reason for hiding this comment

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

The sanitizer issue is because there is no default here.

/// Remark file to output to
std::string remarksOutputFileFlag = "";
/// Remark filters
std::string remarksAllFilterFlag = "";
std::string remarksPassedFilterFlag = "";
std::string remarksFailedFilterFlag = "";
std::string remarksMissedFilterFlag = "";
std::string remarksAnalyseFilterFlag = "";

/// Configuration for the debugging hooks.
tracing::DebugConfig debugConfig;

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
)
120 changes: 111 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,58 @@ 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(remarksAllFilterFlag), cl::init(""),
cl::cat(remarkCategory));

static cl::opt<std::string, /*ExternalStorage=*/true> remarksFile(
"remarks-output-file",
cl::desc(
"Output file for yaml and bitstream remark formats. Default is "
"mlir-remarks.yaml or mlir-remarks.bitstream"),
cl::location(remarksOutputFileFlag), cl::init(""),
cl::cat(remarkCategory));

static cl::opt<std::string, /*ExternalStorage=*/true> remarksPassed(
"remarks-passed", cl::desc("Show passed remarks"),
cl::location(remarksPassedFilterFlag), cl::init(""),
cl::cat(remarkCategory));

static cl::opt<std::string, /*ExternalStorage=*/true> remarksFailed(
"remarks-failed", cl::desc("Show failed remarks"),
cl::location(remarksFailedFilterFlag), cl::init(""),
cl::cat(remarkCategory));

static cl::opt<std::string, /*ExternalStorage=*/true> remarksMissed(
"remarks-missed", cl::desc("Show missed remarks"),
cl::location(remarksMissedFilterFlag), cl::init(""),
cl::cat(remarkCategory));

static cl::opt<std::string, /*ExternalStorage=*/true> remarksAnalyse(
"remarks-analyse", cl::desc("Show analysis remarks"),
cl::location(remarksAnalyseFilterFlag), 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 +296,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 +517,53 @@ 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.getRemarksAllFilter(), config.getRemarksPassedFilter()),
combine(config.getRemarksAllFilter(), config.getRemarksMissedFilter()),
combine(config.getRemarksAllFilter(), config.getRemarksAnalyseFilter()),
combine(config.getRemarksAllFilter(), config.getRemarksFailedFilter())};

mlir::MLIRContext &ctx = *context;

switch (config.getRemarkFormat()) {
case REMARK_FORMAT_STDOUT:
if (failed(mlir::remark::enableOptimizationRemarks(
ctx, nullptr, cats, true /*printAsEmitRemarks*/)))
return failure();
break;

case REMARK_FORMAT_YAML: {
std::string file = config.getRemarksOutputFile().empty()
? "mlir-remarks.yaml"
: config.getRemarksOutputFile();
if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
ctx, file, llvm::remarks::Format::YAML, cats)))
return failure();
break;
}

case REMARK_FORMAT_BITSTREAM: {
std::string file = config.getRemarksOutputFile().empty()
? "mlir-remarks.bitstream"
: config.getRemarksOutputFile();
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 +625,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 +771,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
50 changes: 50 additions & 0 deletions mlir/test/Pass/remarks.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// RUN: mlir-opt %s --test-remark --remarks-passed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-PASSED
// RUN: mlir-opt %s --test-remark --remarks-missed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-MISSED
// RUN: mlir-opt %s --test-remark --remarks-failed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-FAILED
// RUN: mlir-opt %s --test-remark --remarks-analyse="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ANALYSIS
// RUN: mlir-opt %s --test-remark --remarks="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL
// RUN: mlir-opt %s --test-remark --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"
// CHECK-ALL1-NOT: remarks.mlir:8:3: remark: [Failure]
// CHECK-ALL1-NOT: remarks.mlir:8:3: remark: [Analysis]
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
Loading