This change adds initial support needed to generate OpenCL compliant SPIRV.
If Kernel capability is declared then memory model becomes OpenCL.
If Addresses capability is declared then addressing model becomes Physical64.
Additionally for Kernel capability interface variable ABI attributes are not
generated as entry point function is expected to have normal arguments.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
THanks! This is very welcome addition. Just a few minor comments below.
I am wondering if the Addresses capability should be done here. In general we have assumed that addressing mode is 32-bit, i.e. indexType is lowered to i32 in the SPIRVTypeConverter. We should make it 64 bits if the capability exists. It should then use 64-bit indexing out of the box, but that is untested. So seems like there is some work to be done on that aspect. The rest of the change seems unrelated.
Broader question though. RIght now there is an mlir-vulkan-runner that takes the generated SPIR-V binary and runs it to make sure the generated binary is correct. This also means that it is validated. There is no direct way of validating SPIR-V binary in MLIR tree, but wondering if you have used such a validation tool on the generated SPIR-V binary with Kernel capabilities?
mlir/test/Conversion/GPUToSPIRV/test_opencl_spirv.mlir | ||
---|---|---|
30 ↗ | (On Diff #282871) | Nit: Please address missing newline at end of file. |
Awesome, great to see that you are interested in bring up the OpenCL conversion path! :)
+1. Overall I'd suggest to have a central place to host this target execution environment related information. For example, add a new ExecutionEnvironment.{h|cpp} or something to have utility functions returning the addressing/memory/execution/etc. model. This way it avoids scattering such information in all the patterns and it's a better separation of concerns I think.
In general we have assumed that addressing mode is 32-bit, i.e. indexType is lowered to i32 in the SPIRVTypeConverter. We should make it 64 bits if the capability exists. It should then use 64-bit indexing out of the box, but that is untested. So seems like there is some work to be done on that aspect. The rest of the change seems unrelated.
+1. Good point Mahesh. I think the type converter should have access to the target env, so it can change to emit a different bitwidth for index if that's desired. It shouldn't be too hard but I guess there are places we are assuming 32-bit as pointed by Mahesh and that needs to be fixed. It can happen as a next step though.
mlir/lib/Dialect/SPIRV/Transforms/LowerABIAttributesPass.cpp | ||
---|---|---|
245 | This seems a bit reversed. I think we should look into avoiding generating the ABI attributes in the first place if they are not useful? |
Separated functions to query execution environment related information
into ExecutionEnvironment{.h,.cpp}.
Removed generation of spv.interface_var_abi if it's not needed.
Fixed missing newline.
@mravishankar @antiagainst
Thank you for the reviews, I have made some changes addressing your comments.
This is a part of upstreaming PlaidML required changes from https://github.com/plaidml/plaidml/pull/1237. I am currently working on adding OpenCL+SPIRV path there and I have managed to get full pipeline, including kernel compilation, working.
There are still some issues with extended set of instructions that I'm planning to look at later.
Do you think it may be useful to consider adding similar mlir-opencl-runner in the future?
I was looking at both Addresses and Kernel capabilities together, because they are both required to make the binary compile. Do you think I should split Addresses into separate change?
Agree, but if it's not a problem, I'd like to do this in separate change. It's currently not required to compile generated SPIR-V.
There is also the issue of selecting between Physical32 vs Physical64 and I have no idea how to select between those. Seems to me that spv.target_env may need some additional field, but I was little worried about breaking compatibility with other projects.
I think that would be very useful and a good way to make sure as we add OpenCL features we dont regress on Vulkan support. We heavily use Vulkan within IREE, so if something breaks they will show up there (cause of more extensive testing there). There are some mlir-vulkan-runner tests that will gives basic functionality testing. But having an OpenCL runner will provide the same stability for Compute capabilities, i.e. make sure that the OpenCL support doesnt regress with changes that are meant for Vulkan. Since there is no "in-tree" verifier, having a runner would be the best way to hook that up.
I was looking at both Addresses and Kernel capabilities together, because they are both required to make the binary compile. Do you think I should split Addresses into separate change?
I think now the change looks better to me. So I just have a few more comments, and it should be fine to land.
Agree, but if it's not a problem, I'd like to do this in separate change. It's currently not required to compile generated SPIR-V.
There is also the issue of selecting between Physical32 vs Physical64 and I have no idea how to select between those. Seems to me that spv.target_env may need some additional field, but I was little worried about breaking compatibility with other projects.
spv.target_env definitely needs more attributes. With the mlir-vulkan-runner we get some basic level of testing. Completely fine with looking into this in a separate change.
mlir/include/mlir/Dialect/SPIRV/ExecutionEnvironment.h | ||
---|---|---|
22 ↗ | (On Diff #283195) | Mostly nit: If you just include SPIRVTypes.h you will get the enum definitions. THis is fine as well, so do not have strong opinion on this. |
31 ↗ | (On Diff #283195) | I think we just use Optional<...> in MLIR AFAIK. |
38 ↗ | (On Diff #283195) | I think most of these functions can go into TargetAndABI.h ? |
mlir/lib/Dialect/SPIRV/ExecutionEnvironment.cpp | ||
20 ↗ | (On Diff #283195) | I think most of these can go into TargetAndABI.cpp? |
23 ↗ | (On Diff #283195) | Maybe add a TODO here to say that the Physical64 is being hard-wired here, but it should really come from the TargetEnvAttr itself. |
mlir/include/mlir/Dialect/SPIRV/ExecutionEnvironment.h | ||
---|---|---|
31 ↗ | (On Diff #283195) | I'm not sure about this, FailureOr<...> is defined inside MLIR, so if it's not used shouldn't it be removed? |
38 ↗ | (On Diff #283195) | Sure, looks like a fitting place to host these functions. |
mlir/include/mlir/Dialect/SPIRV/ExecutionEnvironment.h | ||
---|---|---|
31 ↗ | (On Diff #283195) | I got confused with something else (which I though was from core LLVM). I am not totally opposed to it, but its not used at all in the SPIR-V dialect. I think Optional is more consistent. |
38 ↗ | (On Diff #283195) | I think it is OK to move it there. |
Addressed review comments.
Minor style fixes - added explicit types if they don't hurt readability.
mlir/include/mlir/Dialect/SPIRV/ExecutionEnvironment.h | ||
---|---|---|
31 ↗ | (On Diff #283195) | FailureOr is more recent, and should be used when it is more readable than Optional. This is a similar situation to why LogicalResult is preferred over bool. |
mlir/test/Conversion/GPUToSPIRV/test_opencl_spirv.mlir | ||
---|---|---|
11 ↗ | (On Diff #283678) | Forgot to mention this, but could you refactor the CHECK* lines a bit. It is more readable IMO if you group all the CHECK statements together and insert spaces to
So // CHECK-LABEL: func @foo // CHECK-SAME: %[[ARG0:.*]] // CHECK: %[[T0:.*]] = |
Addressed comments.
Refactored not needed CHECKs in .mlir tests.
Brought back FailureOr, as per comment it is preferred over Optional.
@mravishankar @antiagainst
I think I addressed all the comments.
If you think the change is still good as is, could you commit on my behalf? I don't have commit access.
Name and email: Konrad Dobros <konrad.dobros@intel.com>
... whether the given SPIR-V target ..