This is an archive of the discontinued LLVM Phabricator instance.

[mlir] Make DenseArrayAttr generic
ClosedPublic

Authored by Mogball on Aug 26 2022, 1:09 PM.

Details

Summary

This patch turns DenseArrayBaseAttr into a fully-functional attribute by
adding a generic parser and printer, supporting bool or integer and floating
point element types with bitwidths divisible by 8. It has been renamed
to DenseArrayAttr. The patch maintains the specialized subclasses,
e.g. DenseI32ArrayAttr, which remain the preferred API for accessing
elements in C++.

This allows DenseArrayAttr to hold signed and unsigned integer elements:

array<si8: -128, 127>
array<ui8: 255>

"Exotic" floating point elements:

array<bf16: 1.2, 3.4>

And integers of other bitwidths:

array<i24: 8388607>

Diff Detail

Event Timeline

Mogball created this revision.Aug 26 2022, 1:09 PM
Herald added a project: Restricted Project. · View Herald Transcript
Mogball requested review of this revision.Aug 26 2022, 1:09 PM
Mogball edited the summary of this revision. (Show Details)Aug 26 2022, 2:53 PM
lattner accepted this revision.Aug 26 2022, 3:45 PM
lattner added a subscriber: lattner.

This is really great Jeff! Thank you for cleaning this up!

mlir/lib/AsmParser/AttributeParser.cpp
867

I'm pretty sure this is incorrect for big-endian systems, e.g. an i8 is stored in the last 8 bytes of a 64-bit word instead of the first byte. I would implement this with a "extract a byte at a time from the low part of an APInt" loop.

This revision is now accepted and ready to land.Aug 26 2022, 3:45 PM
Mogball updated this revision to Diff 456067.Aug 26 2022, 5:01 PM

Use llvm::StoreIntToMemory and llvm::LoadIntFromMemory to handle endianness

Mogball marked an inline comment as done.Aug 26 2022, 5:01 PM
Mogball added inline comments.
mlir/lib/AsmParser/AttributeParser.cpp
867

Grr you're right. That means the opposite trick in the printer is also incorrect :(. Good catch

rriddle accepted this revision.Aug 29 2022, 12:08 AM

Aside from the getValuesImpl change (which we discussed on another revision), LGTM.

Mogball marked an inline comment as done.Aug 30 2022, 10:47 AM

@mehdi_amini any comments/concerns?

Mogball updated this revision to Diff 456727.Aug 30 2022, 11:05 AM

pull in the fix

Mogball updated this revision to Diff 456758.Aug 30 2022, 12:34 PM

add tests for error cases

This revision was landed with ongoing or failed builds.Aug 30 2022, 1:29 PM
This revision was automatically updated to reflect the committed changes.

@mehdi_amini any comments/concerns?

If you're asking, you could maybe wait at least a day before landing?

This patch turns DenseArrayBaseAttr into a fully-functional attribute by adding a generic parser and printer

I don't know what this means? In general I would rephrase the title as well, the genericity here is fairly limited as far as I can tell (some folks would want an Array of enums :) ).

Otherwise my main concern on the code change right now is that it isn't clear to me what the C++ story is: you added the ability to parse/print some stuff but how do we access / use this on the C++side of things?

@mehdi_amini any comments/concerns?

If you're asking, you could maybe wait at least a day before landing?

Sorry >.<. I didn't realize how little time had passed since I posted that comment

This patch turns DenseArrayBaseAttr into a fully-functional attribute by adding a generic parser and printer

I don't know what this means? In general I would rephrase the title as well, the genericity here is fairly limited as far as I can tell (some folks would want an Array of enums :) ).

Yes, you're right that "generic" is too broad a word. It's a little less "generic" than DenseElementsAttr, which allows string elements and integers or any width. On the former point, DenseArrayBaseAttr was on its own not very useful. You needed to use one of the sub-classes. Now, the sub-classes function as more strongly typed "views" on the DenseArrayAttr base class.

Otherwise my main concern on the code change right now is that it isn't clear to me what the C++ story is: you added the ability to parse/print some stuff but how do we access / use this on the C++side of things?

I made some changes to ElementsAttr that would allow DenseArrayAttr to implement, for example, getValues<APInt> and getValues<APFloat>. Coming soon^TM

On the former point, DenseArrayBaseAttr was on its own not very useful. You needed to use one of the sub-classes. Now, the sub-classes function as more strongly typed "views" on the DenseArrayAttr base class.

Right but that was very intentional though: making the API hard to misuse is quite important here.

Otherwise my main concern on the code change right now is that it isn't clear to me what the C++ story is: you added the ability to parse/print some stuff but how do we access / use this on the C++side of things?

I made some changes to ElementsAttr that would allow DenseArrayAttr to implement, for example, getValues<APInt> and getValues<APFloat>. Coming soon^TM

OK but ElementsAttr is an interface, and we're back to some convoluted way to access the data. This can't be the main intended way of using this attribute I believe.

On the former point, DenseArrayBaseAttr was on its own not very useful. You needed to use one of the sub-classes. Now, the sub-classes function as more strongly typed "views" on the DenseArrayAttr base class.

Right but that was very intentional though: making the API hard to misuse is quite important here.

I would say it's still quite difficult to misuse. The base attribute is still limited in what it offers out-of-the-box. Adding APInt and APFloat accessors will make interacting with the base class easier while still requiring significant effort to "abuse".

Otherwise my main concern on the code change right now is that it isn't clear to me what the C++ story is: you added the ability to parse/print some stuff but how do we access / use this on the C++side of things?

I made some changes to ElementsAttr that would allow DenseArrayAttr to implement, for example, getValues<APInt> and getValues<APFloat>. Coming soon^TM

OK but ElementsAttr is an interface, and we're back to some convoluted way to access the data. This can't be the main intended way of using this attribute I believe.

I mean you would be able to do DenseArrayAttr::getValues<T> and not go through the interface at all (but the interface would work as well).

I don't understand why we'd expose any APInt access at all actually? Why should we "exclusively" restrict access to the data through the specialized classes?

I don't understand why we'd expose any APInt access at all actually? Why should we "exclusively" restrict access to the data through the specialized classes?

"Should" or "shouldn't"? The specialized classes are still the "preferred" way to interact with the data and the most meaningful way in C++, *if* the data needs to be interacted with in C++.

I don't understand why we'd expose any APInt access at all actually? Why should we "exclusively" restrict access to the data through the specialized classes?

"Should" or "shouldn't"?

"Shouldn't" :)

The specialized classes are still the "preferred" way to interact with the data and the most meaningful way in C++, *if* the data needs to be interacted with in C++.

Right, but the discussion here is only about C++, and you added new in-memory support for this attribute without a good way to manipulate it in C++ as far as I can tell.

Right, but the discussion here is only about C++, and you added new in-memory support for this attribute without a good way to manipulate it in C++ as far as I can tell.

I was planning on adding C++ subclasses for the unsigned variants but use APInt/APFloat as the fallback way of interacting with data that don't have great C++ equivalents. Would you instead prefer the parser be restricted even more?

The whole point of this attribute is to offer a safe API always exposed as ArrayRef<T> with zero ambiguity. Users should never have to lookup the shapes type or anything else there to use it I think.

Yes, and that hasn't and won't change.

vitalybuka added a comment.EditedAug 31 2022, 11:22 PM

There is another one https://lab.llvm.org/buildbot/#/builders/85/builds/10389

I can take a took tomorrow, but I guess it's easy to debug with asserts even without UBsan build.

@Mogball please prioritize fixing bots after your patch lands: if we can't fix quickly we should always revert quickly.

Mogball added a comment.EditedSep 1 2022, 8:47 AM

I need to check why I'm not getting buildbot emails anymore. I'll look into the failure ASAP (but my UB/ASAN build takes a while)

I pushed a fix.

I need to check why I'm not getting buildbot emails anymore. I'll look into the failure ASAP (but my UB/ASAN build takes a while)

That's our fault.
We run check-mlir with sanitizers, but buildbot was not configured to watch that project. So Mlir changes are not on the blame list.
I've changed that yesterday, but it will take time to get from staging to buildbot https://github.com/llvm/llvm-zorg/commit/d96f4ee444459831dbe7de44c859e24b9c06a594