This is an archive of the discontinued LLVM Phabricator instance.

[mlir] Generate constructor in generic adaptors allowing construction from an op instance
ClosedPublic

Authored by zero9178 on Aug 9 2023, 8:50 AM.

Details

Summary

In essentially all occurrences of adaptor constructions in the codebase, an instance of the op is available and only a different value range is being used. Nevertheless, one had to perform the ritual of calling and pass getAttrDictionary(), getProperties and getRegions manually.

This patch changes that by teaching TableGen to generate a new constructor in the adaptor that is constructable using GenericAdaptor(valueRange, op). The (discardable) attr dictionary, properties and the regions are then taken directly from the passed op, with only the value range being taken from the first parameter.

This simplifies a lot of code and also guarantees that all the various getters of the adaptor work in all scenarios.

Diff Detail

Event Timeline

zero9178 created this revision.Aug 9 2023, 8:50 AM
Herald added a reviewer: ftynse. · View Herald Transcript
Herald added a reviewer: dcaballe. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
zero9178 requested review of this revision.Aug 9 2023, 8:50 AM

Nice cleanup!

mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
3975

The condition seems reversed?

zero9178 updated this revision to Diff 548895.Aug 10 2023, 12:13 AM
zero9178 marked an inline comment as done.

Address review comments

mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
3975

Nice catch, thanks! Fixed and added a test as well.

mehdi_amini accepted this revision.Aug 10 2023, 12:21 AM
This revision is now accepted and ready to land.Aug 10 2023, 12:21 AM

One thought: could it be a method on the Op class? getAdaptor(ValueRange values) { ... }.
It's templated with the ConcreteOp and should be able to handle everything. Seems slightly less intrusive than TableGen.

zero9178 added a comment.EditedAug 10 2023, 12:52 AM

One thought: could it be a method on the Op class? getAdaptor(ValueRange values) { ... }.
It's templated with the ConcreteOp and should be able to handle everything. Seems slightly less intrusive than TableGen.

I briefly tried it but I think its less ergonomic to use. What I had was essentially:

template <typename RangeT, typename ConcreteOpT = ConcreteType>
typename ConcreteOpT::GenericAdaptor<std::decay_t<RangeT>> getAdaptor(RangeT &&range) {

(ignore the second template parameter, its required for compilation but does not change semantics).

The first issue I encountered is that you could not construct a OpAdaptor as it is a subclass of GenericAdaptor<ValueRange>.
Second, I think the type deduction performed by C++ in this case leads to more surprising code. If you have an interface expecting GenericAdaptor<ValueRange> but pass in a ArrayRef<Value> into the above, you'll get a different adaptor type. One could fix this by having TableGen generate implicit constructors if the ranges are convertible but that would once again require TableGen changes. (To be fair, we maybe want this at some point anyways).

To counteract these two issues I also attempted:

template <typename Adaptor, class RangeT>
auto getAdaptor(RangeT &&range) {

This fixes both of my concerns but is still annoying to use in generic contexts: sourceOp.template getAdaptor<OpAdaptor>(operands) as opposed to just OpAdaptor(operands, sourceOp).
It is also a lot easier and faster to write a using for an adaptor class than it is to write a wrapper for getAdaptor.
You'd also have to write a static_assert within getAdaptor to make sure that Adaptor is an instance or subclass of ConcreteOp::GenericAdaptor to get the same strong typing as the current solution. I can definitely do that but it adds to the complexity.

I personally prefer the current solution for that reason. While I agree that writing C++ code is better than making TableGen generate code, I like the ergonomics of the TableGen approach more and think they are worth it.

Mogball added inline comments.Aug 10 2023, 1:05 AM
mlir/include/mlir/TableGen/Class.h
181

Does the API rely on deduplication of the template arguments? Otherwise, the SetVector doesn't make much sense.

192

Please default this to zero given that most methods won't have template params.

zero9178 updated this revision to Diff 548915.Aug 10 2023, 1:21 AM
zero9178 marked 2 inline comments as done.

Address review comments

mlir/include/mlir/TableGen/Class.h
181

Not really, this was just lazy copy paste programming from my side. This is required in other places, but definitely not here.

This revision was landed with ongoing or failed builds.Aug 10 2023, 3:52 AM
This revision was automatically updated to reflect the committed changes.