Files
gps/tools/local/circt/include/mlir/Conversion/Passes.td
T
2026-07-12 11:01:51 +03:00

1749 lines
72 KiB
TableGen

//===-- Passes.td - Conversion 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_CONVERSION_PASSES
#define MLIR_CONVERSION_PASSES
include "mlir/Pass/PassBase.td"
include "mlir/Dialect/Vector/Transforms/VectorTransformsBase.td"
//===----------------------------------------------------------------------===//
// ToEmitC
//===----------------------------------------------------------------------===//
def ConvertToEmitC : Pass<"convert-to-emitc"> {
let summary = "Convert to EmitC dialect via dialect interfaces";
let description = [{
This is a generic pass to convert to the EmitC dialect, it uses the
`ConvertToEmitCPatternInterface` dialect interface to delegate to dialects
the injection of conversion patterns.
}];
let options = [
ListOption<"filterDialects", "filter-dialects", "std::string",
"Test conversion patterns of only the specified dialects">,
Option<"lowerToCpp", "lower-to-cpp", "bool", "",
"Target C++ (true) instead of C (false)">,
];
}
//===----------------------------------------------------------------------===//
// ToLLVM
//===----------------------------------------------------------------------===//
def ConvertToLLVMPass : Pass<"convert-to-llvm"> {
let summary = "Convert to LLVM via dialect interfaces found in the input IR";
let description = [{
This is a generic pass to convert to LLVM, it uses the
`ConvertToLLVMPatternInterface` dialect interface to delegate to dialects
the injection of conversion patterns.
If `dynamic` is set to `true`, the pass will look for
`ConvertToLLVMAttrInterface` attributes and use them to further configure
the conversion process. This option also uses the `DataLayoutAnalysis`
analysis to configure the type converter. Enabling this option incurs in
extra overhead.
}];
let options = [
ListOption<"filterDialects", "filter-dialects", "std::string",
"Test conversion patterns of only the specified dialects">,
Option<"useDynamic", "dynamic", "bool", "false",
"Use op conversion attributes to configure the conversion">,
Option<"allowPatternRollback", "allow-pattern-rollback", "bool", "true",
"Experimental performance flag to disallow pattern rollback">
];
}
//===----------------------------------------------------------------------===//
// LowerAffine
//===----------------------------------------------------------------------===//
def LowerAffinePass : Pass<"lower-affine"> {
let summary = "Lower Affine operations to a combination of Arith and SCF "
"operations";
let description = [{
Convert operations from the affine dialect into operations from the SCF and
standard dialects.
`affine.for` operations are converted to `scf.for` operations that are free
of certain structural restrictions (on their bounds and step). `affine.if`
is similarly converted to the `scf.if` operation. `affine.apply` operations
are converted into sequences of primitive arithmetic operations from the
arith dialect that have the same effect, using operands of the `index`
type. Consequently, named maps and sets thare are no longer in use may be
removed from the module.
For example, `%r = affine.apply affine_map<(d0, d1)[s0] -> (d0 + 2*d1 +
s0)>(%d0, %d1)[%s0]`
can be converted into:
```mlir
%d0 = <...>
%d1 = <...>
%s0 = <...>
%0 = arith.constant 2 : index
%1 = arith.muli %0, %d1
%2 = arith.addi %d0, %1
%r = arith.addi %2, %s0
```
#### Input invariant
- no `Tensor` types;
These restrictions may be lifted in the future.
#### Output IR
Functions with `affine.for` and `affine.if` operations eliminated. These
functions may contain operations from the Standard dialect in addition to
those already present before the pass.
#### Invariants
- Functions without a body are not modified.
- The semantics of the other functions is preserved.
- Individual operations other than those mentioned above are not modified
if they do not depend on the loop iterator value or on the result of
`affine.apply`.
}];
let dependentDialects = ["arith::ArithDialect", "memref::MemRefDialect",
"scf::SCFDialect", "vector::VectorDialect"];
}
//===----------------------------------------------------------------------===//
// AMDGPUToROCDL
//===----------------------------------------------------------------------===//
def ConvertAMDGPUToROCDLPass : Pass<"convert-amdgpu-to-rocdl"> {
let summary = "Convert AMDGPU dialect to ROCDL dialect";
let description = [{
This pass converts supported AMDGPU ops to ROCDL dialect intrinsics.
}];
let dependentDialects = [
"LLVM::LLVMDialect",
"ROCDL::ROCDLDialect",
];
let options = [Option<"chipset", "chipset", "std::string",
/*default=*/"\"gfx000\"",
"Chipset that these operations will run on">];
}
//===----------------------------------------------------------------------===//
// ArithToAMDGPU
//===----------------------------------------------------------------------===//
def ArithToAMDGPUConversionPass : Pass<"convert-arith-to-amdgpu"> {
let summary = "Convert Arith operations to AMDGPU-specific implementations";
let description = [{
Convert `arith` operations (currently extf and truncf on 8-bit floats)
to operations in the `amdgpu` dialect. This pass is done in two steps
in order to avoid running a notional arith-to-rocdl and arith-to-llvm
simultaniously.
}];
let dependentDialects = ["amdgpu::AMDGPUDialect", "vector::VectorDialect"];
let options = [
Option<"chipset", "chipset", "std::string",
/*default=*/"\"gfx000\"",
"Chipset that these operations will run on">,
Option<"saturateFP8Truncf", "saturate-fp8-truncf", "bool",
/*default=*/"false",
"Use saturating truncation for 8-bit float types">,
Option<"allowPackedF16Rtz", "allow-packed-f16-round-to-zero", "bool",
/*default=*/"false",
"Whether we should allow f32->f16 packed round-to-zero conversion">,
];
}
//===----------------------------------------------------------------------===//
// ArithToEmitC
//===----------------------------------------------------------------------===//
def ConvertArithToEmitC : Pass<"convert-arith-to-emitc"> {
let summary = "Convert Arith dialect to EmitC dialect";
let dependentDialects = ["emitc::EmitCDialect"];
}
//===----------------------------------------------------------------------===//
// ArithToLLVM
//===----------------------------------------------------------------------===//
def ArithToLLVMConversionPass : Pass<"convert-arith-to-llvm"> {
let summary = "Convert Arith dialect to LLVM dialect";
let description = [{
This pass converts supported Arith ops to LLVM dialect instructions.
}];
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
"Bitwidth of the index type, 0 to use size of machine word">,
];
}
//===----------------------------------------------------------------------===//
// ArithToAPFloat
//===----------------------------------------------------------------------===//
def ArithToAPFloatConversionPass
: Pass<"convert-arith-to-apfloat", "ModuleOp"> {
let summary = "Convert Arith ops to APFloat runtime library calls";
let description = [{
This pass converts supported Arith ops to APFloat-based runtime library
calls (APFloatWrappers.cpp). APFloat is a software implementation of
floating-point arithmetic operations.
}];
let dependentDialects = ["arith::ArithDialect", "func::FuncDialect",
"vector::VectorDialect"];
}
//===----------------------------------------------------------------------===//
// ArithToSPIRV
//===----------------------------------------------------------------------===//
def ConvertArithToSPIRVPass : Pass<"convert-arith-to-spirv"> {
let summary = "Convert Arith dialect to SPIR-V dialect";
let dependentDialects = ["spirv::SPIRVDialect"];
let options = [
Option<"emulateLT32BitScalarTypes", "emulate-lt-32-bit-scalar-types",
"bool", /*default=*/"true",
"Emulate narrower scalar types with 32-bit ones if not supported by "
"the target">,
Option<"emulateUnsupportedFloatTypes", "emulate-unsupported-float-types",
"bool", /*default=*/"true",
"Emulate unsupported float types by representing them with integer "
"types of same bit width">
];
}
//===----------------------------------------------------------------------===//
// ArithToArmSME
//===----------------------------------------------------------------------===//
def ArithToArmSMEConversionPass : Pass<"convert-arith-to-arm-sme"> {
let summary = "Convert Arith dialect to ArmSME dialect";
let dependentDialects = ["arm_sme::ArmSMEDialect"];
}
//===----------------------------------------------------------------------===//
// ArmNeon2dToIntr
//===----------------------------------------------------------------------===//
def ConvertArmNeon2dToIntrPass : Pass<"arm-neon-2d-to-intr"> {
let summary = "Convert Arm NEON structured ops to intrinsics";
let description = [{
Creates a pass to lower Arm NEON 2D ops to intrinsics, i.e.
equivalent ops operating on flattened 1D vectors and mapping more
directly to the corresponding Arm NEON instruction.
}];
let dependentDialects = ["arm_neon::ArmNeonDialect", "vector::VectorDialect"];
}
//===----------------------------------------------------------------------===//
// AsyncToLLVM
//===----------------------------------------------------------------------===//
def ConvertAsyncToLLVMPass : Pass<"convert-async-to-llvm", "ModuleOp"> {
let summary = "Convert the operations from the async dialect into the LLVM "
"dialect";
let description = [{
Convert `async.execute` operations to LLVM coroutines and use async runtime
API to execute them.
}];
let dependentDialects = [
"arith::ArithDialect",
"async::AsyncDialect",
"LLVM::LLVMDialect",
"func::FuncDialect",
];
}
//===----------------------------------------------------------------------===//
// BufferizationToMemRef
//===----------------------------------------------------------------------===//
def ConvertBufferizationToMemRefPass : Pass<"convert-bufferization-to-memref"> {
let summary = "Convert operations from the Bufferization dialect to the "
"MemRef dialect";
let description = [{
This pass converts bufferization operations into memref operations.
In the current state, this pass only transforms a `bufferization.clone`
operation into `memref.alloc` and `memref.copy` operations and
`bufferization.dealloc` operations (the same way as the
`-bufferization-lower-deallocations` pass). The conversion of `clone`
operations is needed, since some clone operations could remain after
applying several transformation processes. Currently, only `canonicalize`
transforms clone operations or even eliminates them. This can lead to errors
if any clone op survived after all conversion passes (starting from the
bufferization dialect) are performed.
See:
https://llvm.discourse.group/t/bufferization-error-related-to-memref-clone/4665
To avoid these errors, this pass can be performed as a last clean-up pass to
transform remaining operations and to proceed in other dialects (memref
e.g.).
Note that this pass only transforms the operation without any further
analyses. This pass does not consider any memory analysis or optimization
and hence does not resolve any memory leaks.
}];
let dependentDialects = [
"arith::ArithDialect", "memref::MemRefDialect", "scf::SCFDialect",
"func::FuncDialect"
];
}
//===----------------------------------------------------------------------===//
// ComplexToLLVM
//===----------------------------------------------------------------------===//
def ConvertComplexToLLVMPass : Pass<"convert-complex-to-llvm"> {
let summary = "Convert Complex dialect to LLVM dialect";
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"complexRange", "complex-range", "::mlir::complex::ComplexRangeFlags",
/*default=*/"::mlir::complex::ComplexRangeFlags::basic",
"Control the intermediate calculation of complex number division",
[{::llvm::cl::values(
clEnumValN(::mlir::complex::ComplexRangeFlags::improved, "improved", "improved"),
clEnumValN(::mlir::complex::ComplexRangeFlags::basic, "basic", "basic (default)"),
clEnumValN(::mlir::complex::ComplexRangeFlags::none, "none", "none")
)}]>,
];
}
//===----------------------------------------------------------------------===//
// ComplexToLibm
//===----------------------------------------------------------------------===//
def ConvertComplexToLibm : Pass<"convert-complex-to-libm", "ModuleOp"> {
let summary = "Convert Complex dialect to libm calls";
let description = [{
This pass converts supported Complex ops to libm calls.
}];
let dependentDialects = ["func::FuncDialect"];
}
//===----------------------------------------------------------------------===//
// ComplexToROCDLLibraryCalls
//===----------------------------------------------------------------------===//
def ConvertComplexToROCDLLibraryCalls : Pass<"convert-complex-to-rocdl-library-calls", "ModuleOp"> {
let summary = "Convert Complex dialect to ROCDL library calls";
let description = [{
This pass converts supported Complex ops to calls to the AMD device library.
}];
let dependentDialects = ["func::FuncDialect"];
}
//===----------------------------------------------------------------------===//
// ComplexToSPIRV
//===----------------------------------------------------------------------===//
def ConvertComplexToSPIRVPass : Pass<"convert-complex-to-spirv"> {
let summary = "Convert Complex dialect to SPIRV dialect";
let dependentDialects = ["spirv::SPIRVDialect"];
}
//===----------------------------------------------------------------------===//
// ComplexToStandard
//===----------------------------------------------------------------------===//
def ConvertComplexToStandardPass : Pass<"convert-complex-to-standard"> {
let summary = "Convert Complex dialect to standard dialect";
let dependentDialects = ["math::MathDialect"];
let options = [
Option<"complexRange", "complex-range", "::mlir::complex::ComplexRangeFlags",
/*default=*/"::mlir::complex::ComplexRangeFlags::improved",
"Control the intermediate calculation of complex number division",
[{::llvm::cl::values(
clEnumValN(::mlir::complex::ComplexRangeFlags::improved, "improved", "improved (default)"),
clEnumValN(::mlir::complex::ComplexRangeFlags::basic, "basic", "basic"),
clEnumValN(::mlir::complex::ComplexRangeFlags::none, "none", "none")
)}]>,
];
}
//===----------------------------------------------------------------------===//
// ControlFlowToLLVM
//===----------------------------------------------------------------------===//
def ConvertControlFlowToLLVMPass : Pass<"convert-cf-to-llvm", "ModuleOp"> {
let summary = "Convert ControlFlow operations to the LLVM dialect";
let description = [{
Convert ControlFlow operations into LLVM IR dialect operations.
If other operations are present and their results are required by the LLVM
IR dialect operations, the pass will fail. Any LLVM IR operations or types
already present in the IR will be kept as is.
}];
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
"Bitwidth of the index type, 0 to use size of machine word">
];
}
//===----------------------------------------------------------------------===//
// ControlFlowToSCF
//===----------------------------------------------------------------------===//
def LiftControlFlowToSCFPass : Pass<"lift-cf-to-scf"> {
let summary = "Lift ControlFlow dialect to SCF dialect";
let description = [{
Lifts ControlFlow operations to SCF dialect operations.
This pass is prefixed with "lift" instead of "convert" as it is not always
guaranteed to replace all ControlFlow ops.
If a region contains only a single kind of return-like operation, all
ControlFlow operations will be replaced successfully.
Otherwise a single ControlFlow switch branching to one block per return-like
operation kind remains.
This pass may need to create unreachable terminators in case of infinite
loops, which is only supported for 'func.func' for now. If you potentially
have infinite loops inside CFG regions not belonging to 'func.func',
consider using `transformCFGToSCF` function directly with corresponding
`CFGToSCFInterface::createUnreachableTerminator` implementation.
}];
let dependentDialects = ["scf::SCFDialect",
"arith::ArithDialect",
"ub::UBDialect",
// TODO: This is only necessary until we have a
// ub.unreachable op.
"func::FuncDialect"];
}
//===----------------------------------------------------------------------===//
// ControlFlowToSPIRV
//===----------------------------------------------------------------------===//
def ConvertControlFlowToSPIRVPass : Pass<"convert-cf-to-spirv"> {
let summary = "Convert ControlFlow dialect to SPIR-V dialect";
let dependentDialects = ["spirv::SPIRVDialect"];
let options = [
Option<"emulateLT32BitScalarTypes", "emulate-lt-32-bit-scalar-types",
"bool", /*default=*/"true",
"Emulate narrower scalar types with 32-bit ones if not supported by"
" the target">,
Option<"emulateUnsupportedFloatTypes", "emulate-unsupported-float-types",
"bool", /*default=*/"true",
"Emulate unsupported float types by representing them with integer "
"types of same bit width">
];
}
//===----------------------------------------------------------------------===//
// FuncToEmitC
//===----------------------------------------------------------------------===//
def ConvertFuncToEmitC : Pass<"convert-func-to-emitc", "ModuleOp"> {
let summary = "Convert Func dialect to EmitC dialect";
let dependentDialects = ["emitc::EmitCDialect"];
let options = [Option<
"lowerToCpp", "lower-to-cpp", "bool",
/*default=*/"true",
/*description=*/"Target C++ (true) instead of C (false)">];
}
//===----------------------------------------------------------------------===//
// FuncToLLVM
//===----------------------------------------------------------------------===//
def SetLLVMModuleDataLayoutPass : Pass<"set-llvm-module-datalayout", "ModuleOp"> {
let summary = "Attach a datalayout string as a module attribute";
let description = [{
Verify that the dataLayout string is a valid LLVM datalayout string and
attach it as an attribute `LLVMDialect::getDataLayoutAttrName()` to the
module, overriding the existing one.
}];
let options = [
Option<"dataLayout", "data-layout", "std::string",
/*default=*/"\"\"",
"String description (LLVM format) of the data layout that is "
"expected on the produced module">,
];
}
def ConvertFuncToLLVMPass : Pass<"convert-func-to-llvm", "ModuleOp"> {
let summary = "Convert from the Func dialect to the LLVM dialect";
let description = [{
Convert Func dialect operations into the LLVM IR dialect operations.
#### Input invariant
- no `tensor` types;
- all `vector` are one-dimensional;
- all blocks are reachable by following the successors of the first basic
block;
If other operations are present and their results are required by the LLVM
IR dialect operations, the pass will fail. Any LLVM IR operations or types
already present in the IR will be kept as is.
An LLVM datalayout string can be attached as an attribute to the module on
which the pass anchors. Such an attribute is attached by calling the
set-module-datalayout pass. If present, an llvm::DataLayout object is
created from this attribute and used in the conversion to LLVM.
#### Output IR
Functions converted to LLVM IR. Function arguments types are converted
one-to-one. Function results are converted one-to-one and, in case more than
1 value is returned, packed into an LLVM IR struct type. Function calls and
returns are updated accordingly. Block argument types are updated to use
LLVM IR types.
#### Function discardable attributes
Discardable attributes on `func.func` are lowered as follows.
- **LLVM `llvm.func` properties.** Each inherent attribute defined on
`llvm.func` (ODS properties such as `target_cpu`, `linkage`,
`vscale_range`, `passthrough`, and so on) must be attached to `func.func`
using the `llvm.` prefix (for example `llvm.target_cpu`,
`llvm.vscale_range`). The pass strips that prefix, validates the attribute
value the same way as for `llvm.func`, and fills the corresponding fields
on the generated `llvm.func`. Values that fail validation make conversion
fail.
- **Unprefixed legacy names.** A discardable attribute whose name equals
the bare ODS property name (without `llvm.`) is **not** forwarded: it is
dropped. Only the explicit `llvm.*` spelling is lowered into `llvm.func`
properties so that front ends cannot accidentally rely on ambiguous
short names.
- **Opaque pass-through.** Any other discardable attribute is copied onto
the `llvm.func` unchanged, so arbitrary metadata can survive the
conversion. That includes names that start with `llvm.` but are **not**
inherent `llvm.func` properties (for example dialect-specific markers): they
are not interpreted as properties and are forwarded as discardable
attributes on the result.
- **`func.varargs`.** This attribute is interpreted when converting the
function type (variadic LLVM signature). It is not an LLVM IR dialect
property and is handled separately from the `llvm.*` property mapping
above.
- **`llvm.readnone`.** If present, the pass also sets `memory_effects` on
the `llvm.func` to read-none semantics, in addition to any other attribute
handling.
}];
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"useBarePtrCallConv", "use-bare-ptr-memref-call-conv", "bool",
/*default=*/"false",
"Replace FuncOp's MemRef arguments with bare pointers to the MemRef "
"element types">,
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
"Bitwidth of the index type, 0 to use size of machine word">,
];
}
//===----------------------------------------------------------------------===//
// FuncToSPIRV
//===----------------------------------------------------------------------===//
def ConvertFuncToSPIRVPass : Pass<"convert-func-to-spirv"> {
let summary = "Convert Func dialect to SPIR-V dialect";
let dependentDialects = ["spirv::SPIRVDialect"];
let options = [
Option<"emulateLT32BitScalarTypes", "emulate-lt-32-bit-scalar-types",
"bool", /*default=*/"true",
"Emulate narrower scalar types with 32-bit ones if not supported by"
" the target">,
Option<"emulateUnsupportedFloatTypes", "emulate-unsupported-float-types",
"bool", /*default=*/"true",
"Emulate unsupported float types by representing them with integer "
"types of same bit width">
];
}
//===----------------------------------------------------------------------===//
// GPUCommon
//===----------------------------------------------------------------------===//
def GpuToLLVMConversionPass : Pass<"gpu-to-llvm", "ModuleOp"> {
let summary = "Convert GPU dialect to LLVM dialect with GPU runtime calls";
let description = [{
Creates a pass to convert a GPU operations into a sequence of GPU runtime
calls.
This pass does not generate code to call GPU runtime APIs directly but
instead uses a small wrapper library that exports a stable and conveniently
typed ABI on top of GPU runtimes such as CUDA or ROCm (HIP).
}];
let options = [
Option<"hostBarePtrCallConv", "use-bare-pointers-for-host", "bool",
/*default=*/"false",
"Use bare pointers to pass memref arguments to host functions. "
"All memrefs must have static shape.">,
Option<"kernelBarePtrCallConv", "use-bare-pointers-for-kernels", "bool",
/*default=*/"false",
"Use bare pointers to pass memref arguments to kernels. "
"The kernel must use the same setting for this option."
>,
Option<"kernelIntersperseSizeCallConv", "intersperse-sizes-for-kernels", "bool",
/*default=*/"false",
"Inserts a size_t argument following each memref argument, "
"containing the static size in bytes of the buffer. Incompatible "
"arguments are rejected. This is intended for use by the Vulkan "
"runtime with the kernel bare pointer calling convention, to enable "
"dynamic binding of buffers as arguments without static type info."
>
];
let dependentDialects = [
"LLVM::LLVMDialect",
"memref::MemRefDialect",
];
}
def LowerHostCodeToLLVMPass : Pass<"lower-host-to-llvm", "ModuleOp"> {
let summary = "Lowers the host module code and `gpu.launch_func` to LLVM";
let description = [{
Creates a pass to emulate `gpu.launch_func` call in LLVM dialect and lower
the host module code to LLVM.
This transformation creates a sequence of global variables that are later
linked to the variables in the kernel module, and a series of copies to/from
them to emulate the memory transfer from the host or to the device sides. It
also converts the remaining Arithmetic, Func, and MemRef dialects into LLVM
dialect, emitting C wrappers.
}];
let dependentDialects = ["LLVM::LLVMDialect"];
}
//===----------------------------------------------------------------------===//
// GPUToLLVMSPV
//===----------------------------------------------------------------------===//
def ConvertGpuOpsToLLVMSPVOps : Pass<"convert-gpu-to-llvm-spv", "gpu::GPUModuleOp"> {
let summary =
"Generate LLVM operations to be ingested by a SPIR-V backend for gpu operations";
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"use64bitIndex", "use-64bit-index",
"bool", /*default=*/"false",
"Use 64-bit integers to convert index types">,
];
}
//===----------------------------------------------------------------------===//
// GPUToNVVM
//===----------------------------------------------------------------------===//
def ConvertGpuOpsToNVVMOps : Pass<"convert-gpu-to-nvvm", "gpu::GPUModuleOp"> {
let summary = "Generate NVVM operations for gpu operations";
let dependentDialects = [
"cf::ControlFlowDialect",
"memref::MemRefDialect",
"NVVM::NVVMDialect",
];
let options = [
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/ "0",
"Bitwidth of the index type, 0 to use size of machine word">,
Option<"hasRedux", "has-redux", "bool", /*default=*/"false",
"Target gpu supports redux">,
Option<"useBarePtrCallConv", "use-bare-ptr-memref-call-conv", "bool",
/*default=*/"false",
"Replace memref arguments in GPU functions with bare pointers. "
"All memrefs must have static shape.">,
Option<"allowPatternRollback", "allow-pattern-rollback", "bool", "true",
"Experimental performance flag to disallow pattern rollback">,
ListOption<"allowedDialects", "allowed-dialects", "std::string",
"Run conversion patterns of only the specified dialects">,
];
}
//===----------------------------------------------------------------------===//
// GPUToROCDL
//===----------------------------------------------------------------------===//
def ConvertGpuOpsToROCDLOps : Pass<"convert-gpu-to-rocdl", "gpu::GPUModuleOp"> {
let summary = "Generate ROCDL operations for gpu operations";
let dependentDialects = [
"ROCDL::ROCDLDialect",
"amdgpu::AMDGPUDialect",
"cf::ControlFlowDialect",
"memref::MemRefDialect",
];
let options = [
Option<"chipset", "chipset", "std::string",
/*default=*/"\"gfx000\"",
"Chipset that these operations will run on">,
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/ "0",
"Bitwidth of the index type, 0 to use size of machine word">,
Option<"useBarePtrCallConv", "use-bare-ptr-memref-call-conv", "bool",
/*default=*/"false",
"Replace memref arguments in GPU functions with bare pointers."
"All memrefs must have static shape">,
Option<"runtime", "runtime", "::mlir::gpu::amd::Runtime",
"::mlir::gpu::amd::Runtime::Unknown",
"Runtime code will be run on (default is Unknown, can also use HIP "
"or OpenCL)",
[{::llvm::cl::values(
clEnumValN(::mlir::gpu::amd::Runtime::Unknown, "unknown",
"Unknown (default)"),
clEnumValN(::mlir::gpu::amd::Runtime::HIP, "HIP", "HIP"),
clEnumValN(::mlir::gpu::amd::Runtime::OpenCL, "OpenCL",
"OpenCL"))}]>,
ListOption<"allowedDialects", "allowed-dialects", "std::string",
"Run conversion patterns of only the specified dialects">,
];
}
//===----------------------------------------------------------------------===//
// GPUToSPIRV
//===----------------------------------------------------------------------===//
def ConvertGPUToSPIRV : Pass<"convert-gpu-to-spirv", "ModuleOp"> {
let summary = "Convert GPU dialect to SPIR-V dialect";
let description = [{
This pass converts supported GPU device ops to SPIR-V ops. It does not
handle GPU host ops.
A `gpu.func` op can have parameters to pass in resources. But in SPIR-V
entry functions cannot take parameters; they use descriptors to access
resources. By default, parameters to a `gpu.func` op will be converted to
global variables. These global variables will be assigned sequential binding
numbers following their order in the original `gpu.func` op, starting from
0, in set 0. One can attach `spirv.interface_var_abi` to those parameters
to control the set and binding if wanted.
}];
let constructor = "mlir::createConvertGPUToSPIRVPass()";
let dependentDialects = [
"func::FuncDialect",
"spirv::SPIRVDialect",
];
let options = [
Option<"use64bitIndex", "use-64bit-index",
"bool", /*default=*/"false",
"Use 64-bit integers to convert index types">,
];
}
//===----------------------------------------------------------------------===//
// ConvertIndexToLLVMPass
//===----------------------------------------------------------------------===//
def ConvertIndexToLLVMPass : Pass<"convert-index-to-llvm"> {
let summary = "Lower the `index` dialect to the `llvm` dialect.";
let description = [{
This pass lowers Index dialect operations to LLVM dialect operations.
Operation conversions are 1-to-1 except for the exotic divides: `ceildivs`,
`ceildivu`, and `floordivs`, which expand to series of LLVM operations.
Importantly, the index bitwidth should be correctly set to the target
pointer width via `index-bitwidth`.
}];
let dependentDialects = ["::mlir::LLVM::LLVMDialect"];
let options = [
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
"Bitwidth of the index type, 0 to use size of machine word">,
];
}
//===----------------------------------------------------------------------===//
// ConvertIndexToSPIRVPass
//===----------------------------------------------------------------------===//
def ConvertIndexToSPIRVPass : Pass<"convert-index-to-spirv"> {
let summary = "Lower the `index` dialect to the `spirv` dialect.";
let description = [{
This pass lowers Index dialect operations to SPIR-V dialect operations.
Operation conversions are 1-to-1 except for the exotic divides: `ceildivs`,
`ceildivu`, and `floordivs`. The index bitwidth will be 32 or 64 as
specified by use-64bit-index.
}];
let dependentDialects = ["::mlir::spirv::SPIRVDialect"];
let options = [
Option<"use64bitIndex", "use-64bit-index",
"bool", /*default=*/"false",
"Use 64-bit integers to convert index types">
];
}
//===----------------------------------------------------------------------===//
// LinalgToStandard
//===----------------------------------------------------------------------===//
def ConvertLinalgToStandardPass : Pass<"convert-linalg-to-std", "ModuleOp"> {
let summary = "Convert the operations from the linalg dialect into the "
"Standard dialect";
let dependentDialects = ["func::FuncDialect", "memref::MemRefDialect"];
}
//===----------------------------------------------------------------------===//
// MathToLibm
//===----------------------------------------------------------------------===//
def ConvertMathToLibmPass : Pass<"convert-math-to-libm", "ModuleOp"> {
let summary = "Convert Math dialect to libm calls";
let description = [{
This pass converts supported Math ops to libm calls.
}];
let dependentDialects = [
"arith::ArithDialect",
"func::FuncDialect",
"vector::VectorDialect",
];
}
//===----------------------------------------------------------------------===//
// MathToAPFloat
//===----------------------------------------------------------------------===//
def MathToAPFloatConversionPass
: Pass<"convert-math-to-apfloat", "ModuleOp"> {
let summary = "Convert Math ops to APFloat runtime library calls";
let description = [{
This pass converts supported Math ops to APFloat-based runtime library
calls (APFloatWrappers.cpp). APFloat is a software implementation of
floating-point mathmetic operations.
}];
let dependentDialects = ["math::MathDialect", "func::FuncDialect"];
}
//===----------------------------------------------------------------------===//
// MathToLLVM
//===----------------------------------------------------------------------===//
def ConvertMathToLLVMPass : Pass<"convert-math-to-llvm"> {
let summary = "Convert Math dialect to LLVM dialect";
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"approximateLog1p", "approximate-log1p", "bool", "true",
"Enable approximation of Log1p.">
];
}
//===----------------------------------------------------------------------===//
// MathToLibm
//===----------------------------------------------------------------------===//
def ConvertMathToROCDL : Pass<"convert-math-to-rocdl", "ModuleOp"> {
let summary = "Convert Math dialect to ROCDL library calls";
let description = [{
This pass converts supported Math ops to ROCDL library calls.
The chipset option specifies the target AMDGPU architecture. If the chipset
is empty, none of the chipset-dependent patterns are added, and the pass
will not attempt to parse the chipset.
}];
let dependentDialects = [
"arith::ArithDialect",
"func::FuncDialect",
"ROCDL::ROCDLDialect",
"vector::VectorDialect",
];
let options = [Option<"chipset", "chipset", "std::string",
/*default=*/"\"\"",
"Chipset that these operations will run on">];
}
//===----------------------------------------------------------------------===//
// MathToNVVM
//===----------------------------------------------------------------------===//
def ConvertMathToNVVM : Pass<"convert-math-to-nvvm", "ModuleOp"> {
let summary = "Convert Math dialect to CUDA libdevice calls";
let description = [{
This pass converts supported Math ops to CUDA libdevice calls.
}];
let dependentDialects = ["arith::ArithDialect", "func::FuncDialect",
"NVVM::NVVMDialect", "vector::VectorDialect",
];
}
//===----------------------------------------------------------------------===//
// MathToSPIRV
//===----------------------------------------------------------------------===//
def ConvertMathToSPIRVPass : Pass<"convert-math-to-spirv"> {
let summary = "Convert Math dialect to SPIR-V dialect";
let dependentDialects = ["spirv::SPIRVDialect"];
}
//===----------------------------------------------------------------------===//
// MathToXeVM
//===----------------------------------------------------------------------===//
def ConvertMathToXeVM : Pass<"convert-math-to-xevm"> {
let summary =
"Convert (fast) math operations to native XeVM/SPIRV equivalents";
let description = [{
This pass converts supported math ops marked with the `afn` fastmath flag
to function calls for OpenCL `native_` math intrinsics: These intrinsics
are typically mapped directly to native device instructions, often resulting
in better performance. However, the precision/error of these intrinsics
are implementation-defined, and thus math ops are only converted when they
have the `afn` fastmath flag enabled.
}];
let options = [Option<
"convertArith", "convert-arith", "bool", /*default=*/"true",
"Convert supported Arith ops (e.g. arith.divf) as well.">];
let dependentDialects = [
"arith::ArithDialect",
"xevm::XeVMDialect",
"LLVM::LLVMDialect",
];
}
//===----------------------------------------------------------------------===//
// MathToEmitC
//===----------------------------------------------------------------------===//
def ConvertMathToEmitC : Pass<"convert-math-to-emitc"> {
let summary = "Convert some Math operations to EmitC call_opaque operations";
let description = [{
This pass converts supported Math ops to `call_opaque` ops targeting libc/libm
functions. Unlike convert-math-to-funcs pass, converting to `call_opaque` ops
allows to overload the same function with different argument types.
}];
let dependentDialects = ["emitc::EmitCDialect"];
let options = [
Option<"languageTarget", "language-target", "::mlir::emitc::LanguageTarget",
/*default=*/"::mlir::emitc::LanguageTarget::c99", "Select the language standard target for callees (c99 or cpp11).",
[{::llvm::cl::values(
clEnumValN(::mlir::emitc::LanguageTarget::c99, "c99", "c99"),
clEnumValN(::mlir::emitc::LanguageTarget::cpp11, "cpp11", "cpp11")
)}]>
];
}
//===----------------------------------------------------------------------===//
// MathToFuncs
//===----------------------------------------------------------------------===//
def ConvertMathToFuncs : Pass<"convert-math-to-funcs", "ModuleOp"> {
let summary = "Convert Math operations to calls of outlined implementations.";
let description = [{
This pass converts supported Math ops to calls of compiler generated
functions implementing these operations in software.
The LLVM dialect is used for LinkonceODR linkage of the generated functions.
}];
let dependentDialects = [
"arith::ArithDialect",
"cf::ControlFlowDialect",
"func::FuncDialect",
"scf::SCFDialect",
"vector::VectorDialect",
"LLVM::LLVMDialect",
];
let options = [
Option<"minWidthOfFPowIExponent", "min-width-of-fpowi-exponent", "unsigned",
/*default=*/"1",
"Convert FPowI only if the width of its exponent's integer type "
"is greater than or equal to this value">,
// Most backend targets support a native ctlz operation, so by default
// ctrlz conversion is disabled.
Option<"convertCtlz", "convert-ctlz", "bool", /*default=*/"false",
"Convert math.ctlz to a software implementation. Enable "
"for targets that do not natively support ctlz.">,
];
}
//===----------------------------------------------------------------------===//
// MemRefToEmitC
//===----------------------------------------------------------------------===//
def ConvertMemRefToEmitC : Pass<"convert-memref-to-emitc", "ModuleOp"> {
let summary = "Convert MemRef dialect to EmitC dialect";
let dependentDialects = ["emitc::EmitCDialect"];
let options = [Option<
"lowerToCpp", "lower-to-cpp", "bool",
/*default=*/"false",
/*description=*/"Target C++ (true) instead of C (false)">];
}
//===----------------------------------------------------------------------===//
// MemRefToLLVM
//===----------------------------------------------------------------------===//
def FinalizeMemRefToLLVMConversionPass :
Pass<"finalize-memref-to-llvm", "ModuleOp"> {
let summary = "Finalize MemRef dialect to LLVM dialect conversion";
let description = [{
Finalize the conversion of the operations from the MemRef
dialect to the LLVM dialect.
This conversion will not convert some complex MemRef
operations. Make sure to run `expand-strided-metadata`
beforehand for these.
}];
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"useAlignedAlloc", "use-aligned-alloc", "bool", /*default=*/"false",
"Use aligned_alloc in place of malloc for heap allocations">,
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
"Bitwidth of the index type, 0 to use size of machine word">,
Option<"useGenericFunctions", "use-generic-functions",
"bool",
/*default=*/"false",
"Use generic allocation and deallocation functions instead of the "
"classic 'malloc', 'aligned_alloc' and 'free' functions">
];
}
//===----------------------------------------------------------------------===//
// MemRefToSPIRV
//===----------------------------------------------------------------------===//
def MapMemRefStorageClass : Pass<"map-memref-spirv-storage-class"> {
let summary = "Map numeric MemRef memory spaces to SPIR-V storage classes";
let constructor = "mlir::createMapMemRefStorageClassPass()";
let dependentDialects = ["spirv::SPIRVDialect"];
let options = [
Option<"clientAPI", "client-api", "std::string", /*default=*/"\"vulkan\"",
"The client API to use for populating mappings">
];
}
def ConvertMemRefToSPIRVPass : Pass<"convert-memref-to-spirv"> {
let summary = "Convert MemRef dialect to SPIR-V dialect";
let dependentDialects = ["spirv::SPIRVDialect"];
let options = [
Option<"boolNumBits", "bool-num-bits",
"int", /*default=*/"8",
"The number of bits to store a boolean value">,
Option<"use64bitIndex", "use-64bit-index",
"bool", /*default=*/"false",
"Use 64-bit integers to convert index types">
];
}
//===----------------------------------------------------------------------===//
// ShardToMPI
//===----------------------------------------------------------------------===//
def ConvertShardToMPIPass : Pass<"convert-shard-to-mpi"> {
let summary = "Convert Shard dialect to MPI dialect.";
let description = [{
This pass lowers communication operations from the Shard dialect to the MPI dialect.
If the module contains the DLTI attribute "MPI:comm_world-rank", its integer value is
used as the rank instead of calling MPI_Comm_rank. This enables optimizations such as
constant shape propagation and fusion, since shard and partition sizes can be
determined from the rank.
For some operations the conversion may require intermediate memref allocations.
For compatibility with the buffer deallocation pipeline, these allocations are only
deallocated when the lowered operations return buffers. When the operation was
defined in tensor-land, no explicit deallocation is performed. This means that the
deallocation must be handled by different means, e.g. by the deallocation pipeline.
}];
let dependentDialects = [
"affine::AffineDialect",
"arith::ArithDialect",
"bufferization::BufferizationDialect",
"cf::ControlFlowDialect",
"memref::MemRefDialect",
"mpi::MPIDialect",
"scf::SCFDialect",
"tensor::TensorDialect"
];
}
//===----------------------------------------------------------------------===//
// NVVMToLLVM
//===----------------------------------------------------------------------===//
def ConvertNVVMToLLVMPass : Pass<"convert-nvvm-to-llvm"> {
let summary = "Convert NVVM to PTX with Inline Assembly in LLVM dialect";
let description = [{
This pass generates PTX instructions using inline assembly for NVVM
operations implements `BasicPtxBuilderInterface`.
}];
let dependentDialects = [
"NVVM::NVVMDialect",
];
}
//===----------------------------------------------------------------------===//
// NVGPUToNVVM
//===----------------------------------------------------------------------===//
def ConvertNVGPUToNVVMPass : Pass<"convert-nvgpu-to-nvvm"> {
let summary = "Convert NVGPU dialect to NVVM dialect";
let description = [{
This pass converts supported NVGPU ops to NVVM dialect intrinsics.
}];
let dependentDialects = [
"arith::ArithDialect",
"LLVM::LLVMDialect",
"memref::MemRefDialect",
"NVVM::NVVMDialect"
];
}
//===----------------------------------------------------------------------===//
// OpenACCToSCF
//===----------------------------------------------------------------------===//
def ConvertOpenACCToSCFPass : Pass<"convert-openacc-to-scf", "ModuleOp"> {
let summary = "Convert the OpenACC ops to OpenACC with SCF dialect";
let dependentDialects = ["scf::SCFDialect", "acc::OpenACCDialect"];
}
//===----------------------------------------------------------------------===//
// OpenMPToLLVM
//===----------------------------------------------------------------------===//
def ConvertOpenMPToLLVMPass : Pass<"convert-openmp-to-llvm", "ModuleOp"> {
let summary = "Convert the OpenMP ops to OpenMP ops with LLVM dialect";
let dependentDialects = ["LLVM::LLVMDialect"];
}
//===----------------------------------------------------------------------===//
// PDLToPDLInterp
//===----------------------------------------------------------------------===//
def ConvertPDLToPDLInterpPass : Pass<"convert-pdl-to-pdl-interp", "ModuleOp"> {
let summary = "Convert PDL ops to PDL interpreter ops";
let dependentDialects = ["pdl_interp::PDLInterpDialect"];
}
//===----------------------------------------------------------------------===//
// ReconcileUnrealizedCasts
//===----------------------------------------------------------------------===//
def ReconcileUnrealizedCastsPass : Pass<"reconcile-unrealized-casts"> {
let summary = "Simplify and eliminate unrealized conversion casts";
let description = [{
Eliminate `unrealized_conversion_cast` operations, commonly introduced by
partial dialect conversions, that transitively convert a value to another
value of the same type, that is:
```
%0 = "producer.op"() : () -> !type.A
%1 = unrealized_conversion_cast %0 : !type.A to !type.B
%2 = unrealized_conversion_cast %1 : !type.B to !type.C
%3 = unrealized_conversion_cast %2 : !type.C to !type.A
"consumer.op"(%3) : (!type.A) -> ()
```
Such situations appear when the consumer operation is converted by one pass
and the producer operation is converted by another pass, each of which
produces an unrealized cast. This pass can be used to clean up the IR.
}];
}
//===----------------------------------------------------------------------===//
// SCFToControlFlow
//===----------------------------------------------------------------------===//
def SCFToControlFlowPass : Pass<"convert-scf-to-cf"> {
let summary = "Convert SCF dialect to ControlFlow dialect, replacing structured"
" control flow with a CFG";
let dependentDialects = ["cf::ControlFlowDialect"];
let options = [
Option<"allowPatternRollback", "allow-pattern-rollback", "bool", "true",
"Experimental performance flag to disallow pattern rollback">
];
}
//===----------------------------------------------------------------------===//
// SCFToOpenMP
//===----------------------------------------------------------------------===//
def ConvertSCFToOpenMPPass : Pass<"convert-scf-to-openmp", "ModuleOp"> {
let summary = "Convert SCF parallel loop to OpenMP parallel + workshare "
"constructs.";
let options = [
Option<"numThreads", "num-threads", "unsigned",
/*default=kUseOpenMPDefaultNumThreads*/"0",
"Number of threads to use">
];
let dependentDialects = ["omp::OpenMPDialect", "LLVM::LLVMDialect",
"memref::MemRefDialect"];
}
//===----------------------------------------------------------------------===//
// SCFToSPIRV
//===----------------------------------------------------------------------===//
def SCFToSPIRV : Pass<"convert-scf-to-spirv"> {
let summary = "Convert SCF dialect to SPIR-V dialect.";
let description = [{
Converts SCF ops into SPIR-V structured control flow ops.
SPIR-V structured control flow ops do not support yielding values.
So for SCF ops yielding values, SPIR-V variables are created for
holding the values and load/store operations are emitted for updating
them.
}];
let dependentDialects = ["spirv::SPIRVDialect"];
}
//===----------------------------------------------------------------------===//
// SCFToGPU
//===----------------------------------------------------------------------===//
def ConvertAffineForToGPUPass
: InterfacePass<"convert-affine-for-to-gpu", "FunctionOpInterface"> {
let summary = "Convert top-level AffineFor Ops to GPU kernels";
let dependentDialects = ["gpu::GPUDialect"];
let options = [
Option<"numBlockDims", "gpu-block-dims", "unsigned", /*default=*/"1u",
"Number of GPU block dimensions for mapping">,
Option<"numThreadDims", "gpu-thread-dims", "unsigned", /*default=*/"1u",
"Number of GPU thread dimensions for mapping">
];
}
def ConvertParallelLoopToGpuPass : Pass<"convert-parallel-loops-to-gpu"> {
let summary = "Convert mapped scf.parallel ops to gpu launch operations";
let description = [{
Creates a pass that converts scf.parallel operations into a gpu.launch
operation. The mapping of loop dimensions to launch dimensions is derived
from mapping attributes. See ParallelToGpuLaunchLowering::matchAndRewrite
for a description of the used attributes.
}];
let dependentDialects = ["affine::AffineDialect", "gpu::GPUDialect"];
}
//===----------------------------------------------------------------------===//
// SCFToEmitC
//===----------------------------------------------------------------------===//
def SCFToEmitC : Pass<"convert-scf-to-emitc"> {
let summary = "Convert SCF dialect to EmitC dialect, maintaining structured"
" control flow";
let dependentDialects = ["emitc::EmitCDialect"];
}
//===----------------------------------------------------------------------===//
// ShapeToStandard
//===----------------------------------------------------------------------===//
def ConvertShapeToStandardPass : Pass<"convert-shape-to-std", "ModuleOp"> {
let summary = "Convert operations from the shape dialect into the standard "
"dialect";
let dependentDialects = ["scf::SCFDialect"];
}
def ConvertShapeConstraintsPass : Pass<"convert-shape-constraints"> {
let summary = "Convert shape constraint operations to the standard dialect";
let description = [{
This pass eliminates shape constraints from the program, converting them to
eager (side-effecting) error handling code.
This pass is separate from the regular convert-shape-to-standard, despite
converting between the same dialects, because converting shape constraints
can happen at a different part of the program than general shape
computation lowering.
}];
let dependentDialects = ["cf::ControlFlowDialect", "scf::SCFDialect"];
}
//===----------------------------------------------------------------------===//
// SPIRVToLLVM
//===----------------------------------------------------------------------===//
def ConvertSPIRVToLLVMPass : Pass<"convert-spirv-to-llvm", "ModuleOp"> {
let summary = "Convert SPIR-V dialect to LLVM dialect";
let description = [{
See https://mlir.llvm.org/docs/SPIRVToLLVMDialectConversion/
for more details.
}];
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"clientAPI", "client-api", "::mlir::spirv::ClientAPI",
/*default=*/"::mlir::spirv::ClientAPI::Unknown",
"Derive StorageClass to address space mapping from the client API",
[{::llvm::cl::values(
clEnumValN(::mlir::spirv::ClientAPI::Unknown, "Unknown", "Unknown (default)"),
clEnumValN(::mlir::spirv::ClientAPI::Metal, "Metal", "Metal"),
clEnumValN(::mlir::spirv::ClientAPI::OpenCL, "OpenCL", "OpenCL"),
clEnumValN(::mlir::spirv::ClientAPI::Vulkan, "Vulkan", "Vulkan"),
clEnumValN(::mlir::spirv::ClientAPI::WebGPU, "WebGPU", "WebGPU")
)}]>,
];
}
//===----------------------------------------------------------------------===//
// TensorToLinalg
//===----------------------------------------------------------------------===//
def ConvertTensorToLinalgPass : Pass<"convert-tensor-to-linalg", "ModuleOp"> {
let summary = "Convert some Tensor dialect ops to Linalg dialect";
let dependentDialects = [
"arith::ArithDialect",
"linalg::LinalgDialect",
];
}
//===----------------------------------------------------------------------===//
// TensorToSPIRV
//===----------------------------------------------------------------------===//
def ConvertTensorToSPIRVPass : Pass<"convert-tensor-to-spirv"> {
let summary = "Convert Tensor dialect to SPIR-V dialect";
let dependentDialects = ["spirv::SPIRVDialect"];
let options = [
Option<"emulateLT32BitScalarTypes", "emulate-lt-32-bit-scalar-types",
"bool", /*default=*/"true",
"Emulate narrower scalar types with 32-bit ones if not supported by"
" the target">,
Option<"emulateUnsupportedFloatTypes", "emulate-unsupported-float-types",
"bool", /*default=*/"true",
"Emulate unsupported float types by representing them with integer "
"types of same bit width">
];
}
//===----------------------------------------------------------------------===//
// TosaToArith
//===----------------------------------------------------------------------===//
def TosaToArithPass : Pass<"tosa-to-arith"> {
let summary = "Lower TOSA to the Arith dialect";
let dependentDialects = [
"arith::ArithDialect",
];
let description = [{
Pass that converts TOSA operations to the equivalent operations using the
operations in the Arith dialect. The ApplyScale operator is optionally
included as it is often preserved until the final invocation.
}];
let options = [
Option<"includeApplyRescale", "include-apply-rescale",
"bool", /*default=*/"false",
"Whether to include the lowering for tosa.apply_rescale to arith">,
Option<"use32Bit", "use-32-bit",
"bool", /*default=*/"false",
"Whether to prioritze lowering to 32-bit operations">
];
}
//===----------------------------------------------------------------------===//
// TosaToLinalg
//===----------------------------------------------------------------------===//
def TosaToLinalg
: InterfacePass<"tosa-to-linalg", "FunctionOpInterface"> {
let summary = "Lower TOSA to LinAlg on tensors";
let description = [{
Pass that converts TOSA operations to the equivalent operations using the
tensor operations in LinAlg.
}];
let constructor = "tosa::createTosaToLinalg()";
let options = [
Option<"disableTosaDecompositions", "disable-tosa-decompositions",
"bool", /*default=*/"false",
"Disable tosa decompositions pass">,
Option<"aggressiveReduceConstant", "aggressive-reduce-constant",
"bool", /*default=*/"false",
"Always perform the reduce constant optimization">
];
}
//===----------------------------------------------------------------------===//
// TosaToLinalgNamed
//===----------------------------------------------------------------------===//
def TosaToLinalgNamed
: InterfacePass<"tosa-to-linalg-named", "FunctionOpInterface"> {
let summary = "Lower TOSA to LinAlg named operations";
let description = [{
Pass that converts TOSA operations to the equivalent operations using the
Linalg named operations.
}];
let options = [
Option<"preferConv2DKernelLayoutHWCF", "prefer-conv2d-kernel-layout-hwcf",
"bool", /*default=*/"false",
"Prefer generating linalg.conv_2d_nhwc_hwcf over linalg.conv_2d_nhwc_fhwc">
];
let constructor = "tosa::createTosaToLinalgNamed()";
}
//===----------------------------------------------------------------------===//
// TosaToMLProgram
//===----------------------------------------------------------------------===//
def TosaToMLProgram : Pass<"tosa-to-mlprogram", "ModuleOp"> {
let summary = "Lower TOSA to the MLProgram dialect";
let dependentDialects = ["ml_program::MLProgramDialect"];
let description = [{
Pass that converts TOSA's variable operator operations to the equivalent
MLProgram operations.
}];
}
//===----------------------------------------------------------------------===//
// TosaToSCF
//===----------------------------------------------------------------------===//
def TosaToSCFPass : Pass<"tosa-to-scf"> {
let summary = "Lower TOSA to the SCF dialect";
let dependentDialects = ["tensor::TensorDialect, scf::SCFDialect"];
let description = [{
Pass that converts TOSA's control flow operations to the equivalent SCF
operations.
}];
}
//===----------------------------------------------------------------------===//
// TOSA to SPIR-V Graph/TOSA
//===----------------------------------------------------------------------===//
def TosaToSPIRVTosaMarkGraphConstants
: Pass<"tosa-to-spirv-tosa-mark-graph-constants", "func::FuncOp"> {
let summary = "Mark large TOSA constants as SPIR-V Graph constants";
let description = [{
Marks large `tosa.const` and `tosa.const_shape` operations so the
TOSA-to-SPIR-V Graph/TOSA conversion lowers them to
`spirv.ARM.GraphConstant` instead of inlining them as `spirv.Constant`.
}];
let constructor = "tosa::createTosaToSPIRVTosaMarkGraphConstants()";
}
def TosaToSPIRVTosa : Pass<"tosa-to-spirv-tosa"> {
let summary = "Lower TOSA IR to SPIR-V Graph/TOSA operations";
let dependentDialects = [
"spirv::SPIRVDialect",
];
let description = [{
Converts TOSA programs to the SPIR-V Graph/TOSA representation by
wrapping converted functions in `spirv.module` and `spirv.ARM.Graph`,
lowering supported TOSA ops to `spirv.Tosa.*`, and rewriting TOSA tensor
and shape types to the corresponding SPIR-V ARM tensor types.
}];
let options = [
ListOption<"customOpDomainToOpcode", "custom-op-domain-to-opcode",
"std::pair<std::string, int32_t>",
"Map TOSA custom op domains to spirv.ExperimentalML.Call "
"opcodes. Entries use <domain>:<opcode>. The option can be "
"specified multiple times; if a domain appears more than once, "
"the last mapping wins.">
];
let constructor = "tosa::createTosaToSPIRVTosa()";
}
//===----------------------------------------------------------------------===//
// TosaToTensor
//===----------------------------------------------------------------------===//
def TosaToTensorPass : Pass<"tosa-to-tensor"> {
let summary = "Lower TOSA to the Tensor dialect";
let dependentDialects = [
"tensor::TensorDialect",
];
let description = [{
Pass that converts TOSA operations to the equivalent operations using the
operations in the Tensor dialect.
}];
}
//===----------------------------------------------------------------------===//
// UBToLLVM
//===----------------------------------------------------------------------===//
def UBToLLVMConversionPass : Pass<"convert-ub-to-llvm"> {
let summary = "Convert UB dialect to LLVM dialect";
let description = [{
This pass converts supported UB ops to LLVM dialect instructions.
}];
let dependentDialects = ["LLVM::LLVMDialect"];
let options = [
Option<"indexBitwidth", "index-bitwidth", "unsigned",
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
"Bitwidth of the index type, 0 to use size of machine word">,
];
}
//===----------------------------------------------------------------------===//
// UBToSPIRV
//===----------------------------------------------------------------------===//
def UBToSPIRVConversionPass : Pass<"convert-ub-to-spirv"> {
let summary = "Convert UB dialect to SPIR-V dialect";
let description = [{
This pass converts supported UB ops to SPIR-V dialect ops.
}];
let dependentDialects = ["spirv::SPIRVDialect"];
}
//===----------------------------------------------------------------------===//
// VectorToGPU
//===----------------------------------------------------------------------===//
def ConvertVectorToGPU : Pass<"convert-vector-to-gpu"> {
let summary = "Lower the operations from the vector dialect into the GPU "
"dialect";
let constructor = "mlir::createConvertVectorToGPUPass()";
let dependentDialects = [
"memref::MemRefDialect", "gpu::GPUDialect", "affine::AffineDialect",
"vector::VectorDialect", "nvgpu::NVGPUDialect"
];
let options = [
Option<"useNvGpu", "use-nvgpu", "bool", /*default=*/"false",
"convert to NvGPU ops instead of GPU dialect ops">
];
}
//===----------------------------------------------------------------------===//
// VectorToSCF
//===----------------------------------------------------------------------===//
def ConvertVectorToSCF : Pass<"convert-vector-to-scf"> {
let summary = "Lower the operations from the vector dialect into the SCF "
"dialect";
let constructor = "mlir::createConvertVectorToSCFPass()";
let dependentDialects = [
"affine::AffineDialect",
"memref::MemRefDialect",
"scf::SCFDialect",
"tensor::TensorDialect"
];
let options = [
Option<"fullUnroll", "full-unroll", "bool", /*default=*/"false",
"Perform full unrolling when converting vector transfers to SCF">,
Option<"targetRank", "target-rank", "unsigned", /*default=*/"1",
"Target vector rank to which transfer ops should be lowered">,
Option<"lowerTensors", "lower-tensors", "bool", /*default=*/"false",
"Lower transfer ops that operate on tensors">,
Option<"lowerScalable", "lower-scalable", "bool", /*default=*/"false",
"Add scalable vector specific lowerings (that introduce loops)">
];
}
//===----------------------------------------------------------------------===//
// VectorToArmSME
//===----------------------------------------------------------------------===//
def ConvertVectorToArmSMEPass : Pass<"convert-vector-to-arm-sme"> {
let summary = "Lower the operations from the vector dialect into the ArmSME "
"dialect";
let description = [{
Pass that converts vector dialect operations into equivalent ArmSME dialect
operations.
}];
let dependentDialects = ["arm_sme::ArmSMEDialect", "arm_sve::ArmSVEDialect"];
}
//===----------------------------------------------------------------------===//
// ArmSMEToSCF
//===----------------------------------------------------------------------===//
def ConvertArmSMEToSCFPass : Pass<"convert-arm-sme-to-scf"> {
let summary = "Lower the operations from the ArmSME dialect into the SCF "
"dialect";
let dependentDialects = [
"scf::SCFDialect",
"arith::ArithDialect",
"vector::VectorDialect",
"arm_sme::ArmSMEDialect"
];
}
//===----------------------------------------------------------------------===//
// ArmSMEToLLVM
//===----------------------------------------------------------------------===//
def ConvertArmSMEToLLVM : InterfacePass<"convert-arm-sme-to-llvm", "FunctionOpInterface"> {
let summary = "Lower the operations from the ArmSME dialect into the LLVM "
"dialect";
let constructor = "mlir::createConvertArmSMEToLLVMPass()";
let dependentDialects = [
"arm_sme::ArmSMEDialect",
"LLVM::LLVMDialect"
];
let options = [
Option<"dumpTileLiveRanges", "dump-tile-live-ranges",
"bool", /*default=*/"false",
"Dump the live ranges of SME tiles (for debugging)">
];
}
//===----------------------------------------------------------------------===//
// VectorToLLVM
//===----------------------------------------------------------------------===//
def ConvertVectorToLLVMPass : Pass<"convert-vector-to-llvm"> {
let summary = "Lower the operations from the vector dialect into the LLVM "
"dialect";
let description = [{
Convert operations from the vector dialect into the LLVM IR dialect
operations. The lowering pass provides several options to control
the kinds of optimizations that are allowed. It also provides options
that enable the use of one or more architectural-specific dialects
(X86, ArmNeon, ArmSVE, etc.) in combination with the architectural-neutral
vector dialect lowering.
}];
// Override explicitly in C++ to allow conditional dialect dependence.
// let dependentDialects;
let options = [
Option<"reassociateFPReductions", "reassociate-fp-reductions",
"bool", /*default=*/"false",
"Allows llvm to reassociate floating-point reductions for speed">,
Option<"force32BitVectorIndices", "force-32bit-vector-indices",
"bool", /*default=*/"true",
"Allows compiler to assume vector indices fit in 32-bit if that "
"yields faster code">,
Option<"useVectorAlignment", "use-vector-alignment",
"bool", /*default=*/"false",
"Use the preferred alignment of a vector type in load/store "
"operations instead of the alignment of the element type of the "
"memref. This flag is intended for use with hardware which requires"
"vector alignment, or in application contexts where it is known all "
"vector access are naturally aligned. If operations have an "
"alignment attribute set, the alignment attribute takes priority "
"over this option ">,
Option<"enableGEPInboundsNuw", "enable-gep-inbounds-nuw",
"bool", /*default=*/"false",
"Emit inbounds|nuw flags on GEPs generated by vector.load/store "
"lowering. Assumes 0 <= idx < dim_size and non-negative strides for "
"all dimensions. Setting this when those conditions do not hold is "
"undefined behavior under the LLVM lowering.">,
Option<"armNeon", "enable-arm-neon",
"bool", /*default=*/"false",
"Enables the use of ArmNeon dialect while lowering the vector "
"dialect.">,
Option<"armSVE", "enable-arm-sve",
"bool", /*default=*/"false",
"Enables the use of ArmSVE dialect while lowering the vector "
"dialect.">,
Option<"armI8MM", "enable-arm-i8mm",
"bool", /*default=*/"false",
"Enables the use of Arm FEAT_I8MM instructions while lowering "
"the vector dialect.">,
Option<"armBF16", "enable-arm-bf16",
"bool", /*default=*/"false",
"Enables the use of Arm FEAT_BF16 instructions while lowering "
"the vector dialect.">,
Option<"x86", "enable-x86",
"bool", /*default=*/"false",
"Enables the use of X86 dialect while lowering the vector dialect.">,
Option<"vectorContractLowering", "vector-contract-lowering",
"vector::VectorContractLowering",
/*default=*/"vector::VectorContractLowering::Dot",
VectorContractLoweringAttr.summary, [{::llvm::cl::values(
clEnumValN(::mlir::vector::VectorContractLowering::Dot, "dot",
"Progressively lower to finer grained `vector.contract` and dot-products. (default)"),
clEnumValN(::mlir::vector::VectorContractLowering::LLVMIntr, "llvmintr",
"Lower directly to `llvm.intr.matrix.multiply`."),
clEnumValN(::mlir::vector::VectorContractLowering::OuterProduct, "outerproduct",
"Lower to `vector.outerproduct`."),
clEnumValN(::mlir::vector::VectorContractLowering::ParallelArith, "parallelarith",
"Lower contract with all reduction dimensions unrolled to 1 to a vector elementwise operations.")
)}]>,
Option<"vectorTransposeLowering", "vector-transpose-lowering",
"vector::VectorTransposeLowering",
/*default=*/"vector::VectorTransposeLowering::EltWise",
VectorTransposeLoweringAttr.summary, [{::llvm::cl::values(
clEnumValN(::mlir::vector::VectorTransposeLowering::EltWise, "eltwise",
"Lower transpose into element-wise extract and inserts (default)"),
clEnumValN(::mlir::vector::VectorTransposeLowering::LLVMIntr, "llvmintr",
"Lower 2-D transpose directly to `llvm.intr.matrix.transpose`"),
clEnumValN(::mlir::vector::VectorTransposeLowering::Shuffle1D, "shuffle1d",
"Lower 2-D transpose to `vector.shuffle` on 1-D vector."),
clEnumValN(::mlir::vector::VectorTransposeLowering::Shuffle16x16, "shuffle16x16",
"Lower 2-D transpose to `vector.shuffle` on 16x16 vector.")
)}]>,
];
}
//===----------------------------------------------------------------------===//
// VectorToSPIRV
//===----------------------------------------------------------------------===//
def ConvertVectorToSPIRVPass : Pass<"convert-vector-to-spirv"> {
let summary = "Convert Vector dialect to SPIR-V dialect";
let dependentDialects = [
"spirv::SPIRVDialect",
"ub::UBDialect"
];
}
//===----------------------------------------------------------------------===//
// VectorToXeGPU
//===----------------------------------------------------------------------===//
def ConvertVectorToXeGPU : Pass<"convert-vector-to-xegpu"> {
let summary = "Lower the operations from the vector dialect into the XeGPU "
"dialect";
let dependentDialects = [
"memref::MemRefDialect", "arith::ArithDialect",
"vector::VectorDialect", "xegpu::XeGPUDialect"
];
}
//===----------------------------------------------------------------------===//
// VectorToAMX
//===----------------------------------------------------------------------===//
def ConvertVectorToAMX : Pass<"convert-vector-to-amx"> {
let summary = "Lower the operations from the vector dialect into the X86 "
"dialect AMX operations";
let dependentDialects = [
"affine::AffineDialect", "x86::X86Dialect", "arith::ArithDialect",
"memref::MemRefDialect", "scf::SCFDialect", "vector::VectorDialect"
];
}
//===----------------------------------------------------------------------===//
// XeVMToLLVM
//===----------------------------------------------------------------------===//
def ConvertXeVMToLLVMPass : Pass<"convert-xevm-to-llvm"> {
let summary = "Convert XeVM to LLVM dialect";
let dependentDialects = ["LLVM::LLVMDialect"];
}
//===----------------------------------------------------------------------===//
// XeGPUToXeVM
//===----------------------------------------------------------------------===//
def ConvertXeGPUToXeVMPass : Pass<"convert-xegpu-to-xevm"> {
let summary = "Convert XeGPU to XeVM dialect";
let dependentDialects = ["xevm::XeVMDialect", "vector::VectorDialect",
"memref::MemRefDialect", "arith::ArithDialect",
"LLVM::LLVMDialect", "index::IndexDialect",
"gpu::GPUDialect", "scf::SCFDialect"];
let options = [Option<"use64bitIndex", "use-64bit-index", "bool",
/*default=*/"true",
"Use 64-bit integers to convert index types">,
];
}
#endif // MLIR_CONVERSION_PASSES