llvm-project/mlir/tools/mlir-opt/mlir-opt.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

220 lines
8.1 KiB
C++
Raw Normal View History

//===- mlir-opt.cpp - MLIR Optimizer Driver -------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Main entry function for mlir-opt for when built as standalone binary.
//
//===----------------------------------------------------------------------===//
#include "mlir/IR/AsmState.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/InitAllDialects.h"
#include "mlir/InitAllPasses.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Support/MlirOptMain.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/ToolOutputFile.h"
using namespace llvm;
using namespace mlir;
// Defined in the test directory, no public header.
namespace mlir {
void registerConvertToTargetEnvPass();
void registerPassManagerTestPass();
void registerPrintSpirvAvailabilityPass();
void registerShapeFunctionTestPasses();
[mlir][SideEffects] Define a set of interfaces and traits for defining side effects This revision introduces the infrastructure for defining side-effects and attaching them to operations. This infrastructure allows for defining different types of side effects, that don't interact with each other, but use the same internal mechanisms. At the base of this is an interface that allows operations to specify the different effect instances that are exhibited by a specific operation instance. An effect instance is comprised of the following: * Effect: The specific effect being applied. For memory related effects this may be reading from memory, storing to memory, etc. * Value: A specific value, either operand/result/region argument, the effect pertains to. * Resource: This is a global entity that represents the domain within which the effect is being applied. MLIR serves many different abstractions, which cover many different domains. Simple effects are may have very different context, for example writing to an in-memory buffer vs a database. This revision defines uses this infrastructure to define a set of initial MemoryEffects. The are effects that generally correspond to memory of some kind; Allocate, Free, Read, Write. This set of memory effects will be used in follow revisions to generalize various parts of the compiler, and make others more powerful(e.g. DCE). This infrastructure was originally proposed here: https://groups.google.com/a/tensorflow.org/g/mlir/c/v2mNl4vFCUM Differential Revision: https://reviews.llvm.org/D74439
2020-03-07 05:53:16 +08:00
void registerSideEffectTestPasses();
void registerSliceAnalysisTestPass();
void registerSymbolTestPasses();
void registerTestAffineDataCopyPass();
void registerTestAffineLoopUnswitchingPass();
void registerTestAllReduceLoweringPass();
void registerTestFunc();
void registerTestGpuMemoryPromotionPass();
void registerTestLoopPermutationPass();
void registerTestMatchers();
void registerTestOperationEqualPass();
void registerTestPrintDefUsePass();
void registerTestPrintNestingPass();
void registerTestReducer();
void registerTestSpirvEntryPointABIPass();
void registerTestSpirvGLSLCanonicalizationPass();
void registerTestSpirvModuleCombinerPass();
void registerTestTraitsPass();
void registerTosaTestQuantUtilAPIPass();
void registerVectorizerTestPass();
namespace test {
void registerConvertCallOpPass();
void registerInliner();
void registerMemRefBoundCheck();
void registerPatternsTestPass();
void registerSimpleParametricTilingPass();
void registerTestAffineLoopParametricTilingPass();
void registerTestAliasAnalysisPass();
[mlir] Refactor ElementsAttr into an AttrInterface This revision refactors ElementsAttr into an Attribute Interface. This enables a common interface with which to interact with element attributes, without needing to modify the builtin dialect. It also removes a majority (if not all?) of the need for the current OpaqueElementsAttr, which was originally intended as a way to opaquely represent data that was not representable by the other builtin constructs. The new ElementsAttr interface not only allows for users to natively represent their data in the way that best suits them, it also allows for efficient opaque access and iteration of the underlying data. Attributes using the ElementsAttr interface can directly expose support for interacting with the held elements using any C++ data type they claim to support. For example, DenseIntOrFpElementsAttr supports iteration using various native C++ integer/float data types, as well as APInt/APFloat, and more. ElementsAttr instances that refer to DenseIntOrFpElementsAttr can use all of these data types for iteration: ```c++ DenseIntOrFpElementsAttr intElementsAttr = ...; ElementsAttr attr = intElementsAttr; for (uint64_t value : attr.getValues<uint64_t>()) ...; for (APInt value : attr.getValues<APInt>()) ...; for (IntegerAttr value : attr.getValues<IntegerAttr>()) ...; ``` ElementsAttr also supports failable range/iterator access, allowing for selective code paths depending on data type support: ```c++ ElementsAttr attr = ...; if (auto range = attr.tryGetValues<uint64_t>()) { for (uint64_t value : *range) ...; } ``` Differential Revision: https://reviews.llvm.org/D109190
2021-09-21 09:40:45 +08:00
void registerTestBuiltinAttributeInterfaces();
void registerTestCallGraphPass();
void registerTestComprehensiveFunctionBufferize();
void registerTestConstantFold();
void registerTestConvVectorization();
void registerTestGpuSerializeToCubinPass();
void registerTestGpuSerializeToHsacoPass();
void registerTestDataLayoutQuery();
void registerTestDecomposeCallGraphTypes();
void registerTestDiagnosticsPass();
void registerTestDominancePass();
void registerTestDynamicPipelinePass();
void registerTestExpandTanhPass();
void registerTestComposeSubView();
void registerTestGpuParallelLoopMappingPass();
void registerTestIRVisitorsPass();
void registerTestInterfaces();
void registerTestLinalgCodegenStrategy();
void registerTestLinalgControlFuseByExpansion();
void registerTestLinalgDistribution();
void registerTestLinalgElementwiseFusion();
void registerTestPushExpandingReshape();
void registerTestLinalgFusionTransforms();
void registerTestLinalgTensorFusionTransforms();
void registerTestLinalgTiledLoopFusionTransforms();
void registerTestLinalgGreedyFusion();
void registerTestLinalgHoisting();
void registerTestLinalgTileAndFuseSequencePass();
void registerTestLinalgTransforms();
void registerTestLivenessPass();
void registerTestLoopFusion();
void registerTestLoopMappingPass();
void registerTestLoopUnrollingPass();
void registerTestMatchReductionPass();
void registerTestMathAlgebraicSimplificationPass();
void registerTestMathPolynomialApproximationPass();
void registerTestMemRefDependenceCheck();
void registerTestMemRefStrideCalculation();
void registerTestNumberOfBlockExecutionsPass();
void registerTestNumberOfOperationExecutionsPass();
void registerTestOpaqueLoc();
[mlir][PDL] Add support for PDL bytecode and expose PDL support to OwningRewritePatternList PDL patterns are now supported via a new `PDLPatternModule` class. This class contains a ModuleOp with the pdl::PatternOp operations representing the patterns, as well as a collection of registered C++ functions for native constraints/creations/rewrites/etc. that may be invoked via the pdl patterns. Instances of this class are added to an OwningRewritePatternList in the same fashion as C++ RewritePatterns, i.e. via the `insert` method. The PDL bytecode is an in-memory representation of the PDL interpreter dialect that can be efficiently interpreted/executed. The representation of the bytecode boils down to a code array(for opcodes/memory locations/etc) and a memory buffer(for storing attributes/operations/values/any other data necessary). The bytecode operations are effectively a 1-1 mapping to the PDLInterp dialect operations, with a few exceptions in cases where the in-memory representation of the bytecode can be more efficient than the MLIR representation. For example, a generic `AreEqual` bytecode op can be used to represent AreEqualOp, CheckAttributeOp, and CheckTypeOp. The execution of the bytecode is split into two phases: matching and rewriting. When matching, all of the matched patterns are collected to avoid the overhead of re-running parts of the matcher. These matched patterns are then considered alongside the native C++ patterns, which rewrite immediately in-place via `RewritePattern::matchAndRewrite`, for the given root operation. When a PDL pattern is matched and has the highest benefit, it is passed back to the bytecode to execute its rewriter. Differential Revision: https://reviews.llvm.org/D89107
2020-12-02 06:30:18 +08:00
void registerTestPDLByteCodePass();
void registerTestPreparationPassWithAllowedMemrefResults();
void registerTestRecursiveTypesPass();
void registerTestSCFUtilsPass();
void registerTestSliceAnalysisPass();
void registerTestVectorLowerings();
} // namespace test
} // namespace mlir
namespace test {
void registerTestDialect(DialectRegistry &);
} // namespace test
#ifdef MLIR_INCLUDE_TESTS
void registerTestPasses() {
registerConvertToTargetEnvPass();
registerPassManagerTestPass();
registerPrintSpirvAvailabilityPass();
registerShapeFunctionTestPasses();
[mlir][SideEffects] Define a set of interfaces and traits for defining side effects This revision introduces the infrastructure for defining side-effects and attaching them to operations. This infrastructure allows for defining different types of side effects, that don't interact with each other, but use the same internal mechanisms. At the base of this is an interface that allows operations to specify the different effect instances that are exhibited by a specific operation instance. An effect instance is comprised of the following: * Effect: The specific effect being applied. For memory related effects this may be reading from memory, storing to memory, etc. * Value: A specific value, either operand/result/region argument, the effect pertains to. * Resource: This is a global entity that represents the domain within which the effect is being applied. MLIR serves many different abstractions, which cover many different domains. Simple effects are may have very different context, for example writing to an in-memory buffer vs a database. This revision defines uses this infrastructure to define a set of initial MemoryEffects. The are effects that generally correspond to memory of some kind; Allocate, Free, Read, Write. This set of memory effects will be used in follow revisions to generalize various parts of the compiler, and make others more powerful(e.g. DCE). This infrastructure was originally proposed here: https://groups.google.com/a/tensorflow.org/g/mlir/c/v2mNl4vFCUM Differential Revision: https://reviews.llvm.org/D74439
2020-03-07 05:53:16 +08:00
registerSideEffectTestPasses();
registerSliceAnalysisTestPass();
registerSymbolTestPasses();
registerTestAffineDataCopyPass();
registerTestAffineLoopUnswitchingPass();
registerTestAllReduceLoweringPass();
registerTestFunc();
registerTestGpuMemoryPromotionPass();
registerTestLoopPermutationPass();
registerTestMatchers();
registerTestOperationEqualPass();
registerTestPrintDefUsePass();
registerTestPrintNestingPass();
registerTestReducer();
registerTestSpirvEntryPointABIPass();
registerTestSpirvGLSLCanonicalizationPass();
registerTestSpirvModuleCombinerPass();
registerTestTraitsPass();
registerVectorizerTestPass();
registerTosaTestQuantUtilAPIPass();
mlir::test::registerConvertCallOpPass();
mlir::test::registerInliner();
mlir::test::registerMemRefBoundCheck();
mlir::test::registerPatternsTestPass();
mlir::test::registerSimpleParametricTilingPass();
mlir::test::registerTestAffineLoopParametricTilingPass();
mlir::test::registerTestAliasAnalysisPass();
[mlir] Refactor ElementsAttr into an AttrInterface This revision refactors ElementsAttr into an Attribute Interface. This enables a common interface with which to interact with element attributes, without needing to modify the builtin dialect. It also removes a majority (if not all?) of the need for the current OpaqueElementsAttr, which was originally intended as a way to opaquely represent data that was not representable by the other builtin constructs. The new ElementsAttr interface not only allows for users to natively represent their data in the way that best suits them, it also allows for efficient opaque access and iteration of the underlying data. Attributes using the ElementsAttr interface can directly expose support for interacting with the held elements using any C++ data type they claim to support. For example, DenseIntOrFpElementsAttr supports iteration using various native C++ integer/float data types, as well as APInt/APFloat, and more. ElementsAttr instances that refer to DenseIntOrFpElementsAttr can use all of these data types for iteration: ```c++ DenseIntOrFpElementsAttr intElementsAttr = ...; ElementsAttr attr = intElementsAttr; for (uint64_t value : attr.getValues<uint64_t>()) ...; for (APInt value : attr.getValues<APInt>()) ...; for (IntegerAttr value : attr.getValues<IntegerAttr>()) ...; ``` ElementsAttr also supports failable range/iterator access, allowing for selective code paths depending on data type support: ```c++ ElementsAttr attr = ...; if (auto range = attr.tryGetValues<uint64_t>()) { for (uint64_t value : *range) ...; } ``` Differential Revision: https://reviews.llvm.org/D109190
2021-09-21 09:40:45 +08:00
mlir::test::registerTestBuiltinAttributeInterfaces();
mlir::test::registerTestCallGraphPass();
mlir::test::registerTestConstantFold();
mlir::test::registerTestDiagnosticsPass();
#if MLIR_CUDA_CONVERSIONS_ENABLED
mlir::test::registerTestGpuSerializeToCubinPass();
#endif
#if MLIR_ROCM_CONVERSIONS_ENABLED
mlir::test::registerTestGpuSerializeToHsacoPass();
#endif
mlir::test::registerTestComprehensiveFunctionBufferize();
mlir::test::registerTestConvVectorization();
mlir::test::registerTestDecomposeCallGraphTypes();
mlir::test::registerTestDataLayoutQuery();
mlir::test::registerTestDominancePass();
mlir::test::registerTestDynamicPipelinePass();
mlir::test::registerTestExpandTanhPass();
mlir::test::registerTestComposeSubView();
mlir::test::registerTestGpuParallelLoopMappingPass();
mlir::test::registerTestIRVisitorsPass();
mlir::test::registerTestInterfaces();
mlir::test::registerTestLinalgCodegenStrategy();
mlir::test::registerTestLinalgControlFuseByExpansion();
mlir::test::registerTestLinalgDistribution();
mlir::test::registerTestLinalgElementwiseFusion();
mlir::test::registerTestPushExpandingReshape();
mlir::test::registerTestLinalgFusionTransforms();
mlir::test::registerTestLinalgTensorFusionTransforms();
mlir::test::registerTestLinalgTiledLoopFusionTransforms();
mlir::test::registerTestLinalgGreedyFusion();
mlir::test::registerTestLinalgHoisting();
mlir::test::registerTestLinalgTileAndFuseSequencePass();
mlir::test::registerTestLinalgTransforms();
mlir::test::registerTestLivenessPass();
mlir::test::registerTestLoopFusion();
mlir::test::registerTestLoopMappingPass();
mlir::test::registerTestLoopUnrollingPass();
mlir::test::registerTestMatchReductionPass();
mlir::test::registerTestMathAlgebraicSimplificationPass();
mlir::test::registerTestMathPolynomialApproximationPass();
mlir::test::registerTestMemRefDependenceCheck();
mlir::test::registerTestMemRefStrideCalculation();
mlir::test::registerTestNumberOfBlockExecutionsPass();
mlir::test::registerTestNumberOfOperationExecutionsPass();
mlir::test::registerTestOpaqueLoc();
mlir::test::registerTestPDLByteCodePass();
mlir::test::registerTestRecursiveTypesPass();
mlir::test::registerTestSCFUtilsPass();
mlir::test::registerTestSliceAnalysisPass();
mlir::test::registerTestVectorLowerings();
}
#endif
int main(int argc, char **argv) {
registerAllPasses();
#ifdef MLIR_INCLUDE_TESTS
registerTestPasses();
#endif
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 &registry) 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 registry;
registerAllDialects(registry);
#ifdef MLIR_INCLUDE_TESTS
::test::registerTestDialect(registry);
#endif
return mlir::asMainReturnCode(
mlir::MlirOptMain(argc, argv, "MLIR modular optimizer driver\n", registry,
/*preloadDialectsInContext=*/false));
}