Operation Attributes to cache expensive computations

While working on ⚙ D109418 [mlir][MemRef] Compute unused dimensions of a rank-reducing subviews using strides as well., I found a use case for having a way to cache some information that might be needed from the op, but would be expensive to compute using the operation operands/attributes. It would be very useful to have a way to compute that information once and store it on the op using an attribute.

One issues there is that adding this as an attribute that is part of the ins list in the Ops ODS definition would result in this attribute being part of build methods of the operation. That is better avoided since this information can be computed from existing operands/attributes.
Another issue is that these attributes should not be parsed/printed. They are essentially “hidden” attributes that are just caching information. I am mostly thinking of the assemblyFormat route of parser/printers where we can have an interface for operations that allow operations to specify a list of such attributes which the parser/printer generator can pick up.

There are a few options I have preliminarily looked at. Would like to first get an idea of

  1. Is this a good idea
  2. Some suggestions about how to go about implementing this.

@mehdi_amini @River707 for comments.

1 Like

Wouldn’t you need to manually write any builder that don’t take this “inferred” attribute manually anyway?

In general an interesting question is how to ensure that this cached attribute stays up-to-date, and what is the mechanism to recompute it if needed?

We can have an interface that allows op to specify which attribute is cached. Looking at OpFormatsGen.cpp it elides the attributes that are for tracking variadic operands and result segments. We could use an interface to allow operations to specify a list of further attributes to be elided while parsing/printing using the assembly format.

For now I would let an operation deal with it. There might be a generic mechanism, but I dont have any idea about how to structure that.

If we have such an interface, it could provide a verifier in the trait that checks that the attribute is up-to-date?

Depends on what operands/attributes of the operation are used to compute this cached value. I cant see a general solution for this that is reasonably simple. So thats why I am thinking of decoupling it.
First have a way to actually carry this information without disrupting the parser/printer/build methods that are generated. Then have a way to track/update the attribute values. For now for sake of correctness we can say that if any of the operands/attributes of the operation change, the cache should be invalidated. I dont know how to implement this though.

What about forcing the update to go through well defined API. If an attribute is defined as inferred and cached, then there is a known method to compute the cached value. The verifier can then just check if the cached attribute is present and if so call this method and compare the values.
The builders can also be taught to omit the attribute from the list and call this method on construction automatically.

Make sense. In the straw-man example I had, this basically what I was doing.