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