This is an archive of the discontinued LLVM Phabricator instance.

[mlir][Linalg] Add support for fusing linalg.tensor_reshape with linalg.generic operations.
ClosedPublic

Authored by mravishankar on Apr 19 2020, 3:37 PM.

Diff Detail

Event Timeline

mravishankar created this revision.Apr 19 2020, 3:37 PM

Updating the logic to handle cases where some dimensions are dynamic.

nicolasvasilache requested changes to this revision.Apr 21 2020, 1:43 PM
nicolasvasilache added inline comments.
mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
583

Adding the example from your test would be informative:

E.g.
%0 = op ... : tensor<?x?x4x5xf32>
with output index_map `affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>`

and reshape:
%1 = linalg.tensor_reshape %0 [affine_map<(i, j, k, l) -> (i)>,
                                 affine_map<(i, j, k, l) -> (j, k, l)>] :
    tensor<?x?x4x5xf32> into tensor<?x?xf32>

would be rewritten into:
%0 = op ... : tensor<?x?x4x5xf32>
with output index_map `affine_map<(d0, d1, d2, d3) -> (d0, d1 * 20 + d2 * 5 + d3)>`
644

Could you please add a:

// TODO: In the future this restriction may justify extending the linalg.generic to semi-affine maps.
// TODO: Alternatively, fusing across a reshape and pushing the reshape towards the boundary of the function could help too.
648

I wonder if we could slightly refactor the function exposed here https://reviews.llvm.org/D75575
and just use it instead of rewriting a slightly different version.

Basically the existing function would just need a starting dimPos = 0 by default.

You could then just use that to get:

for ... {
  AffineExpr stridedExpression = makeCanonicalStridedLayoutExpr(srcShape.slice(), context);
  if (!isPureAffine(stridedExpression))
    return AffineMap();
  results.push_back(stridedExpression);
}
return AffineMap.get(...);

And check whether AffineMap is empty to know whether it is fusible.

The downside is that in your current code structure you could be recomputing it twice but IMO this would largely be beneficial to save a few dozen lines of code that is similar to something we already have in the codebase.

If the recomputing bothers you, you could refactor a bit but I wouldn't be worried at this time, these are really trivial computations.

681

Can we simplify l680 - 695 with something along the lines of:

SmallVector<Attribute, 4> fusedIndexMaps(consumerIndexMaps.begin(), consumerIndexMaps.end());
fusedIndexMaps[consumerIdx] = linearize();
726

typo thee

729

Same here, create then update should be simpler.

799

If you adopt the style in the previous PR, this conditional would just fold into the Operation* based form above.

This revision now requires changes to proceed.Apr 21 2020, 1:43 PM
mravishankar marked 8 inline comments as done.

Addressing comments

rriddle resigned from this revision.Apr 21 2020, 4:25 PM
nicolasvasilache accepted this revision.Apr 22 2020, 9:17 PM

Thanks for the cleanup!

mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
650

Could this whole loop be replaced by something like:

if (!useIndexMap.isIdentity()) return false;
for (auto linearizedExpr : linearizeCollapsedDims(useIndexMap, srcShape, reassociationMaps) )
  if (!isPureAffine(linearizedExpr)) return false;
This revision is now accepted and ready to land.Apr 22 2020, 9:17 PM

Submitting some responses that I had forgetten to submit

mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
583

THanks for the detailed comment.

648

It ended up being quite a significant change to makeCanonicalStridedLayoutExpr, but it is more general now, and it works well with the current use case as well. It does recompute twice, but thats OK by me. PTAL

681

Nice! Done

antiagainst accepted this revision.Apr 23 2020, 8:52 AM

Cool stuff!

mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
580

Linearizes

592

Neat: alignment :)

661

Can return WalkResult::interrupt() after this to avoid further walking.

mravishankar marked 7 inline comments as done.

Addressing comments

mravishankar added inline comments.Apr 23 2020, 1:31 PM
mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
650

I removed this in the checker and just added a check in the fuse operations to check that the resulting map is pure affine.

661

I dont think the walk on AffineExpr allows that. In any case not needed anymore

This revision was automatically updated to reflect the committed changes.