This is an archive of the discontinued LLVM Phabricator instance.

[mlir][spirv] Memref to SPIRV lowering for OCL
ClosedPublic

Authored by raikonenfnu on Aug 25 2022, 7:02 PM.

Details

Summary

-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.

Diff Detail

Event Timeline

raikonenfnu created this revision.Aug 25 2022, 7:02 PM
raikonenfnu requested review of this revision.Aug 25 2022, 7:02 PM
antiagainst requested changes to this revision.Aug 29 2022, 4:52 PM
antiagainst added inline comments.
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.

This revision now requires changes to proceed.Aug 29 2022, 4:52 PM

Refactored code to address issues.

raikonenfnu edited the summary of this revision. (Show Details)

minor clean up

another minor clean up

how does this intercept the ongoing work with extract_strided_metadata ?

how does this intercept the ongoing work with extract_strided_metadata ?

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.

how does this intercept the ongoing work with extract_strided_metadata ?

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 ).

antiagainst added a comment.EditedSep 19 2022, 9:02 AM

how does this intercept the ongoing work with extract_strided_metadata ?

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.)

antiagainst accepted this revision.Sep 19 2022, 9:12 AM

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 revision is now accepted and ready to land.Sep 19 2022, 9:12 AM

fix styling nits

antiagainst accepted this revision.Sep 19 2022, 10:14 AM
This revision was landed with ongoing or failed builds.Sep 19 2022, 10:24 AM
This revision was automatically updated to reflect the committed changes.