This patch adds type conversion for 4 SPIR-V types: array, runtime array, pointer and struct. This conversion is integrated using a separate function populateSPIRVToLLVMTypeConversion() that adds new type conversions. At the moment, this is a basic skeleton that allows to perfom some basic conversion from SPIR-V to LLVM. There is no support of array strides, struct offset and member decorations, as well as of storage classes. I think that these will be supported on the case by case basis.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | ||
---|---|---|
491 | I'm slightly concerned about this capturing typeConverter reference, even though the lambda is stored into the typeConverter itself so the lifetime is fine. @rriddle anything we can do for type conversions that require recursive calls into the type conversion infra without exposing such things to the user? |
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | ||
---|---|---|
491 | Capturing the reference is fine so long as we make TypeConverter non-copyable. I don't think it is right now, but that seems like a fine trade-off IMO. |
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | ||
---|---|---|
70 | Please add some documentation for top-level functions. In general, I think it would be useful to also have a document like https://mlir.llvm.org/docs/ConversionToLLVMDialect/ (feel free to rename that document to something that mentions it's only for the standard dialect) that explains the SPIRV-to-LLVM conversion on the high level. For example, type conversion rules. | |
mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir | ||
42 | How would this work for offsets that are not equal to cumulative size of the previous struct elements, e.g. <f32 [0], i32 [8]> ? |
mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir | ||
---|---|---|
42 | This is not supported yet, although some padding fields can be inserted to emulate the offset in my opinion. |
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | ||
---|---|---|
70 | I will put some comments in the code and create a markdown in a separate patch then. |
mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir | ||
---|---|---|
42 | Not supported in the conversion, or in the SPIRV dialect? If only in the conversion, I'd suggest to add a check for that and fail the conversion. LLVM IR can also pad structures, e.g., {i8, i32} will likely have 3 pad bytes between the elements; a packed structure, <{i8, i32}>, won't. |
mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir | ||
---|---|---|
42 | In the conversion. SPIR-V actually allows struct members to have offsets that are more than the the size of previous elements (even though it is not a common case as far as I know). |
- [MLIR][SPIRVToLLVM] Added comments to type conversion functions and refactored struct conversion
- [MLIR][SPIRVToLLVM] Refactored the code to follow clang style
Added comments to document type conversion functions. This indicates what is currently supported.
Refactored convertStructType() to only handle structs with no offset. They will be mapped to packed structs. The case when structs have offset will be a separate case (either inserting extra padding or keeping the offset as sizeof(previous elements)) and will be implemented shortly.
- [MLIR][SPIRVToLLVM] Added missing tests for packed struct
Since struct with no offset are modelled as packed structs, the test had to be updated to reflect this change.
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | ||
---|---|---|
70 | +1. Thanks for the great point, @ftynse! We should have such a doc. Apart from being generally useful for understanding the logic and code, it could also be a nice artifact of the GSOC project itself. | |
85 | Should return null type if type.getArrayStride() != 0 to indicate that's not supported. | |
105 | Same here. Check to reject unsupported cases. | |
115 | I think we should check and return null type to indicate not supported case here. The assert can happen in convertStructTypePacked. It's a subtle difference but generally asserts means we are seeing unexpected input in an API and the programmer is breaking preconditions, which is the case for convertStructTypePacked. For convertStructType, all sorts of struct types should be expected input; it's just that we are not handling them yet. So return naturally to indicate an error would be nice than abort abruptly only under debug mode. | |
mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir | ||
42 | We should check and return failure during conversion for the unsupported case. Type conversion is quite fundamental to dialect conversion and the infrastructure is quite involved on this front; so being explicit (and verbose) to reject unsupported case can be quite helpful for development. And we should also have negative tests here that check we do nothing for types with offsets. (As a background: SPIR-V struct types with explicit layout is really for kernel-runtime ABI. And normally you can expect the data are stored in buffers tightly so each element is having natural size and alignment. Most of the time we just see explicit layout like that, esp. for ML I think. But there indeed exist cases where we want to place data differently. It can happen in graphics world, which is not in the GSOC's scope here.) |
- [MLIR][SPIRVToLLVM] Added conversion for naturally padded structs
- [MLIR][SPIRVToLLVM] Added alignment in struct conversion pattern
- [MLIR][SPIRVToLLVM] Added comments to padded struct conversion
- [MLIR][SPIRVToLLVM] Refactored the code to follow clang style
Addressed comments:
- Array conversions return null if type.getArrayStride() == 0 is not satisfied.
- Struct type conversion is now splitted in two. It can be converted to a packed struct if there is no offset. If there is an offset, then a check if the offsets are "natural" is performed. At the moment, struct with offset conversion supports scalars, pointers and arrays as its members. I also added tests that indicate a failure of conversion.
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | ||
---|---|---|
70 | I think you can do for (Type elementType : type.getElementTypes) or llvm::map_range(type.getElementTypes(), [...](...) { ... }) here? | |
91 | I feel this is dense logic that worth some more testing and it's better to have a separate commit for it. Could you split this case out? | |
98 | typo: butes | |
102 | Ah, the cast<spirv::SPIRVType> part is annoying. I think we should actually change spirv::StructType's APIs to return SPIRVType instead of Type and hide this inside the APIs, given a SPIR-V struct can only contain SPIR-V types for sure. |
I will split this review in 2 new revisions:
- Adds array. runtime array and pointer conversion
- Adds struct conversion without offset
- Support of structs with natural offset
Please add some documentation for top-level functions.
In general, I think it would be useful to also have a document like https://mlir.llvm.org/docs/ConversionToLLVMDialect/ (feel free to rename that document to something that mentions it's only for the standard dialect) that explains the SPIRV-to-LLVM conversion on the high level. For example, type conversion rules.