MLIR 24.0.0git
GPUToXeVMPipeline.cpp
Go to the documentation of this file.
1//===- GPUToXeVMPipeline.cpp - Lowering pipeline to XeVM/LLVM -------------===//
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// This file implements a pass for testing the lowering to XeVM as a generally
10// usable sink pass. If XeGPU ops are used, it expects the MLIR code to have
11// XeGPU ops already embedded in gpu code.
12//
13//===----------------------------------------------------------------------===//
14
40
41#include <utility>
42
43using namespace mlir;
44
45namespace {
46//===----------------------------------------------------------------------===//
47// Pre-GPU common pipeline for both Host and GPU.
48//===----------------------------------------------------------------------===//
49void buildPreGPUCommonPassPipeline(
51 // builtin.module scope passes.
52 pm.addPass(createCSEPass());
53 {
54 GpuXeVMAttachTargetOptions xevmTargetOptions;
55 xevmTargetOptions.moduleMatcher = options.xevmModuleMatcher;
56 xevmTargetOptions.triple = options.zebinTriple;
57 xevmTargetOptions.chip = options.zebinChip;
58 xevmTargetOptions.optLevel = options.optLevel;
59 xevmTargetOptions.cmdOptions = options.cmdOptions;
60 pm.addPass(createGpuXeVMAttachTarget(std::move(xevmTargetOptions)));
61 }
62 pm.addPass(createLowerAffinePass());
63 pm.addNestedPass<func::FuncOp>(createGpuAsyncRegionPass());
64}
65
66//===----------------------------------------------------------------------===//
67// GPUModule-specific stuff.
68//===----------------------------------------------------------------------===//
69void buildGPUPassPipeline(OpPassManager &pm,
71 xegpu::XeGPUPropagateLayoutOptions laneLayoutOptions;
72 laneLayoutOptions.indexBitWidth = options.use64bitIndex ? 64 : 32;
73 laneLayoutOptions.layoutKind = "lane";
74 pm.addNestedPass<ModuleOp>(createCSEPass());
75 if (options.enableVectorToXeGPU)
76 pm.addNestedPass<gpu::GPUModuleOp>(createConvertVectorToXeGPU());
77 if (options.xegpuOpLevel == "workgroup") {
78 xegpu::XeGPUPropagateLayoutOptions sgLayoutOptions;
79 sgLayoutOptions.layoutKind = "subgroup";
80 pm.addNestedPass<gpu::GPUModuleOp>(
81 xegpu::createXeGPUPropagateLayout(std::move(sgLayoutOptions)));
82 pm.addNestedPass<gpu::GPUModuleOp>(xegpu::createXeGPUWgToSgDistribute());
83 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
84 pm.addNestedPass<gpu::GPUModuleOp>(createLowerAffinePass());
85 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
86 xegpu::XeGPUPropagateLayoutOptions instDataOptions;
87 instDataOptions.layoutKind = "inst";
88 pm.addNestedPass<gpu::GPUModuleOp>(
89 xegpu::createXeGPUPropagateLayout(std::move(instDataOptions)));
90 pm.addNestedPass<gpu::GPUModuleOp>(xegpu::createXeGPUBlocking());
91 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
92 }
93 if (options.xegpuOpLevel == "subgroup" ||
94 options.xegpuOpLevel == "workgroup") {
95 pm.addNestedPass<gpu::GPUModuleOp>(
96 xegpu::createXeGPUPropagateLayout(laneLayoutOptions));
97 pm.addNestedPass<gpu::GPUModuleOp>(xegpu::createXeGPUPeepHoleOptimizer());
98 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
99 pm.addNestedPass<gpu::GPUModuleOp>(
100 xegpu::createXeGPUPropagateLayout(std::move(laneLayoutOptions)));
101 pm.addNestedPass<gpu::GPUModuleOp>(xegpu::createXeGPUSgToLaneDistribute());
102 pm.addNestedPass<gpu::GPUModuleOp>(createCanonicalizerPass());
103 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
104 pm.addNestedPass<gpu::GPUModuleOp>(createLoopInvariantCodeMotionPass());
105 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
106 pm.addNestedPass<gpu::GPUModuleOp>(xegpu::createXeGPUVectorLinearize());
107 pm.addNestedPass<gpu::GPUModuleOp>(createCanonicalizerPass());
108 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
109 }
110 // Break down high-level micro-scaling (MX) ops (arith.scaling_extf and
111 // arith.scaling_truncf) into standard arith ops (extf/truncf + mulf), and
112 // expand extf/truncf on f8E8M0FNU into integer bit manipulation. This runs
113 // before the XeVM/LLVM conversions. The f4E2M1FN expansion patterns are
114 // intentionally left disabled: f4E2M1FN extf/truncf are lowered by the XeVM
115 // conversions (xevm.extf), whereas f8E8M0FNU is not supported there and so
116 // must be expanded here.
117 {
118 arith::ArithExpandOpsPassOptions arithExpandOptions;
119 arithExpandOptions.includeF8E8M0 = true;
120 pm.addNestedPass<gpu::GPUModuleOp>(
121 arith::createArithExpandOpsPass(std::move(arithExpandOptions)));
122 }
123 pm.addNestedPass<gpu::GPUModuleOp>(createConvertMathToXeVM());
124 ConvertXeGPUToXeVMPassOptions xegpuToXeVMOptions;
125 xegpuToXeVMOptions.use64bitIndex = options.use64bitIndex;
126 pm.addNestedPass<gpu::GPUModuleOp>(
127 createConvertXeGPUToXeVMPass(std::move(xegpuToXeVMOptions)));
128 {
129 ConvertGpuOpsToLLVMSPVOpsOptions gpuToLLVMSPVOptions;
130 gpuToLLVMSPVOptions.use64bitIndex = options.use64bitIndex;
131 pm.addNestedPass<gpu::GPUModuleOp>(
132 createConvertGpuOpsToLLVMSPVOps(std::move(gpuToLLVMSPVOptions)));
133 }
134 // Legalize math/arith ops on floating-point types that the XeVM target
135 // cannot handle natively (e.g. bf16) by wrapping them with extf/truncf
136 // around a supported type (defaulting to f32).
137 {
138 math::MathExtendToSupportedTypesOptions mathExtendOptions;
139 mathExtendOptions.extraTypeStrs.assign(options.mathExtendExtraTypes.begin(),
140 options.mathExtendExtraTypes.end());
141 mathExtendOptions.targetTypeStr = options.supportedTargetTypes;
142 pm.addNestedPass<gpu::GPUModuleOp>(
143 math::createMathExtendToSupportedTypes(std::move(mathExtendOptions)));
144 }
145 {
146 arith::ArithEmulateUnsupportedFloatsOptions arithEmulateOptions;
147 arithEmulateOptions.sourceTypeStrs.assign(
148 options.unsupportedSourceTypes.begin(),
149 options.unsupportedSourceTypes.end());
150 arithEmulateOptions.targetTypeStr = options.supportedTargetTypes;
151 pm.addNestedPass<gpu::GPUModuleOp>(
152 arith::createArithEmulateUnsupportedFloats(
153 std::move(arithEmulateOptions)));
154 }
155 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
156 pm.addNestedPass<gpu::GPUModuleOp>(createReconcileUnrealizedCastsPass());
157}
158
159//===----------------------------------------------------------------------===//
160// Post-GPU pipeline for both Host and GPU.
161//===----------------------------------------------------------------------===//
162void buildPostGPUCommonPassPipeline(
164 // builtin.module scope passes.
166 pm.addPass(createSCFToControlFlowPass());
167 pm.addPass(memref::createExpandStridedMetadataPass());
168 {
169 GpuToLLVMConversionPassOptions gpuToLLVMOptions;
170 gpuToLLVMOptions.hostBarePtrCallConv = options.hostBarePtrCallConv;
171 gpuToLLVMOptions.kernelBarePtrCallConv = options.kernelBarePtrCallConv;
172 pm.addPass(createGpuToLLVMConversionPass(std::move(gpuToLLVMOptions)));
173 }
174 pm.addPass(createLowerAffinePass());
175 pm.addPass(createConvertVectorToLLVMPass());
176 pm.addPass(createConvertToLLVMPass());
177 pm.addPass(createReconcileUnrealizedCastsPass());
178 pm.addNestedPass<gpu::GPUModuleOp>(createCanonicalizerPass());
179 pm.addNestedPass<gpu::GPUModuleOp>(createCSEPass());
180 // XeVM-to-LLVM must be the last pass before gpu-module-to-binary.
181 pm.addNestedPass<gpu::GPUModuleOp>(createConvertXeVMToLLVMPass());
182 // gpu-module-to-binary
183 {
184 GpuModuleToBinaryPassOptions gpuToModuleBinOptions;
185 gpuToModuleBinOptions.compilationTarget = options.binaryFormat;
186 gpuToModuleBinOptions.cmdOptions = options.cmdOptions;
187 pm.addPass(createGpuModuleToBinaryPass(std::move(gpuToModuleBinOptions)));
188 }
189}
190} // namespace
191
194 // Pre-GPU common pipelines.
195 buildPreGPUCommonPassPipeline(pm, options);
196
197 // GPUModule-specific stuff.
198 buildGPUPassPipeline(pm, options);
199
200 // Post-GPU pipeline for both Host and GPU.
201 buildPostGPUCommonPassPipeline(pm, options);
202}
203
206 "gpu-lower-to-xevm-pipeline",
207 "The default GPU to XeVM lowering pipeline. It starts by lowering GPU "
208 "code to the "
209 "specified compilation target (default is fatbin) then lowers the host "
210 "code.",
212}
static llvm::ManagedStatic< PassManagerOptions > options
This class represents a pass manager that runs passes on either a specific operation type,...
Definition PassManager.h:46
void addPass(std::unique_ptr< Pass > pass)
Add the given pass to this pass manager.
Definition Pass.cpp:392
void addNestedPass(std::unique_ptr< Pass > pass)
Add the given pass to a nested pass manager for the given operation kind OpT.
void registerGPUToXeVMPipeline()
void buildLowerToXeVMPassPipeline(OpPassManager &pm, const GPUToXeVMPipelineOptions &options)
Adds the GPU to XeVM pipeline to the given pass manager.
Include the generated interface declarations.
std::unique_ptr< Pass > createCanonicalizerPass(const GreedyRewriteConfig &config, ArrayRef< std::string > disabledPatterns={}, ArrayRef< std::string > enabledPatterns={})
Creates an instance of the Canonicalizer pass with the specified config.
std::unique_ptr< Pass > createConvertVectorToSCFPass(const VectorTransferToSCFOptions &options=VectorTransferToSCFOptions())
Create a pass to convert a subset of vector ops to SCF.
PassPipelineRegistration provides a global initializer that registers a Pass pipeline builder routine...