This is an archive of the discontinued LLVM Phabricator instance.

[mlir][Linalg] NFC: Verify tiling on linalg.generic operation on tensors.
ClosedPublic

Authored by mravishankar on Dec 10 2020, 4:39 PM.

Details

Summary

With the recent changes to linalg on tensor semantics, the tiling
operations works out-of-the-box for generic operations. Add a test to
verify that and some minor refactoring.

Diff Detail

Event Timeline

mravishankar created this revision.Dec 10 2020, 4:39 PM
mravishankar requested review of this revision.Dec 10 2020, 4:39 PM
nicolasvasilache requested changes to this revision.Dec 11 2020, 3:45 AM

It's nice that we actually don't need to change op semantics to support "init_tensor form" and that all semantics can be dealt with just in tiling.
However we need a better abstraction and documentation to avoid leaking the op + init or result tensor implementation detail into the tiling implementation.

A simple

struct {
  LinalgOp op;
  Value result; // only if op has no init_tensor
};

with a proper API and assertions should be enough to separate these concerns.

The harder part will prob. be finding good names for this :)

mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
47 ↗(On Diff #311064)

initialization

48 ↗(On Diff #311064)

Now that I see you don't need to specify dims because the op must fold away before bufferization,
I am not worried about "the assumption that entire tensor is overwritten", this is the semantics of linalg ops and this is preserved by tiling.
So I would drop the "Proceed with caution" sentence and instead emphasize that this is an op that must fold away before bufferization.

mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
68 ↗(On Diff #311064)

This seems fishy to me because it changes the semantics of all ops.

Shouldn't we instead drop the extra dimensions from the getShapesToLoopsMap as discussed in https://reviews.llvm.org/D93076 ?
As I mentioned there, this was written in the context of buffers where the output buffers are part of the shaped operands.
So this needs a little adjustment but I would claim in the other direction.

mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
378

Please isolate in a helper function and document it:
"tiling on tensors requires tensors to write form"
"don't change the op semantics to become init_tensors but instead but create result tensors when needed"
"this op must fold away and does not require size operands even in the dynamic case"
etc

409–410

This doc assumed we would evolve the op semantics to allow all ops to convert to an "init_tensor form".
The direction you are pushing avoids that change and it need to be clearly documented.

409–410

this would benefit from a helper function + documentation that mentions the 2 cases:

  1. op with init tensor
  2. op without init tensor but with a companion result tensor for the purpose of tiling.
414

This is now harder to follow and we will trip over in the future.

I suggest a helper struct that captures the op and potentially the result tensor.
That struct hides the implementation detail for the purpose of tiling and would be queried as if the op was in init_tensor form.
With proper documentation it will make it much easier to understand in 3 months.

This revision now requires changes to proceed.Dec 11 2020, 3:45 AM
mravishankar marked an inline comment as done.Dec 12 2020, 9:55 AM
mravishankar added inline comments.
mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
48 ↗(On Diff #311064)

There are still issues with this op definition I am not entirely clear about. I sent this out for review to start conversion about this. Here are issues that i think need to be solved

  1. If it is upto bufferization to make sure that the init_tensor -> scf.for pattern should result in the "init_tensor being folded away" then I would expect it would be better to make sure there is one init_tensor for every tiling loop generated, i.e. init_tensor ops are not CSEed if there are multiple tiling loops. In that case we probably want to add some dummy side-effect for init_tensor
  2. I actually dont think having an initial value here is doing anything. Should we drop the "initialization value" above. The reason why I had this was because leaving it undef is a whole other can of worms, but that seems to actually match what is needed here. The proceed with caution was to say that the initialization value is not load-bearing at all. It is overwritten after tiling loops are executed.

My preference right now is to

  • make this a side-effecting operation that cannot be CSE-ed.
  • drop the initialization value
  • Assume that the bufferization is going to fold the op away
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
68 ↗(On Diff #311064)

Agreed. WIll send out a different patch for that.

Address comments and rebase

mravishankar marked 4 inline comments as done.Dec 13 2020, 10:03 AM
mravishankar added inline comments.
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
68 ↗(On Diff #311064)
mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
378

Good Idea. Made a helper struct TiledOp that encompasses all the logic. It does make things cleaner.

hanchung requested changes to this revision.Dec 14 2020, 3:46 AM
hanchung added inline comments.
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
1774–1778 ↗(On Diff #311455)

nit: drop braces.

https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements

E.g.,

// This should also omit braces.  The `for` loop contains only a single statement,
// so it shouldn't have braces.  The `if` also only contains a single simple
// statement (the for loop), so it also should omit braces.
if (isa<FunctionDecl>(D))
  for (auto *A : D.attrs())
mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
314

s/a/an

317

s/a/an

320–342

I would add braces between methods and vars because it helps readability. E.g.,

struct TiledOp {
  TiledOp(OpBuilder &b, LinalgOp op) : op(op) {
     ...
   }

  SmallVector<Value, 4> getTiledOperands() {
     ...
   }

  LinalgOp op;
  SmallVector<Value, 1> initTensors;
};
mlir/test/Dialect/Linalg/roundtrip.mlir
722–727 ↗(On Diff #311455)

We typically put this to invalid.mlir, lets move to there and remove adding -verify-diagnostics to this file.

mlir/test/Dialect/Linalg/tile-tensors.mlir
46

remove the blank line?

This revision now requires changes to proceed.Dec 14 2020, 3:46 AM
mravishankar marked an inline comment as done.

Updating this to use init_tensor operation, but this doesnt work. It
creates a use-after-def issue. This should be resolved when
https://llvm.discourse.group/t/linalg-and-shapes/2421 is addressed.

Rebase over recent changes to linalg on tensors

mravishankar retitled this revision from [mlir][Linalg] Allow tiling of Linalg operation on tensors that dont have init tensors. to [mlir][Linalg] NFC: Verify tiling on linalg.generic operation on tensors..Dec 24 2020, 5:29 PM
mravishankar edited the summary of this revision. (Show Details)
hanchung requested changes to this revision.Dec 28 2020, 10:56 AM
hanchung added inline comments.
mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
575

Since you also add IndexedGenericOp, could we add a test for it?

This revision now requires changes to proceed.Dec 28 2020, 10:56 AM
nicolasvasilache accepted this revision.Jan 5 2021, 12:23 PM

+1 for the extra test.

Rebase and add extra test

hanchung accepted this revision.Jan 11 2021, 11:07 AM
This revision is now accepted and ready to land.Jan 11 2021, 11:07 AM