This is an archive of the discontinued LLVM Phabricator instance.

[mlir][spirv] Add MatrixTimesScalar operation
ClosedPublic

Authored by Hazem on Jun 11 2020, 11:27 AM.

Details

Summary
  • Define the MatrixTimesScalar operation and add roundtrip tests.
  • Added a new base class for matrix-specific operations to avoid invalid operands type mismatch check.
  • Created a separate Matrix arithmetic operations td file to add more operations in the future.
  • Augmented the automatically generated verify method to print more fine-grained error messages.
  • Made minor Updates to the matrix type tests.

Diff Detail

Event Timeline

Hazem created this revision.Jun 11 2020, 11:27 AM
Hazem updated this revision to Diff 270194.Jun 11 2020, 11:50 AM
  • remove unintentionally added include line
antiagainst requested changes to this revision.Jun 12 2020, 4:01 PM

Thanks @Hazem! A few nits.

mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
3001

Could you keep this alphabetically sorted?

3029

Same here.

mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
2

Nit: align to 80 characters

19

Could you keep each line wrapped to 80 characters?

23

This isn't correct actually? I think we need two different operand types because for example for OpMatrixTimesScalar the second operand should be a scalar type? This is actually not needed given in the following you override with explicit arguments and results. We can just remove this and derive from SPV_Op.

47

Could you keep each line wrapped to 80 characters?

55

Same here

70

Actually we can have just one matrix type given that the input and result are the same and the scalar's type can be deduced from it. If you'd like to handle it later a TOOD here would be nice.

mlir/test/Dialect/SPIRV/Serialization/matrix.mlir
11

This should match with the function name.

18

Same here.

29

Why adding this? Seems unrelated..

This revision now requires changes to proceed.Jun 12 2020, 4:01 PM
Hazem marked 12 inline comments as done.Jun 15 2020, 11:10 AM
Hazem added inline comments.
mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
23

The comment about similar operands was a copy paste error. Thanks for SPV_Op hint, I thought we need to group arithmetic ops under SPV_ArithmeticOps class by any means. Fixed it now, and all subsequent matrix ops will follow the same pattern if possible.

70

I am still trying to understand how the Op declarative form work, so let's say I change this line to only have the input Matrix type, then I get the following error:

"error: type of operand #1, named 'scalar', is not buildable and a buildable type cannot be inferred"

The same happens for result/matrix as well. I looked in the documentation and my understanding is that I need to inherit from BuildableType class for these variables types. Is that correct? Because otherwise I already set a type constraint for each of them as ins/outs.

I couldn't find SPIRV examples using assembly format definition (except cooperative matrix), and the documentation is somewhat lacking diverse examples. I could use a custom printer/parser but I wanted to leverage the auto-gen feature as it is more concise, representative, and easier to update, if needed, in the future.

Please if you have hints/docs on what needs to be done to get this right send me and I will work on it. I believe this will be beneficial as I plan to add the rest of the matrix-related Ops after this patch.

mlir/test/Dialect/SPIRV/Serialization/matrix.mlir
29

This and the next two are minor re-naming of matrix tests, should they be separated in a different patch?

Hazem marked 3 inline comments as done.Jun 15 2020, 11:13 AM
Hazem added inline comments.
mlir/test/Dialect/SPIRV/Serialization/matrix.mlir
29

Removed them as unneeded.

Hey @Hazem , did you forget to push new changes? I'm still seeing the old commits.

mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

Documentation for the Declarative Assembly Format is at here: https://mlir.llvm.org/docs/OpDefinitions/#declarative-assembly-format. It's a bit opaque as you said, similar like other declarative mechanisms because the goal is to be a high-level description so by nature it is inevitably terse. :) At the moment a good way to understand is to search the codebase and find other examples.

I don't think you can express the relationship that $scalar is of a type that is the same as the element type of $matrix. So pretty much it means manually defining a parser/printer.. So if you'd like to avoid that for now, it's fine for me with just a TODO here so we can remind ourselves later. :)

rriddle added inline comments.Jun 15 2020, 1:51 PM
mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

If the type of $scalar is the element type of something else, you can use a trait for that. TypesMatchWith in this case:

https://github.com/llvm/llvm-project/blob/13331477c0d1aeb8f3c9f24b3d0487bc6fcaa225/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td#L1028

You can find many other usages in that file.

Hazem updated this revision to Diff 270940.Jun 15 2020, 6:51 PM
  • address revision comments
Hazem marked an inline comment as done.EditedJun 15 2020, 6:53 PM

[Edit] I believe this patch will crash the build if D81763 is committed to master before it, due to accesschain tests format change. So once D81763 is committed, I can update this patch to reflect the format changes before committing it.

Hey @Hazem , did you forget to push new changes? I'm still seeing the old commits.

I was reluctant to add a TODO versus actually implementing the change. I went for a TODO for now. Might revisit it later. I pushed the changes now. Sorry for the confusion.

Hazem marked an inline comment as done.Jun 15 2020, 6:54 PM
Hazem added inline comments.
mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

The $scalar is the element type of an element type.

For example:
Scalar is f16 when

float16 is the element type of Vector, and this Vector is the element type of a Matrix. So, one more level of nesting.

rriddle added inline comments.Jun 16 2020, 12:07 AM
mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

The level of nesting doesn't matter. All that matters is that you can transform one type to get the other. As long as there is a translation from A->B that doesn't require external information, you can represent it using TypesMatchWith.

Hazem marked an inline comment as done.Jun 16 2020, 10:04 AM
Hazem added inline comments.
mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

I see. Is it a good practice in this case to do something like that in the transformation:

"$_self.cast<MatrixType>().getElementType().cast<VectorType>().getElementType()"

If yes, wouldn't this cause issues if the matrix element type is not a valid vector type?

rriddle added inline comments.Jun 16 2020, 10:09 AM
mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

It's fine as long as you ensure that the matrix type is verified to have a vector element type before hand(i.e. via the type constraint). This is good practice in general though. The type constraint for $matrix(or whatever the matrix type is) should be as complete as possible. The declarative parser will use the type constraint to verify the type before applying the transformation.

Hazem marked 2 inline comments as done.Jun 16 2020, 10:31 AM
Hazem added inline comments.
mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

Makes sense. Thank you!

antiagainst accepted this revision.Jun 17 2020, 2:53 PM
antiagainst marked an inline comment as done.

LGTM!

mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td
70

Yes. What River said. Sorry I didn't track all the nice progress there so I wasn't aware it's possible now. :)

This revision is now accepted and ready to land.Jun 17 2020, 2:53 PM
Hazem marked an inline comment as done.Jun 17 2020, 3:21 PM

LGTM!

Excellent, I was granted commit access today, should I go ahead and land this one?

This revision was automatically updated to reflect the committed changes.