When we originally proposed the packing operations, we went from Linalg to Tensor on a pre-RFC discussion, but over time we often wanted to keep the packing semantics through bufferization (to fuse at micro-kernel level) but couldn’t and had to rely on loop-level fusion.
IREE still retains its linalg_ext.pack operation for presumably similar reason, so I’ve been thinking perhaps we should move the pack/unpack pair into Linalg.
Recently, there was a PR that exposed yet-another problem of packing operations at tensor level: tensor compilers need to embed attributes to data movement operations that are not related to the actual tensor type, but have no other way to carry them that discardable attributes.
The fix was to propagate discardable attributes, because extending operations (to add non discardable attributes) is not that easy in MLIR, especially those that are associated with built-in types. Here there are no good solutions (pollute tensor
dialect with various unrelated attributes or propagate attributes that may have become invalid).
This gives us a second, more important, reason to move (or copy?) pack
and unpack
to Linalg: if we restrict its usage to “tensor compiler” logic, then we can inbue it with HW information, because that’s what tensor compilers do.
Due to the “tensor compiler” bias in my work, it’s not clear to me how much tensor.pack
is used outside of such use case. If not at all, then moving is the right thing to do, as we can evolve faster on the linalg
side without breaking other, non-linear algebra cases.
If they are used elsewhere, then there could be a more involved discussion on how to break it.
For example, where linalg.pack
“lowers to” tensor.pack
plus surrounding bits (loops, offset calculations, function calls, etc). Or if there’s only a minor use case, then we can also argue to duplicate packing onto another smaller dialect (potentially downstream). But we should not get ourselves in this convoluted discussion if there are no use cases.
My number one concern here is to keep design churn where the people that will pay the price are the ones actually making the decisions (right or wrong in the eyes of other people). By segregating decision makers and the impact of their decisions, we reduce conflict and avoid unwanted separation of concerns. We may not reach the best design in the meantime, but as long as we’re evolving into a better design space, this is a sound strategy.