blob: 060f46241d8b58db727163eb08a7c6f7d905300b [file] [log] [blame]
//===-- Passes.td - Linalg pass definition file ------------*- tablegen -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_DIALECT_LINALG_PASSES
#define MLIR_DIALECT_LINALG_PASSES
include "mlir/Pass/PassBase.td"
def ConvertElementwiseToLinalg : FunctionPass<"convert-elementwise-to-linalg"> {
let summary = "Convert ElementwiseMappable ops to linalg";
let description = [{
Convert ops with the `ElementwiseMappable` trait to linalg parallel loops.
This pass only converts ops that operate on ranked tensors.
}];
let constructor = "mlir::createConvertElementwiseToLinalgPass()";
let dependentDialects = ["linalg::LinalgDialect", "memref::MemRefDialect"];
}
def LinalgComprehensiveModuleBufferize :
Pass<"linalg-comprehensive-module-bufferize", "ModuleOp"> {
let summary = "Bufferize (tensor into memref) for a Module.";
let description = [{
This pass implements a cross-dialect bufferization approach and performs an
analysis to determine which op operands and results may be bufferized in the
same buffers. The analysis is performed on topologically sorted CallOp and
FuncOp within a module. It provides analyses and bufferization across
function boundaries. Within a function boundary, the analysis is performed
on SSA use-def chains starting from function operands that are annotated
with the 'inplaceable' attribute.
}];
let options = [
Option<"testAnalysisOnly", "test-analysis-only", "bool",
/*default=*/"false",
"Only runs inplaceability analysis (for testing purposes only)">,
Option<"allowReturnMemref", "allow-return-memref", "bool",
/*default=*/"false",
"Allows the return of memrefs (for testing purposes only)">,
Option<"useAlloca", "use-alloca", "bool",
/*default=*/"false",
"Use stack allocations for memrefs (for testing purposes only)">,
Option<"analysisFuzzerSeed", "analysis-fuzzer-seed", "unsigned",
/*default=*/"0",
"Analyze ops in random order with a given seed (fuzzer)">
];
let constructor = "mlir::createLinalgComprehensiveModuleBufferizePass()";
}
def LinalgFoldUnitExtentDims : FunctionPass<"linalg-fold-unit-extent-dims"> {
let summary = "Remove unit-extent dimension in Linalg ops on tensors";
let constructor = "mlir::createLinalgFoldUnitExtentDimsPass()";
let options = [
Option<"foldOneTripLoopsOnly", "fold-one-trip-loops-only", "bool",
/*default=*/"false",
"Only folds the one-trip loops from Linalg ops on tensors "
"(for testing purposes only)">
];
let dependentDialects = [
"linalg::LinalgDialect", "AffineDialect", "memref::MemRefDialect"
];
}
def LinalgElementwiseOpFusion : Pass<"linalg-fuse-elementwise-ops"> {
let summary = "Fuse elementwise operations on tensors";
let constructor = "mlir::createLinalgElementwiseOpFusionPass()";
let options = [
Option<"allowFoldingUnitDimReshapes", "allow-folding-unit-dim-reshapes",
"bool", /*default=*/"false",
"Allow fusing linalg.tensor_reshape ops that performs unit "
"dimension collapsing">
];
let dependentDialects = [
"AffineDialect", "linalg::LinalgDialect", "memref::MemRefDialect"
];
}
def LinalgFoldReshapeOpsByLinearization :
Pass<"linalg-fold-reshape-ops-by-linearization"> {
let summary = "Fold TensorReshapeOps with generic/indexed generic ops by "
"linearization";
let constructor = "mlir::createFoldReshapeOpsByLinearizationPass()";
let options = [
Option<"allowFoldingUnitDimReshapes", "allow-folding-unit-dim-reshapes",
"bool", /*default=*/"false",
"Allow fusing linalg.tensor_reshape ops that performs unit "
"dimension collapsing">
];
let dependentDialects = ["AffineDialect", "memref::MemRefDialect"];
}
def LinalgLowerTiledLoopsToSCF
: FunctionPass<"convert-linalg-tiled-loops-to-scf"> {
let summary = "Lower linalg tiled loops to SCF loops and parallel loops";
let constructor = "mlir::createConvertLinalgTiledLoopsToSCFPass()";
let dependentDialects = [
"linalg::LinalgDialect",
"scf::SCFDialect",
"AffineDialect"
];
}
def LinalgInlineScalarOperands : FunctionPass<"linalg-inline-scalar-operands"> {
let summary = "Inline scalar operands into linalg generic ops";
let constructor = "mlir::createLinalgInlineScalarOperandsPass()";
let dependentDialects = [
"linalg::LinalgDialect"
];
}
def LinalgLowerToAffineLoops : FunctionPass<"convert-linalg-to-affine-loops"> {
let summary = "Lower the operations from the linalg dialect into affine "
"loops";
let constructor = "mlir::createConvertLinalgToAffineLoopsPass()";
let dependentDialects = [
"AffineDialect", "linalg::LinalgDialect", "memref::MemRefDialect"];
}
def LinalgLowerToLoops : FunctionPass<"convert-linalg-to-loops"> {
let summary = "Lower the operations from the linalg dialect into loops";
let constructor = "mlir::createConvertLinalgToLoopsPass()";
let dependentDialects = [
"linalg::LinalgDialect",
"scf::SCFDialect",
"AffineDialect"
];
}
def LinalgLowerToParallelLoops
: FunctionPass<"convert-linalg-to-parallel-loops"> {
let summary = "Lower the operations from the linalg dialect into parallel "
"loops";
let constructor = "mlir::createConvertLinalgToParallelLoopsPass()";
let dependentDialects = [
"AffineDialect",
"linalg::LinalgDialect",
"memref::MemRefDialect",
"scf::SCFDialect"
];
}
def LinalgBufferize : Pass<"linalg-bufferize", "FuncOp"> {
let summary = "Bufferize the linalg dialect";
let constructor = "mlir::createLinalgBufferizePass()";
let dependentDialects = [
"AffineDialect",
"bufferization::BufferizationDialect",
"linalg::LinalgDialect",
"memref::MemRefDialect",
];
}
def LinalgPromotion : FunctionPass<"linalg-promote-subviews"> {
let summary = "Promote subview ops to local buffers";
let constructor = "mlir::createLinalgPromotionPass()";
let options = [
Option<"dynamicBuffers", "test-promote-dynamic", "bool",
/*default=*/"false", "Test generation of dynamic promoted buffers">,
Option<"useAlloca", "test-use-alloca", "bool",
/*default=*/"false", "Test generation of alloca'ed buffers.">
];
let dependentDialects = ["linalg::LinalgDialect"];
}
def LinalgTiling : FunctionPass<"linalg-tile"> {
let summary = "Tile operations in the linalg dialect";
let constructor = "mlir::createLinalgTilingPass()";
let dependentDialects = [
"AffineDialect",
"linalg::LinalgDialect",
"memref::MemRefDialect",
"scf::SCFDialect"
];
let options = [
ListOption<"tileSizes", "tile-sizes", "int64_t", "Tile sizes",
"llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated">,
Option<"loopType", "loop-type", "std::string", /*default=*/"\"for\"",
"Specify the type of loops to generate: for, parallel or "
"tiled_loop">,
ListOption<"distributionTypes", "distribution-types", "std::string",
"DistributionTypes (if loop-type=tiled_loop)",
"llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated">
];
}
def LinalgGeneralization : FunctionPass<"linalg-generalize-named-ops"> {
let summary = "Convert named ops into generic ops";
let constructor = "mlir::createLinalgGeneralizationPass()";
let dependentDialects = ["linalg::LinalgDialect"];
}
def LinalgDetensorize : FunctionPass<"linalg-detensorize"> {
let summary = "Detensorize linalg ops";
let constructor = "mlir::createLinalgDetensorizePass()";
let dependentDialects = [];
let description = [{
Detensoring is the process through which a tensor value is convereted to one
or potentially more primitive value(s). During this process, operations with
such detensored operands are also converted to an equivalent form that works
on primitives.
The detensoring process is driven by linalg-on-tensor ops. In particular, a
linalg-on-tensor op is checked to see whether *all* its operands can be
detensored. If so, those operands are converted to their primitive
counterparts and the linalg op is replaced by an equivalent op that takes
those new primitive values as operands. Therefore, detensoring an op can be
divided into 2 main logical phases:
1. Detect/match an op that can be detensored.
2. Detensor the operands of the op and replace it with a primitive
equivalent.
In addition to detensoring individual ops, this pass detensors internal
control flow inside a function. All blocks except for the entry block are
detensored by converting their arguments whenever possible.
}];
}
def LinalgStrategyTileAndFusePass
: FunctionPass<"linalg-strategy-tile-and-fuse-pass"> {
let summary = "Configurable pass to apply pattern-based tiling and fusion.";
let constructor = "mlir::createLinalgStrategyTileAndFusePass()";
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
Option<"anchorOpName", "anchor-op", "std::string", /*default=*/"",
"Which linalg op within the func is the anchor to latch on.">,
];
}
def LinalgStrategyTilePass
: FunctionPass<"linalg-strategy-tile-pass"> {
let summary = "Configurable pass to apply pattern-based linalg tiling.";
let constructor = "mlir::createLinalgStrategyTilePass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
Option<"anchorOpName", "anchor-op", "std::string", /*default=*/"",
"Which linalg op within the func is the anchor to latch on.">,
];
}
def LinalgStrategyPadPass
: FunctionPass<"linalg-strategy-pad-pass"> {
let summary = "Configurable pass to apply padding and hoisting.";
let constructor = "mlir::createLinalgStrategyPadPass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
Option<"anchorOpName", "anchor-op", "std::string", /*default=*/"",
"Which linalg op within the func is the anchor to latch on.">,
];
}
def LinalgStrategyPromotePass
: FunctionPass<"linalg-strategy-promote-pass"> {
let summary = "Configurable pass to apply pattern-based linalg promotion.";
let constructor = "mlir::createLinalgStrategyPromotePass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
Option<"anchorOpName", "anchor-op", "std::string", /*default=*/"",
"Which linalg op within the func is the anchor to latch on.">,
];
}
def LinalgStrategyGeneralizePass
: FunctionPass<"linalg-strategy-generalize-pass"> {
let summary = "Configurable pass to apply pattern-based generalization.";
let constructor = "mlir::createLinalgStrategyGeneralizePass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
Option<"anchorOpName", "anchor-op", "std::string", /*default=*/"",
"Which linalg op within the func is the anchor to latch on.">,
];
}
// TODO: if/when we need finer control add an anchorOp option.
def LinalgStrategyDecomposePass
: FunctionPass<"linalg-strategy-decompose-pass"> {
let summary = "Configurable pass to apply pattern-based generalization.";
let constructor = "mlir::createLinalgStrategyDecomposePass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
];
}
def LinalgStrategyInterchangePass
: FunctionPass<"linalg-strategy-interchange-pass"> {
let summary = "Configurable pass to apply pattern-based iterator interchange.";
let constructor = "mlir::createLinalgStrategyInterchangePass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
];
}
def LinalgStrategyVectorizePass
: FunctionPass<"linalg-strategy-vectorize-pass"> {
let summary = "Configurable pass to apply pattern-based linalg vectorization.";
let constructor = "mlir::createLinalgStrategyVectorizePass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
Option<"anchorOpName", "anchor-op", "std::string", /*default=*/"",
"Which linalg op within the func is the anchor to latch on.">,
Option<"vectorizePadding", "vectorize-padding", "bool", "false",
"Enable vectorization of padding ops.">,
];
}
def LinalgStrategyEnablePass
: FunctionPass<"linalg-strategy-enable-pass"> {
let summary = "Configurable pass to enable the application of other "
"pattern-based linalg passes.";
let constructor = "mlir::createLinalgStrategyEnablePass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
];
}
def LinalgStrategyLowerVectorsPass
: FunctionPass<"linalg-strategy-lower-vectors-pass"> {
let summary = "Configurable pass to lower vector operations.";
let constructor = "mlir::createLinalgStrategyLowerVectorsPass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
];
}
def LinalgStrategyRemoveMarkersPass
: FunctionPass<"linalg-strategy-remove-markers-pass"> {
let summary = "Cleanup pass that drops markers.";
let constructor = "mlir::createLinalgStrategyRemoveMarkersPass()";
let dependentDialects = ["linalg::LinalgDialect"];
let options = [
Option<"anchorFuncName", "anchor-func", "std::string", /*default=*/"",
"Which func op is the anchor to latch on.">,
];
}
#endif // MLIR_DIALECT_LINALG_PASSES