-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[mlir] Prepare convert-gpu-to-spirv for OpenCL support #69941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
7ca3f97
02ff96c
561af5d
6417cb7
d73edae
57c0d76
4241a60
7f0efa4
dfb3fcb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
#include "mlir/Conversion/FuncToSPIRV/FuncToSPIRV.h" | ||
#include "mlir/Conversion/GPUToSPIRV/GPUToSPIRV.h" | ||
#include "mlir/Conversion/MemRefToSPIRV/MemRefToSPIRV.h" | ||
#include "mlir/Dialect/Func/IR/FuncOps.h" | ||
#include "mlir/Dialect/GPU/IR/GPUDialect.h" | ||
#include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h" | ||
#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h" | ||
|
@@ -54,22 +55,52 @@ void GPUToSPIRVPass::runOnOperation() { | |
|
||
SmallVector<Operation *, 1> gpuModules; | ||
OpBuilder builder(context); | ||
|
||
auto targetEnvSupportsKernelCapability = [](gpu::GPUModuleOp moduleOp) { | ||
Operation *gpuModule = moduleOp.getOperation(); | ||
auto targetAttr = spirv::lookupTargetEnvOrDefault(gpuModule); | ||
spirv::TargetEnv targetEnv(targetAttr); | ||
return targetEnv.allows(spirv::Capability::Kernel); | ||
}; | ||
|
||
module.walk([&](gpu::GPUModuleOp moduleOp) { | ||
// Clone each GPU kernel module for conversion, given that the GPU | ||
// launch op still needs the original GPU kernel module. | ||
builder.setInsertionPoint(moduleOp.getOperation()); | ||
// For Vulkan Shader capabilities, we insert the newly converted SPIR-V | ||
// module right after the original GPU module, as that's the expectation of | ||
// the in-tree Vulkan runner. | ||
// For OpenCL Kernel capabilities, we insert the newly converted SPIR-V | ||
// module inside the original GPU module, as that's the expectaion of the | ||
// normal GPU compilation pipeline. | ||
if (targetEnvSupportsKernelCapability(moduleOp)) { | ||
builder.setInsertionPoint(moduleOp.getBody(), | ||
moduleOp.getBody()->begin()); | ||
} else { | ||
builder.setInsertionPoint(moduleOp.getOperation()); | ||
} | ||
gpuModules.push_back(builder.clone(*moduleOp.getOperation())); | ||
}); | ||
|
||
// Run conversion for each module independently as they can have different | ||
// TargetEnv attributes. | ||
for (Operation *gpuModule : gpuModules) { | ||
spirv::TargetEnvAttr targetAttr = | ||
spirv::lookupTargetEnvOrDefault(gpuModule); | ||
|
||
// Map MemRef memory space to SPIR-V storage class first if requested. | ||
if (mapMemorySpace) { | ||
spirv::TargetEnv targetEnv(targetAttr); | ||
FailureOr<spirv::MemoryModel> memoryModel = | ||
spirv::getMemoryModel(targetEnv); | ||
if (failed(memoryModel)) | ||
return signalPassFailure(); | ||
|
||
std::unique_ptr<ConversionTarget> target = | ||
spirv::getMemorySpaceToStorageClassTarget(*context); | ||
spirv::MemorySpaceToStorageClassMap memorySpaceMap = | ||
spirv::mapMemorySpaceToVulkanStorageClass; | ||
(memoryModel == spirv::MemoryModel::OpenCL) | ||
? spirv::mapMemorySpaceToOpenCLStorageClass | ||
: spirv::mapMemorySpaceToVulkanStorageClass; | ||
spirv::MemorySpaceToStorageClassConverter converter(memorySpaceMap); | ||
|
||
RewritePatternSet patterns(context); | ||
|
@@ -79,7 +110,6 @@ void GPUToSPIRVPass::runOnOperation() { | |
return signalPassFailure(); | ||
} | ||
|
||
auto targetAttr = spirv::lookupTargetEnvOrDefault(gpuModule); | ||
std::unique_ptr<ConversionTarget> target = | ||
SPIRVConversionTarget::get(targetAttr); | ||
|
||
|
@@ -108,6 +138,25 @@ void GPUToSPIRVPass::runOnOperation() { | |
if (failed(applyFullConversion(gpuModule, *target, std::move(patterns)))) | ||
return signalPassFailure(); | ||
} | ||
|
||
// For OpenCL, the gpu.func op in the original gpu.module op needs to be | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this gpu.func->func.func necessary? Can you just keep the original gpu.func instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keeping the original gpu.func causes legality check error later in the gpu compile pipeline. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the problem is, the lack of spirv support in gpu dialect. For example, gpu.func needs to be able to wrap spirv.func so gpu-to-llvm pass (for the host code) can properly handle the relation between gpu.launch_func and spirv.func. |
||
// replaced with an empty func.func op with the same arguments as the gpu.func | ||
// op. The func.func op needs gpu.kernel attribute set. | ||
module.walk([&](gpu::GPUModuleOp moduleOp) { | ||
if (targetEnvSupportsKernelCapability(moduleOp)) { | ||
moduleOp.walk([&](gpu::GPUFuncOp funcOp) { | ||
builder.setInsertionPoint(funcOp); | ||
auto newFuncOp = builder.create<func::FuncOp>( | ||
funcOp.getLoc(), funcOp.getName(), funcOp.getFunctionType()); | ||
auto entryBlock = newFuncOp.addEntryBlock(); | ||
builder.setInsertionPointToEnd(entryBlock); | ||
builder.create<func::ReturnOp>(funcOp.getLoc()); | ||
newFuncOp->setAttr(gpu::GPUDialect::getKernelFuncAttrName(), | ||
builder.getUnitAttr()); | ||
funcOp.erase(); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
} // namespace | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we can also use the above
targetEnvSupportsKernelCapability
no? Something like:spirv::MemorySpaceToStorageClassMap memorySpaceMap = targetEnvSupportsKernelCapability(gpuModule) ? ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.