| //===- GPUToROCDLPipeline.cpp - Lowering pipeline to ROCDL/AMDGPU --------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements a sink pipeline that lowers a payload containing |
| // `gpu.launch` / `gpu.module` ops to AMDGPU/ROCDL and emits an AMDGCN binary |
| // blob via `gpu-module-to-binary`. It is the AMD counterpart of |
| // `gpu-lower-to-nvvm-pipeline` and `gpu-lower-to-xevm-pipeline`. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "mlir/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.h" |
| #include "mlir/Conversion/AffineToStandard/AffineToStandard.h" |
| #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h" |
| #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h" |
| #include "mlir/Conversion/GPUCommon/GPUCommonPass.h" |
| #include "mlir/Conversion/GPUToROCDL/GPUToROCDLPass.h" |
| #include "mlir/Conversion/GPUToROCDL/Runtimes.h" |
| #include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h" |
| #include "mlir/Conversion/MathToLLVM/MathToLLVM.h" |
| #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h" |
| #include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h" |
| #include "mlir/Conversion/VectorToSCF/VectorToSCF.h" |
| #include "mlir/Dialect/GPU/IR/GPUDialect.h" |
| #include "mlir/Dialect/GPU/Pipelines/Passes.h" |
| #include "mlir/Dialect/GPU/Transforms/Passes.h" |
| #include "mlir/Dialect/MemRef/Transforms/Passes.h" |
| #include "mlir/Pass/PassManager.h" |
| #include "mlir/Pass/PassOptions.h" |
| #include "mlir/Transforms/Passes.h" |
| |
| using namespace mlir; |
| |
| namespace { |
| |
| //===----------------------------------------------------------------------===// |
| // Common pipeline |
| //===----------------------------------------------------------------------===// |
| void buildCommonPassPipeline( |
| OpPassManager &pm, const mlir::gpu::GPUToROCDLPipelineOptions &options) { |
| // Lower AMDGPU dialect ops (e.g. amdgpu.lds_barrier, amdgpu.dpp, |
| // amdgpu.mfma, amdgpu.dot, ...) to ROCDL intrinsics first, while they may |
| // still live in unout-lined `gpu.launch` bodies. Mirrors the way NVVM's |
| // pipeline runs `convert-nvgpu-to-nvvm` before kernel outlining. |
| ConvertAMDGPUToROCDLPassOptions amdgpuToROCDLOpt; |
| amdgpuToROCDLOpt.chipset = options.chip; |
| pm.addPass(createConvertAMDGPUToROCDLPass(amdgpuToROCDLOpt)); |
| |
| pm.addPass(createGpuKernelOutliningPass()); |
| pm.addPass(createConvertVectorToSCFPass()); |
| pm.addPass(createSCFToControlFlowPass()); |
| pm.addPass(createConvertFuncToLLVMPass()); |
| pm.addPass(memref::createExpandStridedMetadataPass()); |
| |
| GpuROCDLAttachTargetOptions rocdlTargetOptions; |
| rocdlTargetOptions.triple = options.triple; |
| rocdlTargetOptions.chip = options.chip; |
| rocdlTargetOptions.features = options.features; |
| rocdlTargetOptions.abiVersion = options.abiVersion; |
| rocdlTargetOptions.optLevel = options.optLevel; |
| rocdlTargetOptions.wave64Flag = options.wave64; |
| pm.addPass(createGpuROCDLAttachTarget(rocdlTargetOptions)); |
| |
| pm.addPass(createLowerAffinePass()); |
| pm.addPass(createArithToLLVMConversionPass()); |
| ConvertIndexToLLVMPassOptions convertIndexToLLVMPassOpt; |
| convertIndexToLLVMPassOpt.indexBitwidth = options.indexBitWidth; |
| pm.addPass(createConvertIndexToLLVMPass(convertIndexToLLVMPassOpt)); |
| pm.addPass(createCanonicalizerPass()); |
| pm.addPass(createCSEPass()); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // GPUModule-specific stuff. |
| //===----------------------------------------------------------------------===// |
| void buildGpuPassPipeline(OpPassManager &pm, |
| const mlir::gpu::GPUToROCDLPipelineOptions &options) { |
| ConvertGpuOpsToROCDLOpsOptions opt; |
| opt.chipset = options.chip; |
| opt.useBarePtrCallConv = options.kernelUseBarePtrCallConv; |
| opt.indexBitwidth = options.indexBitWidth; |
| // Always declare HIP as the runtime so that gpu.printf etc. lower to the |
| // matching runtime entry points exposed by `libmlir_rocm_runtime.so`. |
| opt.runtime = mlir::gpu::amd::Runtime::HIP; |
| pm.addNestedPass<gpu::GPUModuleOp>(createConvertGpuOpsToROCDLOps(opt)); |
| pm.addNestedPass<gpu::GPUModuleOp>(createCanonicalizerPass()); |
| pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass()); |
| pm.addNestedPass<gpu::GPUModuleOp>(createReconcileUnrealizedCastsPass()); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Host Post-GPU pipeline |
| //===----------------------------------------------------------------------===// |
| void buildHostPostPipeline( |
| OpPassManager &pm, const mlir::gpu::GPUToROCDLPipelineOptions &options) { |
| GpuToLLVMConversionPassOptions opt; |
| opt.hostBarePtrCallConv = options.hostUseBarePtrCallConv; |
| opt.kernelBarePtrCallConv = options.kernelUseBarePtrCallConv; |
| pm.addPass(createGpuToLLVMConversionPass(opt)); |
| |
| GpuModuleToBinaryPassOptions gpuModuleToBinaryPassOptions; |
| gpuModuleToBinaryPassOptions.compilationTarget = options.binaryFormat; |
| gpuModuleToBinaryPassOptions.cmdOptions = options.cmdOptions; |
| pm.addPass(createGpuModuleToBinaryPass(gpuModuleToBinaryPassOptions)); |
| pm.addPass(createConvertMathToLLVMPass()); |
| pm.addPass(createCanonicalizerPass()); |
| pm.addPass(createCSEPass()); |
| pm.addPass(createReconcileUnrealizedCastsPass()); |
| } |
| |
| } // namespace |
| |
| void mlir::gpu::buildLowerToROCDLPassPipeline( |
| OpPassManager &pm, const GPUToROCDLPipelineOptions &options) { |
| // Common pipelines |
| buildCommonPassPipeline(pm, options); |
| |
| // GPUModule-specific stuff |
| buildGpuPassPipeline(pm, options); |
| |
| // Host post-GPUModule-specific stuff |
| buildHostPostPipeline(pm, options); |
| } |
| |
| void mlir::gpu::registerGPUToROCDLPipeline() { |
| PassPipelineRegistration<GPUToROCDLPipelineOptions>( |
| "gpu-lower-to-rocdl-pipeline", |
| "The default pipeline lowers main dialects (arith, memref, scf, vector, " |
| "gpu) to ROCDL. It starts by lowering GPU code to the specified " |
| "compilation target (default is fatbin) then lowers the host code.", |
| buildLowerToROCDLPassPipeline); |
| } |