1//===-- Passes.td - Conversion pass definition file --------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef MLIR_CONVERSION_PASSES
10#define MLIR_CONVERSION_PASSES
11
12include "mlir/Pass/PassBase.td"
13
14//===----------------------------------------------------------------------===//
15// AffineToStandard
16//===----------------------------------------------------------------------===//
17
18def ConvertAffineToStandard : Pass<"lower-affine"> {
19  let summary = "Lower Affine operations to a combination of Standard and SCF "
20                "operations";
21  let description = [{
22
23    Convert operations from the affine dialect into operations from the SCF and
24    standard dialects.
25
26    `affine.for` operations are converted to `scf.for` operations that are free
27    of certain structural restrictions (on their bounds and step). `affine.if`
28    is similarly converted to the `scf.if` operation. `affine.apply` operations
29    are converted into sequences of primitive arithmetic operations from the
30    standard dialect that have the same effect, using operands of the `index`
31    type. Consequently, named maps and sets thare are no longer in use may be
32    removed from the module.
33
34    For example, `%r = affine.apply affine_map<(d0, d1)[s0] -> (d0 + 2*d1 +
35    s0)>(%d0, %d1)[%s0]`
36    can be converted into:
37
38    ```mlir
39    %d0 = <...>
40    %d1 = <...>
41    %s0 = <...>
42    %0 = constant 2 : index
43    %1 = muli %0, %d1
44    %2 = addi %d0, %1
45    %r = addi %2, %s0
46    ```
47
48    #### Input invariant
49
50    -   no `Tensor` types;
51
52    These restrictions may be lifted in the future.
53
54    #### Output IR
55
56    Functions with `affine.for` and `affine.if` operations eliminated. These
57    functions may contain operations from the Standard dialect in addition to
58    those already present before the pass.
59
60    #### Invariants
61
62    -   Functions without a body are not modified.
63    -   The semantics of the other functions is preserved.
64    -   Individual operations other than those mentioned above are not modified
65        if they do not depend on the loop iterator value or on the result of
66        `affine.apply`.
67  }];
68  let constructor = "mlir::createLowerAffinePass()";
69  let dependentDialects = [
70    "scf::SCFDialect",
71    "StandardOpsDialect",
72    "vector::VectorDialect"
73  ];
74}
75
76//===----------------------------------------------------------------------===//
77// AsyncToLLVM
78//===----------------------------------------------------------------------===//
79
80def ConvertAsyncToLLVM : Pass<"convert-async-to-llvm", "ModuleOp"> {
81  let summary = "Convert the operations from the async dialect into the LLVM "
82                "dialect";
83  let description = [{
84    Convert `async.execute` operations to LLVM coroutines and use async runtime
85    API to execute them.
86  }];
87  let constructor = "mlir::createConvertAsyncToLLVMPass()";
88  let dependentDialects = ["LLVM::LLVMDialect"];
89}
90
91//===----------------------------------------------------------------------===//
92// ComplexToLLVM
93//===----------------------------------------------------------------------===//
94
95def ConvertComplexToLLVM : Pass<"convert-complex-to-llvm", "ModuleOp"> {
96  let summary = "Convert Complex dialect to LLVM dialect";
97  let constructor = "mlir::createConvertComplexToLLVMPass()";
98  let dependentDialects = ["LLVM::LLVMDialect"];
99}
100
101//===----------------------------------------------------------------------===//
102// GPUCommon
103//===----------------------------------------------------------------------===//
104
105def GpuToLLVMConversionPass : Pass<"gpu-to-llvm", "ModuleOp"> {
106  let summary = "Convert GPU dialect to LLVM dialect with GPU runtime calls";
107  let constructor = "mlir::createGpuToLLVMConversionPass()";
108  let dependentDialects = ["LLVM::LLVMDialect"];
109  let options = [
110    Option<"gpuBinaryAnnotation", "gpu-binary-annotation", "std::string",
111           "", "Annotation attribute string for GPU binary">,
112  ];
113}
114
115def LowerHostCodeToLLVM : Pass<"lower-host-to-llvm", "ModuleOp"> {
116  let summary = "Lowers the host module code and `gpu.launch_func` to LLVM";
117  let constructor = "mlir::createLowerHostCodeToLLVMPass()";
118  let dependentDialects = ["LLVM::LLVMDialect"];
119}
120
121//===----------------------------------------------------------------------===//
122// GPUToNVVM
123//===----------------------------------------------------------------------===//
124
125def ConvertGpuOpsToNVVMOps : Pass<"convert-gpu-to-nvvm", "gpu::GPUModuleOp"> {
126  let summary = "Generate NVVM operations for gpu operations";
127  let constructor = "mlir::createLowerGpuOpsToNVVMOpsPass()";
128  let dependentDialects = ["NVVM::NVVMDialect"];
129  let options = [
130    Option<"indexBitwidth", "index-bitwidth", "unsigned",
131           /*default=kDeriveIndexBitwidthFromDataLayout*/"0",
132           "Bitwidth of the index type, 0 to use size of machine word">
133  ];
134}
135
136//===----------------------------------------------------------------------===//
137// GPUToROCDL
138//===----------------------------------------------------------------------===//
139
140def ConvertGpuOpsToROCDLOps : Pass<"convert-gpu-to-rocdl", "gpu::GPUModuleOp"> {
141  let summary = "Generate ROCDL operations for gpu operations";
142  let constructor = "mlir::createLowerGpuOpsToROCDLOpsPass()";
143  let dependentDialects = ["ROCDL::ROCDLDialect"];
144  let options = [
145    Option<"indexBitwidth", "index-bitwidth", "unsigned",
146           /*default=kDeriveIndexBitwidthFromDataLayout*/"0",
147           "Bitwidth of the index type, 0 to use size of machine word">
148  ];
149}
150
151//===----------------------------------------------------------------------===//
152// GPUToSPIRV
153//===----------------------------------------------------------------------===//
154
155def ConvertGPUToSPIRV : Pass<"convert-gpu-to-spirv", "ModuleOp"> {
156  let summary = "Convert GPU dialect to SPIR-V dialect";
157  let description = [{
158    This pass converts supported GPU device ops to SPIR-V ops. It does not
159    handle GPU host ops.
160
161    A `gpu.func` op can have parameters to pass in resources. But in SPIR-V
162    entry functions cannot take parameters; they use descriptors to access
163    resources. By default, parameters to a `gpu.func` op will be converted to
164    global variables. These global variables will be assigned sequential binding
165    numbers following their order in the original `gpu.func` op, starting from
166    0, in set 0. One can attach `spv.interface_var_abi` to those parameters
167    to control the set and binding if wanted.
168  }];
169  let constructor = "mlir::createConvertGPUToSPIRVPass()";
170  let dependentDialects = ["spirv::SPIRVDialect"];
171}
172
173//===----------------------------------------------------------------------===//
174// GPUToVulkan
175//===----------------------------------------------------------------------===//
176
177def ConvertGpuLaunchFuncToVulkanLaunchFunc
178    : Pass<"convert-gpu-launch-to-vulkan-launch", "ModuleOp"> {
179  let summary = "Convert gpu.launch_func to vulkanLaunch external call";
180  let description = [{
181    This pass is only intended for the mlir-vulkan-runner.
182  }];
183  let constructor = "mlir::createConvertGpuLaunchFuncToVulkanLaunchFuncPass()";
184  let dependentDialects = ["spirv::SPIRVDialect"];
185}
186
187def ConvertVulkanLaunchFuncToVulkanCalls
188    : Pass<"launch-func-to-vulkan", "ModuleOp"> {
189  let summary = "Convert vulkanLaunch external call to Vulkan runtime external "
190                "calls";
191  let description = [{
192    This pass is only intended for the mlir-vulkan-runner.
193  }];
194  let constructor = "mlir::createConvertVulkanLaunchFuncToVulkanCallsPass()";
195  let dependentDialects = ["LLVM::LLVMDialect"];
196}
197
198//===----------------------------------------------------------------------===//
199// LinalgToLLVM
200//===----------------------------------------------------------------------===//
201
202def ConvertLinalgToLLVM : Pass<"convert-linalg-to-llvm", "ModuleOp"> {
203  let summary = "Convert the operations from the linalg dialect into the LLVM "
204                "dialect";
205  let constructor = "mlir::createConvertLinalgToLLVMPass()";
206  let dependentDialects = ["scf::SCFDialect", "LLVM::LLVMDialect"];
207}
208
209//===----------------------------------------------------------------------===//
210// LinalgToStandard
211//===----------------------------------------------------------------------===//
212
213def ConvertLinalgToStandard : Pass<"convert-linalg-to-std", "ModuleOp"> {
214  let summary = "Convert the operations from the linalg dialect into the "
215                "Standard dialect";
216  let constructor = "mlir::createConvertLinalgToStandardPass()";
217  let dependentDialects = ["StandardOpsDialect"];
218}
219
220//===----------------------------------------------------------------------===//
221// LinalgToSPIRV
222//===----------------------------------------------------------------------===//
223
224def ConvertLinalgToSPIRV : Pass<"convert-linalg-to-spirv", "ModuleOp"> {
225  let summary = "Convert Linalg dialect to SPIR-V dialect";
226  let description = [{
227    This pass converts supported Linalg ops to SPIR-V ops. It's quite
228    experimental and are expected to migrate to other proper conversions.
229  }];
230  let constructor = "mlir::createLinalgToSPIRVPass()";
231  let dependentDialects = ["spirv::SPIRVDialect"];
232}
233
234//===----------------------------------------------------------------------===//
235// OpenMPToLLVM
236//===----------------------------------------------------------------------===//
237
238def ConvertOpenMPToLLVM : Pass<"convert-openmp-to-llvm", "ModuleOp"> {
239  let summary = "Convert the OpenMP ops to OpenMP ops with LLVM dialect";
240  let constructor = "mlir::createConvertOpenMPToLLVMPass()";
241  let dependentDialects = ["LLVM::LLVMDialect"];
242}
243
244//===----------------------------------------------------------------------===//
245// PDLToPDLInterp
246//===----------------------------------------------------------------------===//
247
248def ConvertPDLToPDLInterp : Pass<"convert-pdl-to-pdl-interp", "ModuleOp"> {
249  let summary = "Convert PDL ops to PDL interpreter ops";
250  let constructor = "mlir::createPDLToPDLInterpPass()";
251  let dependentDialects = ["pdl_interp::PDLInterpDialect"];
252}
253
254//===----------------------------------------------------------------------===//
255// SCFToOpenMP
256//===----------------------------------------------------------------------===//
257
258def ConvertSCFToOpenMP : FunctionPass<"convert-scf-to-openmp"> {
259  let summary = "Convert SCF parallel loop to OpenMP parallel + workshare "
260                "constructs.";
261  let constructor = "mlir::createConvertSCFToOpenMPPass()";
262  let dependentDialects = ["omp::OpenMPDialect"];
263}
264
265//===----------------------------------------------------------------------===//
266// SCFToSPIRV
267//===----------------------------------------------------------------------===//
268
269def SCFToSPIRV : Pass<"convert-scf-to-spirv", "ModuleOp"> {
270  let summary = "Convert SCF dialect to SPIR-V dialect.";
271  let description = [{
272    This pass converts SCF ops into SPIR-V structured control flow ops.
273    SPIR-V structured control flow ops does not support yielding values.
274    So for SCF ops yielding values, SPIR-V variables are created for
275    holding the values and load/store operations are emitted for updating
276    them.
277  }];
278  let constructor = "mlir::createConvertSCFToSPIRVPass()";
279  let dependentDialects = ["spirv::SPIRVDialect"];
280}
281
282//===----------------------------------------------------------------------===//
283// SCFToStandard
284//===----------------------------------------------------------------------===//
285
286def SCFToStandard : Pass<"convert-scf-to-std"> {
287  let summary = "Convert SCF dialect to Standard dialect, replacing structured"
288                " control flow with a CFG";
289  let constructor = "mlir::createLowerToCFGPass()";
290  let dependentDialects = ["StandardOpsDialect"];
291}
292
293//===----------------------------------------------------------------------===//
294// SCFToGPU
295//===----------------------------------------------------------------------===//
296
297def ConvertAffineForToGPU : FunctionPass<"convert-affine-for-to-gpu"> {
298  let summary = "Convert top-level AffineFor Ops to GPU kernels";
299  let constructor = "mlir::createAffineForToGPUPass()";
300  let dependentDialects = ["gpu::GPUDialect"];
301  let options = [
302    Option<"numBlockDims", "gpu-block-dims", "unsigned", /*default=*/"1u",
303           "Number of GPU block dimensions for mapping">,
304    Option<"numThreadDims", "gpu-thread-dims", "unsigned", /*default=*/"1u",
305           "Number of GPU thread dimensions for mapping">
306  ];
307}
308
309def ConvertParallelLoopToGpu : Pass<"convert-parallel-loops-to-gpu"> {
310  let summary = "Convert mapped scf.parallel ops to gpu launch operations";
311  let constructor = "mlir::createParallelLoopToGpuPass()";
312  let dependentDialects = ["AffineDialect", "gpu::GPUDialect"];
313}
314
315//===----------------------------------------------------------------------===//
316// ShapeToStandard
317//===----------------------------------------------------------------------===//
318
319def ConvertShapeToStandard : Pass<"convert-shape-to-std", "ModuleOp"> {
320  let summary = "Convert operations from the shape dialect into the standard "
321                "dialect";
322  let constructor = "mlir::createConvertShapeToStandardPass()";
323  let dependentDialects = ["StandardOpsDialect", "scf::SCFDialect"];
324}
325
326def ConvertShapeConstraints: Pass<"convert-shape-constraints", "FuncOp"> {
327  let summary = "Convert shape constraint operations to the standard dialect";
328  let description = [{
329    This pass eliminates shape constraints from the program, converting them to
330    eager (side-effecting) error handling code.
331
332    This pass is separate from the regular convert-shape-to-standard, despite
333    converting between the same dialects, because converting shape constraints
334    can happen at a different part of the program than general shape
335    computation lowering.
336  }];
337  let constructor = "mlir::createConvertShapeConstraintsPass()";
338  let dependentDialects = ["StandardOpsDialect", "scf::SCFDialect"];
339}
340
341//===----------------------------------------------------------------------===//
342// SPIRVToLLVM
343//===----------------------------------------------------------------------===//
344
345def ConvertSPIRVToLLVM : Pass<"convert-spirv-to-llvm", "ModuleOp"> {
346  let summary = "Convert SPIR-V dialect to LLVM dialect";
347  let description = [{
348    See https://mlir.llvm.org/docs/SPIRVToLLVMDialectConversion/
349    for more details.
350  }];
351  let constructor = "mlir::createConvertSPIRVToLLVMPass()";
352  let dependentDialects = ["LLVM::LLVMDialect"];
353}
354
355//===----------------------------------------------------------------------===//
356// StandardToLLVM
357//===----------------------------------------------------------------------===//
358
359def ConvertStandardToLLVM : Pass<"convert-std-to-llvm", "ModuleOp"> {
360  let summary = "Convert scalar and vector operations from the Standard to the "
361                "LLVM dialect";
362  let description = [{
363    Convert standard operations into the LLVM IR dialect operations.
364
365    #### Input invariant
366
367    -   operations including: arithmetic on integers and floats, constants,
368        direct calls, returns and branches;
369    -   no `tensor` types;
370    -   all `vector` are one-dimensional;
371    -   all blocks are reachable by following the successors of the first basic
372        block;
373
374    If other operations are present and their results are required by the LLVM
375    IR dialect operations, the pass will fail.  Any LLVM IR operations or types
376    already present in the IR will be kept as is.
377
378    #### Output IR
379
380    Functions converted to LLVM IR. Function arguments types are converted
381    one-to-one. Function results are converted one-to-one and, in case more than
382    1 value is returned, packed into an LLVM IR struct type. Function calls and
383    returns are updated accordingly. Block argument types are updated to use
384    LLVM IR types.
385  }];
386  let constructor = "mlir::createLowerToLLVMPass()";
387  let dependentDialects = ["LLVM::LLVMDialect"];
388  let options = [
389    Option<"useAlignedAlloc", "use-aligned-alloc", "bool", /*default=*/"false",
390           "Use aligned_alloc in place of malloc for heap allocations">,
391    Option<"useBarePtrCallConv", "use-bare-ptr-memref-call-conv", "bool",
392           /*default=*/"false",
393           "Replace FuncOp's MemRef arguments with bare pointers to the MemRef "
394           "element types">,
395    Option<"emitCWrappers", "emit-c-wrappers", "bool", /*default=*/"false",
396           "Emit wrappers for C-compatible pointer-to-struct memref "
397           "descriptors">,
398    Option<"indexBitwidth", "index-bitwidth", "unsigned",
399           /*default=kDeriveIndexBitwidthFromDataLayout*/"0",
400           "Bitwidth of the index type, 0 to use size of machine word">,
401    Option<"dataLayout", "data-layout", "std::string",
402           /*default=*/"\"\"",
403           "String description (LLVM format) of the data layout that is "
404           "expected on the produced module">
405  ];
406}
407
408//===----------------------------------------------------------------------===//
409// StandardToSPIRV
410//===----------------------------------------------------------------------===//
411
412def LegalizeStandardForSPIRV : Pass<"legalize-std-for-spirv"> {
413  let summary = "Legalize standard ops for SPIR-V lowering";
414  let description = [{
415    The pass contains certain intra standard op conversions that are meant for
416    lowering to SPIR-V ops, e.g., folding subviews loads/stores to the original
417    loads/stores from/to the original memref.
418  }];
419  let constructor = "mlir::createLegalizeStdOpsForSPIRVLoweringPass()";
420  let dependentDialects = ["spirv::SPIRVDialect"];
421}
422
423def ConvertStandardToSPIRV : Pass<"convert-std-to-spirv", "ModuleOp"> {
424  let summary = "Convert Standard dialect to SPIR-V dialect";
425  let constructor = "mlir::createConvertStandardToSPIRVPass()";
426  let dependentDialects = ["spirv::SPIRVDialect"];
427}
428
429//===----------------------------------------------------------------------===//
430// TosaToLinalg
431//===----------------------------------------------------------------------===//
432
433def TosaToLinalgOnTensors : FunctionPass<"tosa-to-linalg-on-tensors"> {
434  let summary = "Lower TOSA to LinAlg on tensors";
435  let description = [{
436    Pass that converts TOSA operations to the equivalent operations using the
437    tensor operations in LinAlg.
438  }];
439
440  let constructor = "tosa::createTosaToLinalgOnTensors()";
441}
442
443//===----------------------------------------------------------------------===//
444// VectorToSCF
445//===----------------------------------------------------------------------===//
446
447def ConvertVectorToSCF : FunctionPass<"convert-vector-to-scf"> {
448  let summary = "Lower the operations from the vector dialect into the SCF "
449                "dialect";
450  let constructor = "mlir::createConvertVectorToSCFPass()";
451  let dependentDialects = ["AffineDialect", "scf::SCFDialect"];
452  let options = [
453    Option<"fullUnroll", "full-unroll", "bool", /*default=*/"false",
454           "Perform full unrolling when converting vector transfers to SCF">,
455  ];
456}
457
458//===----------------------------------------------------------------------===//
459// VectorToLLVM
460//===----------------------------------------------------------------------===//
461
462def ConvertVectorToLLVM : Pass<"convert-vector-to-llvm", "ModuleOp"> {
463  let summary = "Lower the operations from the vector dialect into the LLVM "
464                "dialect";
465  let description = [{
466
467    Convert operations from the vector dialect into the LLVM IR dialect
468    operations. The lowering pass provides several options to control
469    the kinds of optimizations that are allowed. It also provides options
470    that enable the use of one or more architectural-specific dialects
471    (AVX512, ArmNeon, ArmSVE, etc.) in combination with the
472    architectural-neutral vector dialect lowering.
473
474  }];
475  let constructor = "mlir::createConvertVectorToLLVMPass()";
476  // Override explicitly in C++ to allow conditional dialect dependence.
477  // let dependentDialects;
478  let options = [
479    Option<"reassociateFPReductions", "reassociate-fp-reductions",
480           "bool", /*default=*/"false",
481           "Allows llvm to reassociate floating-point reductions for speed">,
482    Option<"enableIndexOptimizations", "enable-index-optimizations",
483           "bool", /*default=*/"true",
484           "Allows compiler to assume indices fit in 32-bit if that yields "
485	   "faster code">,
486    Option<"enableAVX512", "enable-avx512",
487           "bool", /*default=*/"false",
488           "Enables the use of AVX512 dialect while lowering the vector "
489	   "dialect.">,
490    Option<"enableArmNeon", "enable-arm-neon",
491           "bool", /*default=*/"false",
492           "Enables the use of ArmNeon dialect while lowering the vector "
493	   "dialect.">,
494    Option<"enableArmSVE", "enable-arm-sve",
495           "bool", /*default=*/"false",
496           "Enables the use of ArmSVE dialect while lowering the vector "
497       "dialect.">
498  ];
499}
500
501//===----------------------------------------------------------------------===//
502// VectorToROCDL
503//===----------------------------------------------------------------------===//
504
505def ConvertVectorToROCDL : Pass<"convert-vector-to-rocdl", "ModuleOp"> {
506  let summary = "Lower the operations from the vector dialect into the ROCDL "
507                "dialect";
508  let constructor = "mlir::createConvertVectorToROCDLPass()";
509  let dependentDialects = ["ROCDL::ROCDLDialect"];
510}
511
512//===----------------------------------------------------------------------===//
513// VectorToSPIRV
514//===----------------------------------------------------------------------===//
515
516def ConvertVectorToSPIRV : Pass<"convert-vector-to-spirv", "ModuleOp"> {
517  let summary = "Convert Vector dialect to SPIR-V dialect";
518  let constructor = "mlir::createConvertVectorToSPIRVPass()";
519  let dependentDialects = ["spirv::SPIRVDialect"];
520}
521
522#endif // MLIR_CONVERSION_PASSES
523