-Add awareness to Kernel vs Shader capability for memref to spv lowering.
-Add lowering using spv.PtrAccessChain
-Enable lowering from scalar pointee types for kernel capabilities.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h | ||
---|---|---|
67 | This should not be in Options. Options allows a user to control how the type converter works. Whether we have kernel capability is not something a user can control; it is a characteristic of the target environment. We should actually expose a getter method in the SPIRVTypeConverter to return the targetEnv to allow calling its allows(spirv::Capabilty) method. This is also generic enough to avoid special casing Kernel capabilities. | |
172 | Hmm, I think we can fold the different code path selection for Vulkan and OpenCL inside the existing entry point getElementPtr. Under the hood we call into getVulkanElementPtr (which is the existing getElementPtr impl) and getOpenCLElementPtr, depending on whether allows(spirv::Capability::Kernel). The benefits of doing this is that we don't need duplicating all the patterns for Vulkan and OpenCL. (I know I said it's preferable to have separate parallel patterns; but here we are seeing too much similar code duplication across many patterns. Unifying the different part behind a common helper function is better.) | |
mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp | ||
581 | This is not the proper way to add patterns. Patterns should be safe to be _populated_ no matter what target environment we have. See my previous comments regarding how to have the kernel capability probing and selection logic inside getElementPtr. | |
mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp | ||
341 | This should query spirv::TargetEnv::allows(spirv::Capability::Kernel). Also please put some comments before saying " For OpenCL Kernel we can just emit a pointer pointing to the element." and after saying " For Vulkan we need extra wrapping struct and array to satisfy interface needs." | |
406 | Similarly here. | |
435 | This is not the proper way. Options are for user controls. It is different from target environment. |
Hey Nicolas, I am not too familiar with the ongoing work with extract_strided_metadata, however, this current patch is just to check if the spirv is of kernel flavor and introducing the usage and correct accessing (spv.ptrAccessChain) of spv.ptr<ElemType> rather than (spv.AccessChain) + spv.ptr<spv.struct<spv.array<elementType>>> which is needed for vulkan/shader type.
Since the other logic is not really touched I assume the works being done in extract_strided_metadata that's made to fit the current pipeline(vulkan/shader only) can also be used by (ocl/kernel) after this patch lands.
SGTM, I just wanted to attract your collective attention on that line of work that may be useful for SPIRV too.
I do not have deep SPIRV knowledge myself but the descriptor being only unpacked at the level of LLVM was/is a common problem that we are addressing actively.
The logic that creates spv.IMul spv.IAdd spv.PtrAccessChain and friends should also benefit from the new patterns we are adding (cc @qcolombet ).
Thanks for the heads up, @nicolasvasilache ! Yup, memref.extract_strided_metadata would certainly help the spirv path! Unlike llvm, we don't have the flexibility to always represent memref descriptors as structs inside spirv (spirv is used for various client APIs with different capabilities; not all client API or target environment supports such structs. Notably vulkan by default does not.) So on the spirv path we "linearize" the n-D memref descriptor first before converting to spirv. With memref.extract_strided_metadata that would be easier given now we can use that op first and relying on simple arith op lowering afterwards, instead of baking the logic under converting memref.load/memref.store!
I'll convert spirv side to use it later afterwards, which should handle both vulkan and opencl side. (converting to OpAccessChain or OpPtrAccessChain for vulkan/opencl is later to that; so should be orthogonal.)
Cool, overall LGTM; just a few remaining nits. Thanks! :)
mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h | ||
---|---|---|
162 | Nit: In comment please write as "SPIR-V", as that's the official spelling of it. (In code we cannot because of the -, but in comment we don't subject to this restriction.) | |
167 | Same here. | |
mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp | ||
322 | Just use Value here to be clear. | |
362 | ... unsupported for Kernel capability / spv.PtrAccessChain. | |
363 | Style: no need to use { ... } for trivial if conditions. | |
367 | We can write as accessChain.getDefiningOp<spirv::AccessChainOp>(). | |
449 | Value here. | |
490 | Same here. | |
mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp | ||
342 | No {...} here. | |
407 | Same here. |
This should not be in Options. Options allows a user to control how the type converter works. Whether we have kernel capability is not something a user can control; it is a characteristic of the target environment.
We should actually expose a getter method in the SPIRVTypeConverter to return the targetEnv to allow calling its allows(spirv::Capabilty) method. This is also generic enough to avoid special casing Kernel capabilities.