-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[MLIR] Add remark flags to mlir-opt #156825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
a3e2893
a9a0b54
e769225
88f649d
d724f85
a117fe5
c52555b
6f55cc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,4 +13,5 @@ add_mlir_library(MLIROptLib | |
MLIRPluginsLib | ||
MLIRSupport | ||
MLIRIRDL | ||
MLIRRemarkStreamer | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -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{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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)); | ||
grypp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// Set the callback to load a pass plugin. | ||
passPlugins.setCallback([&](const std::string &pluginPath) { | ||
auto plugin = PassPlugin::load(pluginPath); | ||
|
@@ -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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why were these changes needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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"}; | ||
grypp marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
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 +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); | ||
|
@@ -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 " | ||
|
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" | ||
grypp marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
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"; } | ||
grypp marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
StringRef getDescription() const final { | ||
return "Tests the remark pipeline feature"; | ||
} | ||
void getDependentDialects(DialectRegistry ®istry) const override { | ||
OpPassManager pm(ModuleOp::getOperationName(), | ||
OpPassManager::Nesting::Implicit); | ||
|
||
pm.getDependentDialects(registry); | ||
} | ||
grypp marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
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 |
Uh oh!
There was an error while loading. Please reload this page.