Problem Statement
The TilingInterface is designed to allow generating tiled implementations of operations. In addition to tiling specific interface methods for use within helpers like scf::tileUsingSCF
, the interface includes a number of methods designed for “tile and fuse” algorithms, grouped below:
Tiling
getLoopIteratorTypes
getIterationDomain
getTiledImplementation
getResultTilePosition
Fusion
- Producer fusion
generateResultTileValue
getIterationDomainTileFromResultTile
- Consumer fusion
getTiledImplementationFromOperandTile
getIterationDomainTileFromOperandTile
This design works well for chains of tilable ops as users can in theory choose to tile any of the operators in the chain and fuse in the surrounding operations. The fact that fusion is tied to the TilingInterface, however, restricts the fusion algorithm to tilable ops.
Consider the following example
%0 = ...
%1 = linalg.transpose
%2 = tensor.extract_slice %1
%4 = linalg.transpose %2
Currently, trying to tile %4
and fuse producers would stop on %3
(a la tileConsumersAndFuseProducersUsingSCF) as tensor.extract_slice
does not implement the tiling interface. Implementing the tiling interface should be unecessary to perform the fusion though, as after tiling the linalg.transpose
we should expect something like the following:
%0 = ...
%1 = linalg.transpose
%2 = tensor.extract_slice %1
%3 = scf.for {
%4 = tensor.extract_slice %2
%5 = linalg.transpose %4
scf.yield %5
}
Where at this point we could merge consecutive extract slice ops and continue fusion on the merged extract slice, fusing in %1
.
Similar reasoning applies to tensor.expand_shape
and tensor.collapse_shape
where we do not want to implement the tiling interface for those ops but do want to fuse them in situations like the above.
Proposed Solution
The solution proposed here is to split the TilingInterface
into two interfaces: itself (TilingInterface
) and one specifically for fusion, FusableOpInterface
(naming suggestions welcome). The interface methods would be split into the two groups listed above (matching with the existing documentation in TilingInterface.td
).
The TilingInterface
can be changed to inherit from the FusableOpInterface
, leaving existing TilingInterface implementations alone and avoiding API breakages.