This is an archive of the discontinued LLVM Phabricator instance.

[MLIR] Add mlir::TypedValue
ClosedPublic

Authored by Tyker on Aug 16 2022, 9:50 PM.

Details

Summary

mlir::TypedValue is a wrapper class for mlir::Values with a known type
getType will return the known type and all assignments will be asserted
Also the tablegen Operation generator was adapted to use mlir::TypedValue
when appropriate
If an op can only take one type for a specific fields, getting this field
will return a TypedValue of the correct type. so there is no need to cast the type.
I also think TypedValue can be a useful to express directly what an API is expecting or providing
and remove the need for to cast the return of .getType() its Values when using that API.

for example:

/// expressed directly in the API that that the parameter should be a Value of IntegerType.
/// And the return will still be of IntegerType.
TypedValue<IntegerType> maybeCast(TypedValue<IntegerType> )

Value v;
auto v2 = maybeCast(v) /// asserts that the Type is IntergerType
assert(v2.getType().getWidth() == 8); /// no need to do .cast<IntegerType>()

/// Assuming MyOp is defined to operate on TensorType exclusively
MyOp.getLHS().getType() // is a TensorType

/// Not just for APIs
Value getValue()

/// express directly that the expected type of v is IntegerType
TypedValue<IntegerType> temporary = getValue()

/// express that this should only store Values of type IntegerType
DenseMap<mlir::Operations*, TypedValue<IntegerType>>

Diff Detail

Event Timeline

Tyker created this revision.Aug 16 2022, 9:50 PM
Tyker requested review of this revision.Aug 16 2022, 9:50 PM
Tyker edited the summary of this revision. (Show Details)Aug 16 2022, 9:57 PM

Can you elaborate more on the motivation in the description?
Right now you're touching on it with:

I also think TypedValue can be a useful as to express directly what is expected and remove the need for to cast its Values.

But I'm not sure what you mean, if you could also add examples of what kind of API would take advantage of this?

mehdi_amini added inline comments.Aug 17 2022, 3:31 AM
mlir/include/mlir/IR/Value.h
423

Nit: "checked" -> "asserted", there won't be any check in non-assert build.

Tyker edited the summary of this revision. (Show Details)Aug 17 2022, 8:41 AM
Tyker edited the summary of this revision. (Show Details)

Can you elaborate more on the motivation in the description?
Right now you're touching on it with:

I also think TypedValue can be a useful as to express directly what is expected and remove the need for to cast its Values.

But I'm not sure what you mean, if you could also add examples of what kind of API would take advantage of this?

I added a few examples.

Tyker edited the summary of this revision. (Show Details)Aug 17 2022, 8:42 AM
Tyker edited the summary of this revision. (Show Details)

How many places in-tree would benefit from this? It's hard to gauge what the value of this is from the patch as-is.

mlir/include/mlir/IR/Value.h
425

The ValueClass is never anything other than Value, why have this as a template arg?

456–467

Why not just use std::conditional_t?

mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
1158–1162

This should be the expected state of ODS (having qualified types), we shouldn't guard against this ever.

assert(v2.getType().getWidth() == 8); /// no need to do .cast<IntegerType>()

/// Assuming MyOp is defined to operate on TensorType exclusively
MyOp.getLHS().getType() // is a TensorType

Ah I like this! The API is indeed quite nice when getType does not need to be casted... So I'm supportive here if River is as well :)

(You have a typo in multiple place you wrote IntergerType)

Tyker edited the summary of this revision. (Show Details)Aug 17 2022, 6:19 PM
Tyker updated this revision to Diff 453505.Aug 17 2022, 6:28 PM
Tyker marked 3 inline comments as done.

How many places in-tree would benefit from this? It's hard to gauge what the value of this is from the patch as-is.

When ever an operand of an op can operate on only one type. this helps by removing the need for casting the result of getType
a build of all the in-tree dialects with the patch emits 6413 TypedValue with 3657 being TypedValue<Type>, so 42% of operand have a known type

mlir/include/mlir/IR/Value.h
425

This was originally to support other Kinds of Value, like TypedValue<IntergerType, BlockArgument>. but it is rare (at least for me) to cast between Values so I removed it.

456–467

yes it is simpler

mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
1158–1162

I agree that it shouldn't happen. but during testing I found it happens. so this protection is needed. at least until the places where types are not fully qualified become fully qualified.

tablegen should check that the provided type string are fully qualified types (starting with "::").
after looking into it pdl::OperationType seems to be the only type that is causing issues. but I didn't find a way to fix it.

example:

/home/tyker/opensource/llvm-project/build-release/tools/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h.inc:945:22: error: unknown type name 'OperationType'; did you mean 'pdl::OperationType'?
  ::mlir::TypedValue<OperationType> getOperand();
                     ^~~~~~~~~~~~~
                     pdl::OperationType
Tyker added a comment.Aug 17 2022, 6:30 PM
assert(v2.getType().getWidth() == 8); /// no need to do .cast<IntegerType>()

/// Assuming MyOp is defined to operate on TensorType exclusively
MyOp.getLHS().getType() // is a TensorType

Ah I like this! The API is indeed quite nice when getType does not need to be casted... So I'm supportive here if River is as well :)

:)

(You have a typo in multiple place you wrote IntergerType)

The description was updated sorry for the typos

rriddle requested changes to this revision.Aug 22 2022, 1:06 AM
rriddle added inline comments.
mlir/include/mlir/IR/Value.h
422–424

Can you reflow these comments?

430

This assert doesn't look useful, this should be statically guaranteed by the fact that the argument of the function is already Ty.

437–440

Is this used anywhere? Why not force the user to cast the Value before assignment?

483–487
mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
1158–1162

Can you file an issue for this and add a link here? We ideally shouldn't be baking in checks for things we consider bugs.

1387–1388
This revision now requires changes to proceed.Aug 22 2022, 1:06 AM
Tyker updated this revision to Diff 454540.Aug 22 2022, 9:24 AM
Tyker marked 7 inline comments as done.
Tyker added inline comments.
mlir/include/mlir/IR/Value.h
430

Yeah, setType should be taking an mlir::Type and checking it.

437–440

This is here if someone wants to store a TypedValue somewhere. which can happens by default when auto.

mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
1158–1162
rriddle accepted this revision.Aug 24 2022, 2:45 AM

LGTM in general, but I'd like comments addressed first.

mlir/include/mlir/IR/Value.h
437–440

This breaks away from the precedent set everywhere else, how annoying is it to remove this?

mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
1158–1162

Can you link to it in a comment?

This revision is now accepted and ready to land.Aug 24 2022, 2:45 AM
Tyker marked an inline comment as done.EditedAug 24 2022, 9:02 AM
This comment has been deleted.
mlir/include/mlir/IR/Value.h
437–440

It is cheap to remove this since there is only one failure in the upstream MLIR.
what precedent does it break away from ? not overloading operator= ?

I am not sure if it should be removed anyway. because removing this would limit TypedValue variables or containers which I think can be useful. now if you think TypedValue variables should be discouraged. I can remove support for it.

Tyker updated this revision to Diff 455248.Aug 24 2022, 9:13 AM
mscuttari added inline comments.
mlir/include/mlir/IR/Value.h
434

This is making the lookup method of BlockAndValueMapping to crash when the input is a TypedValue with a type different from the mapped value. The Ty template becomes TypedValue and the wrapper is instantied also for the result, which however may have a different type.
See also line 66-71 in mlir/IR/BLockAndValueMapping.h

Tyker added inline comments.Sep 6 2022, 11:45 AM
mlir/include/mlir/IR/Value.h
434

Can Values be mapped to values of different type with BlockAndValueMapping ?
Do you have an example of a crash with mlir because of this ?

mscuttari added inline comments.Sep 6 2022, 1:19 PM
mlir/include/mlir/IR/Value.h
434

I don't see why not, the BlockAndValueMapping class does not impose any constraint about that. In my projects, for example, it happens that some operations have to unwrapped during the cloning process, thus resulting in a different type.
Here is a minimum working example reproducing the problem, including also the workaround I am currently using.

Tyker added inline comments.Sep 6 2022, 4:56 PM
mlir/include/mlir/IR/Value.h
434

here is a patch to solve the issue. https://reviews.llvm.org/D133384