This is an archive of the discontinued LLVM Phabricator instance.

[MLIR][SPIRVToLLVM] Conversion of SPIR-V array, runtime array, pointer and struct types to LLVM dialect.
AbandonedPublic

Authored by georgemitenkov on Jul 1 2020, 3:20 AM.

Details

Summary

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.

Diff Detail

Event Timeline

georgemitenkov created this revision.Jul 1 2020, 3:20 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 1 2020, 3:20 AM
ftynse added inline comments.Jul 1 2020, 3:33 AM
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?

rriddle added inline comments.Jul 1 2020, 1:50 PM
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.

ftynse added inline comments.Jul 2 2020, 1:23 AM
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]> ?

georgemitenkov marked an inline comment as done.Jul 2 2020, 3:41 AM
georgemitenkov added inline comments.
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.

georgemitenkov marked an inline comment as done.Jul 2 2020, 3:46 AM
georgemitenkov added inline comments.
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
70

I will put some comments in the code and create a markdown in a separate patch then.

ftynse added inline comments.Jul 2 2020, 3:46 AM
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.

georgemitenkov added inline comments.Jul 2 2020, 5:12 AM
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.

georgemitenkov updated this revision to Diff 275072.EditedJul 2 2020, 5:24 AM
  • [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.

antiagainst requested changes to this revision.Jul 2 2020, 11:48 AM
antiagainst added inline comments.
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.)

This revision now requires changes to proceed.Jul 2 2020, 11:48 AM
georgemitenkov marked 9 inline comments as done.
  • [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:

  1. Array conversions return null if type.getArrayStride() == 0 is not satisfied.
  2. 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.
antiagainst requested changes to this revision.Jul 7 2020, 7:21 PM
antiagainst added inline comments.
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.

This revision now requires changes to proceed.Jul 7 2020, 7:21 PM
georgemitenkov added a comment.EditedJul 8 2020, 7:54 AM

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
georgemitenkov abandoned this revision.Jul 10 2020, 6:14 AM