dialects: (linalg) support tiling of linalg.generic ops over tensors - #6362
Draft
dipo101 wants to merge 2 commits into
Draft
dialects: (linalg) support tiling of linalg.generic ops over tensors#6362dipo101 wants to merge 2 commits into
dipo101 wants to merge 2 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6362 +/- ##
=======================================
Coverage 86.94% 86.95%
=======================================
Files 440 440
Lines 65983 65999 +16
Branches 7493 7493
=======================================
+ Hits 57368 57387 +19
+ Misses 7037 7036 -1
+ Partials 1578 1576 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Member
|
This is great! This PR is too large to review IMO, and you've already broken it down nicely, so let's iterate in smaller PRs. I'll mark this PR as draft, can you please open a new one with just the first commit to start with? |
superlopuh
marked this pull request as draft
August 14, 2026 09:05
superlopuh
self-requested a review
August 14, 2026 09:05
Contributor
Author
|
Thanks! Opened #6366 with just the first commit (the |
dipo101
force-pushed
the
linalg-tiling-tensor
branch
from
August 14, 2026 12:56
7b365f4 to
ca1c2b4
Compare
This was referenced Aug 14, 2026
dipo101
force-pushed
the
linalg-tiling-tensor
branch
2 times, most recently
from
August 15, 2026 23:25
f6c28cd to
86b79f8
Compare
dipo101
force-pushed
the
linalg-tiling-tensor
branch
from
August 16, 2026 11:25
86b79f8 to
955281e
Compare
…loops A tile of a memref is written through the subview that views it, but a tile of a tensor is a new value, so it has to be written back explicitly and carried out of the loops it was computed in. Pass the outputs of an op with tensor semantics as the loop nest iteration arguments, slice those outputs from the values the innermost loop carries rather than from the originals, and write each computed tile back with a `tensor.insert_slice`. The innermost loop yields the updated tensors and each enclosing loop yields the results of the loop nested inside it, so the outermost loop produces the fully updated tensors, which then replace the results of the original op. Slicing an output from the original tensor rather than from the carried value, or erasing the op rather than replacing its results, would both give IR that verifies but drops the work of the surrounding iterations. The offsets, sizes and strides of a tile are now computed once as `SliceParameters`, since a tile has to be written back exactly where it was extracted from. Tiling memrefs carries nothing, writes nothing back, and yields nothing, so its generated IR is unchanged. Tiling tensors is still rejected during analysis, so this is not yet reachable from the pass.
Everything needed to tile an op with tensor operands is now in place, so stop rejecting them during analysis. The operand check becomes a positive one: memrefs and tensors are both tileable, and anything else is still rejected. Operands with a mix of memref and tensor outputs are rejected instead, since those would have to be written back in different ways within one loop nest, and the pass would otherwise fail while pairing the results of the tiled op with the values the loops carry. An op whose outputs are memrefs is unaffected, including one that reads a tensor and writes a memref: it has no results, so nothing is carried and the output is still written through its subview.
dipo101
force-pushed
the
linalg-tiling-tensor
branch
from
August 17, 2026 09:00
955281e to
fce5d67
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #6140, which tracks Linalg tiling support missing relative to upstream MLIR. This covers the tensor-based tiling checkbox.
Tiling a
linalg.genericover memrefs slices each operand with amemref.subviewand writes results through that view. Tensors have value semantics, so a tile is a new value that has to be written back explicitly and carried out of the loops it was computed in. That difference is what this adds.For an op over tensors, tiling now produces:
The outermost loop carries the original output tensor and each nested loop carries the enclosing loop's block argument, so the output tile is extracted from the value accumulated so far rather than from the original. The outermost loop's results replace the results of the original op.
Only
scf.foris generated. xDSL has noscf.forall, so the parallel form upstream also supports is out of scope here.Commits
dialects: (tensor) add mixed static/dynamic builders to extract_slice—tensor.extract_slicecould only be built with fully static offsets, sizes and strides, so it could not express a slice taken at a loop induction variable. Addsget()andinfer_result_type(), mirroring the existingmemref.SubviewOppair.dialects: (linalg) thread loop-carried values through tile loops— gives_build_tile_loopsan optionaliter_argsparameter.dialects: (linalg) slice tensor operands with tensor.extract_slice— widens the operand type and picks the slicing op based on it.dialects: (linalg) write tiles back into the tensors carried by tile loops— adds thetensor.insert_slicewrite-back and the operand-carrying yields.dialects: (linalg) tile linalg.generic ops over tensors— stops rejecting tensor operands during analysis.Commits 2 to 4 are each inert on their own, since tensor operands are still rejected until the last one. They are kept separate because each is a distinct change to explain.
Behaviour that is unchanged
Tiling memrefs carries nothing, writes nothing back and yields nothing, so its generated IR is byte-identical to before. The existing filecheck expectations are untouched.
An op that reads a tensor and writes a memref has no results, so nothing is carried and the output is still written through its subview. That case used to be rejected and now tiles; it has a test.
Newly rejected
An op with both memref and tensor outputs is rejected. Such an op verifies today but has fewer results than outputs, and the two kinds of output would have to be written back differently within one loop nest.
Tests
extract_slicebuildersOpen questions for review
tensor.ExtractSliceOphas noverify_checking that the dynamic index markers match the operand count, unlikememref.SubviewOp. This is pre-existing and deliberately left out of this PR, but happy to add it here if preferred.ExtractSliceOp.infer_result_typetakes noreduce_rankflag, unlike the memref one, since nothing needs it yet.mlir-optoutput, as the MLIR-conversion tests are opt-in.