2019-06-24 23:41:52 +08:00
|
|
|
//===- MlirOptMain.cpp - MLIR Optimizer Driver ----------------------------===//
|
|
|
|
//
|
2020-01-26 11:58:30 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
2019-12-24 01:35:36 +08:00
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2019-06-24 23:41:52 +08:00
|
|
|
//
|
2019-12-24 01:35:36 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-06-24 23:41:52 +08:00
|
|
|
//
|
|
|
|
// This is a utility that runs an optimization pass and prints the result back
|
|
|
|
// out. It is designed to support unit testing.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "mlir/Support/MlirOptMain.h"
|
2020-08-16 03:02:56 +08:00
|
|
|
#include "mlir/IR/AsmState.h"
|
2019-06-24 23:41:52 +08:00
|
|
|
#include "mlir/IR/Attributes.h"
|
|
|
|
#include "mlir/IR/Diagnostics.h"
|
2020-08-16 03:02:56 +08:00
|
|
|
#include "mlir/IR/Dialect.h"
|
2019-06-24 23:41:52 +08:00
|
|
|
#include "mlir/IR/Location.h"
|
|
|
|
#include "mlir/IR/MLIRContext.h"
|
|
|
|
#include "mlir/IR/Module.h"
|
|
|
|
#include "mlir/Parser.h"
|
|
|
|
#include "mlir/Pass/Pass.h"
|
|
|
|
#include "mlir/Pass/PassManager.h"
|
2020-08-16 03:02:56 +08:00
|
|
|
#include "mlir/Support/FileUtilities.h"
|
2019-09-24 09:17:52 +08:00
|
|
|
#include "mlir/Support/ToolUtilities.h"
|
2019-06-24 23:41:52 +08:00
|
|
|
#include "mlir/Transforms/Passes.h"
|
2020-08-16 03:02:56 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2019-06-24 23:41:52 +08:00
|
|
|
#include "llvm/Support/FileUtilities.h"
|
2020-08-16 03:02:56 +08:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2019-06-24 23:41:52 +08:00
|
|
|
#include "llvm/Support/Regex.h"
|
|
|
|
#include "llvm/Support/SourceMgr.h"
|
2020-08-16 03:02:56 +08:00
|
|
|
#include "llvm/Support/ToolOutputFile.h"
|
2019-06-24 23:41:52 +08:00
|
|
|
|
|
|
|
using namespace mlir;
|
|
|
|
using namespace llvm;
|
|
|
|
using llvm::SMLoc;
|
|
|
|
|
|
|
|
/// Perform the actions on the input file indicated by the command line flags
|
|
|
|
/// within the specified context.
|
|
|
|
///
|
|
|
|
/// This typically parses the main source file, runs zero or more optimization
|
|
|
|
/// passes, then prints the output.
|
|
|
|
///
|
2019-09-14 03:09:50 +08:00
|
|
|
static LogicalResult performActions(raw_ostream &os, bool verifyDiagnostics,
|
|
|
|
bool verifyPasses, SourceMgr &sourceMgr,
|
|
|
|
MLIRContext *context,
|
|
|
|
const PassPipelineCLParser &passPipeline) {
|
2020-05-05 02:21:49 +08:00
|
|
|
// Disable multi-threading when parsing the input file. This removes the
|
|
|
|
// unnecessary/costly context synchronization when parsing.
|
|
|
|
bool wasThreadingEnabled = context->isMultithreadingEnabled();
|
|
|
|
context->disableMultithreading();
|
|
|
|
|
|
|
|
// Parse the input file and reset the context threading state.
|
2019-07-03 01:49:17 +08:00
|
|
|
OwningModuleRef module(parseSourceFile(sourceMgr, context));
|
2020-05-05 02:21:49 +08:00
|
|
|
context->enableMultithreading(wasThreadingEnabled);
|
2019-06-24 23:41:52 +08:00
|
|
|
if (!module)
|
|
|
|
return failure();
|
|
|
|
|
2019-07-09 05:05:37 +08:00
|
|
|
// Apply any pass manager command line options.
|
2019-09-03 10:24:47 +08:00
|
|
|
PassManager pm(context, verifyPasses);
|
2019-07-09 05:05:37 +08:00
|
|
|
applyPassManagerCLOptions(pm);
|
|
|
|
|
2019-09-14 03:09:50 +08:00
|
|
|
// Build the provided pipeline.
|
2019-10-09 09:23:13 +08:00
|
|
|
if (failed(passPipeline.addToPipeline(pm)))
|
|
|
|
return failure();
|
2019-06-24 23:41:52 +08:00
|
|
|
|
|
|
|
// Run the pipeline.
|
2019-07-03 01:49:17 +08:00
|
|
|
if (failed(pm.run(*module)))
|
2019-06-24 23:41:52 +08:00
|
|
|
return failure();
|
|
|
|
|
|
|
|
// Print the output.
|
|
|
|
module->print(os);
|
2020-03-02 18:40:50 +08:00
|
|
|
os << '\n';
|
2019-06-24 23:41:52 +08:00
|
|
|
return success();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parses the memory buffer. If successfully, run a series of passes against
|
|
|
|
/// it and print the result.
|
2019-09-14 03:09:50 +08:00
|
|
|
static LogicalResult processBuffer(raw_ostream &os,
|
|
|
|
std::unique_ptr<MemoryBuffer> ownedBuffer,
|
|
|
|
bool verifyDiagnostics, bool verifyPasses,
|
2020-03-30 06:35:38 +08:00
|
|
|
bool allowUnregisteredDialects,
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
bool preloadDialectsInContext,
|
|
|
|
const PassPipelineCLParser &passPipeline,
|
|
|
|
DialectRegistry ®istry) {
|
2019-06-24 23:41:52 +08:00
|
|
|
// Tell sourceMgr about this buffer, which is what the parser will pick up.
|
|
|
|
SourceMgr sourceMgr;
|
|
|
|
sourceMgr.AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
|
|
|
|
|
|
|
|
// Parse the input file.
|
2020-10-24 04:19:35 +08:00
|
|
|
MLIRContext context;
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
registry.appendTo(context.getDialectRegistry());
|
|
|
|
if (preloadDialectsInContext)
|
|
|
|
registry.loadAll(&context);
|
2020-03-30 06:35:38 +08:00
|
|
|
context.allowUnregisteredDialects(allowUnregisteredDialects);
|
2020-04-04 10:02:39 +08:00
|
|
|
context.printOpOnDiagnostic(!verifyDiagnostics);
|
2019-06-24 23:41:52 +08:00
|
|
|
|
|
|
|
// If we are in verify diagnostics mode then we have a lot of work to do,
|
|
|
|
// otherwise just perform the actions without worrying about it.
|
|
|
|
if (!verifyDiagnostics) {
|
|
|
|
SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context);
|
|
|
|
return performActions(os, verifyDiagnostics, verifyPasses, sourceMgr,
|
2019-09-14 03:09:50 +08:00
|
|
|
&context, passPipeline);
|
2019-06-24 23:41:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceMgrDiagnosticVerifierHandler sourceMgrHandler(sourceMgr, &context);
|
|
|
|
|
|
|
|
// Do any processing requested by command line flags. We don't care whether
|
|
|
|
// these actions succeed or fail, we only care what diagnostics they produce
|
|
|
|
// and whether they match our expectations.
|
|
|
|
performActions(os, verifyDiagnostics, verifyPasses, sourceMgr, &context,
|
2019-09-14 03:09:50 +08:00
|
|
|
passPipeline);
|
2019-06-24 23:41:52 +08:00
|
|
|
|
|
|
|
// Verify the diagnostic handler to make sure that each of the diagnostics
|
|
|
|
// matched.
|
|
|
|
return sourceMgrHandler.verify();
|
|
|
|
}
|
|
|
|
|
2020-08-16 03:02:56 +08:00
|
|
|
LogicalResult mlir::MlirOptMain(raw_ostream &outputStream,
|
2019-09-14 03:09:50 +08:00
|
|
|
std::unique_ptr<MemoryBuffer> buffer,
|
|
|
|
const PassPipelineCLParser &passPipeline,
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
DialectRegistry ®istry, bool splitInputFile,
|
|
|
|
bool verifyDiagnostics, bool verifyPasses,
|
|
|
|
bool allowUnregisteredDialects,
|
|
|
|
bool preloadDialectsInContext) {
|
2019-06-24 23:41:52 +08:00
|
|
|
// The split-input-file mode is a very specific mode that slices the file
|
|
|
|
// up into small pieces and checks each independently.
|
|
|
|
if (splitInputFile)
|
2019-09-24 09:17:52 +08:00
|
|
|
return splitAndProcessBuffer(
|
|
|
|
std::move(buffer),
|
|
|
|
[&](std::unique_ptr<MemoryBuffer> chunkBuffer, raw_ostream &os) {
|
|
|
|
return processBuffer(os, std::move(chunkBuffer), verifyDiagnostics,
|
2020-03-30 06:35:38 +08:00
|
|
|
verifyPasses, allowUnregisteredDialects,
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
preloadDialectsInContext, passPipeline,
|
|
|
|
registry);
|
2019-09-24 09:17:52 +08:00
|
|
|
},
|
2020-08-16 03:02:56 +08:00
|
|
|
outputStream);
|
2019-06-24 23:41:52 +08:00
|
|
|
|
2020-08-16 03:02:56 +08:00
|
|
|
return processBuffer(outputStream, std::move(buffer), verifyDiagnostics,
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
verifyPasses, allowUnregisteredDialects,
|
|
|
|
preloadDialectsInContext, passPipeline, registry);
|
2020-08-16 03:02:56 +08:00
|
|
|
}
|
|
|
|
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
LogicalResult mlir::MlirOptMain(int argc, char **argv, llvm::StringRef toolName,
|
|
|
|
DialectRegistry ®istry,
|
|
|
|
bool preloadDialectsInContext) {
|
2020-08-16 03:02:56 +08:00
|
|
|
static cl::opt<std::string> inputFilename(
|
|
|
|
cl::Positional, cl::desc("<input file>"), cl::init("-"));
|
|
|
|
|
|
|
|
static cl::opt<std::string> outputFilename("o", cl::desc("Output filename"),
|
|
|
|
cl::value_desc("filename"),
|
|
|
|
cl::init("-"));
|
|
|
|
|
|
|
|
static cl::opt<bool> splitInputFile(
|
|
|
|
"split-input-file",
|
|
|
|
cl::desc("Split the input file into pieces and process each "
|
|
|
|
"chunk independently"),
|
|
|
|
cl::init(false));
|
|
|
|
|
|
|
|
static cl::opt<bool> verifyDiagnostics(
|
|
|
|
"verify-diagnostics",
|
|
|
|
cl::desc("Check that emitted diagnostics match "
|
|
|
|
"expected-* lines on the corresponding line"),
|
|
|
|
cl::init(false));
|
|
|
|
|
|
|
|
static cl::opt<bool> verifyPasses(
|
|
|
|
"verify-each",
|
|
|
|
cl::desc("Run the verifier after each transformation pass"),
|
|
|
|
cl::init(true));
|
|
|
|
|
|
|
|
static cl::opt<bool> allowUnregisteredDialects(
|
|
|
|
"allow-unregistered-dialect",
|
|
|
|
cl::desc("Allow operation with no registered dialects"), cl::init(false));
|
|
|
|
|
|
|
|
static cl::opt<bool> showDialects(
|
|
|
|
"show-dialects", cl::desc("Print the list of registered dialects"),
|
|
|
|
cl::init(false));
|
|
|
|
|
|
|
|
InitLLVM y(argc, argv);
|
|
|
|
|
|
|
|
// Register any command line options.
|
|
|
|
registerAsmPrinterCLOptions();
|
|
|
|
registerMLIRContextCLOptions();
|
|
|
|
registerPassManagerCLOptions();
|
|
|
|
PassPipelineCLParser passPipeline("", "Compiler passes to run");
|
|
|
|
|
|
|
|
// Build the list of dialects as a header for the --help message.
|
|
|
|
std::string helpHeader = (toolName + "\nAvailable Dialects: ").str();
|
|
|
|
{
|
|
|
|
llvm::raw_string_ostream os(helpHeader);
|
|
|
|
MLIRContext context;
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
interleaveComma(registry, os, [&](auto ®istryEntry) {
|
|
|
|
StringRef name = registryEntry.first;
|
|
|
|
os << name;
|
2020-08-16 03:02:56 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
// Parse pass names in main to ensure static initialization completed.
|
|
|
|
cl::ParseCommandLineOptions(argc, argv, helpHeader);
|
|
|
|
|
|
|
|
if (showDialects) {
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
llvm::outs() << "Available Dialects:\n";
|
2020-08-16 03:02:56 +08:00
|
|
|
interleave(
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
registry, llvm::outs(),
|
|
|
|
[](auto ®istryEntry) { llvm::outs() << registryEntry.first; }, "\n");
|
2020-08-16 03:02:56 +08:00
|
|
|
return success();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up the input file.
|
|
|
|
std::string errorMessage;
|
|
|
|
auto file = openInputFile(inputFilename, &errorMessage);
|
|
|
|
if (!file) {
|
|
|
|
llvm::errs() << errorMessage << "\n";
|
|
|
|
return failure();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto output = openOutputFile(outputFilename, &errorMessage);
|
|
|
|
if (!output) {
|
|
|
|
llvm::errs() << errorMessage << "\n";
|
|
|
|
return failure();
|
|
|
|
}
|
|
|
|
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
if (failed(MlirOptMain(output->os(), std::move(file), passPipeline, registry,
|
2020-08-16 03:02:56 +08:00
|
|
|
splitInputFile, verifyDiagnostics, verifyPasses,
|
Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.
This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.
To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.
1) For passes, you need to override the method:
virtual void getDependentDialects(DialectRegistry ®istry) const {}
and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.
2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.
3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:
mlir::DialectRegistry registry;
registry.insert<mlir::standalone::StandaloneDialect>();
registry.insert<mlir::StandardOpsDialect>();
Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:
mlir::registerAllDialects(registry);
4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 04:01:19 +08:00
|
|
|
allowUnregisteredDialects, preloadDialectsInContext)))
|
2020-08-16 03:02:56 +08:00
|
|
|
return failure();
|
|
|
|
|
|
|
|
// Keep the output file if the invocation of MlirOptMain was successful.
|
|
|
|
output->keep();
|
|
|
|
return success();
|
2019-06-24 23:41:52 +08:00
|
|
|
}
|