This is an archive of the discontinued LLVM Phabricator instance.

[mlir] Add a canonicalization pattern for MemRefCastOp into dynamic MemRefs
AbandonedPublic

Authored by nicolasvasilache on Jan 17 2020, 9:27 AM.

Details

Summary

This diff adds a canonicalization pattern to canonicalize either:

mlir
  ... = memref_cast ... : memref<8x16xf32> to memref<?x?xf32>
  ... = memref_cast ... : memref<8x16xf32, affine_map<(i, j)->(16 * i + j)>>
        to memref<?x?xf32>

into

mlir
  ... = memref_cast ... : ... to memref<8x16xf32>

This diff additionally needs to modify a seemingly unrelated things that does
not play nicely atm. Some tests that return memref need to be changed because
canonicalization does not propagate to function signature.

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptJan 17 2020, 9:27 AM

Remove spurious declarations.

rriddle requested changes to this revision.Jan 17 2020, 9:36 AM
rriddle added inline comments.
mlir/lib/Dialect/StandardOps/Ops.cpp
1804

You are replacing with something of a different type. That doesn't really fit as a canonicalization. For this to be conservatively correct, it would mean you need to prevent a memref cast from ever being used: in a function call, as a branch argument, etc.

This revision now requires changes to proceed.Jan 17 2020, 9:36 AM

Unit tests: unknown.

clang-tidy: unknown.

clang-format: pass.

Build artifacts: diff.json, clang-format.patch, CMakeCache.txt, console-log.txt

Unit tests: pass. 61909 tests passed, 0 failed and 782 were skipped.

clang-tidy: unknown.

clang-format: pass.

Build artifacts: diff.json, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

nmostafa added inline comments.
mlir/lib/Dialect/StandardOps/Ops.cpp
1768

You need to handle or bailout on UnrankedMemRefType (and probably add a test for it). Also, the type propagation is only valid based on how the result is used : e.g. if a func argument, then the conversion is invalid.

Address review comments.

nicolasvasilache marked 3 inline comments as done.Jan 17 2020, 12:37 PM
nicolasvasilache added inline comments.
mlir/lib/Dialect/StandardOps/Ops.cpp
1768

Thanks, I addressed those points but there are quite deeper implications as River pointed out.

1804

How fundamental do you foresee this to be a limitation in the longer term?
The use cases look like:

cast -> X1 
...
cast -> Xk

where k is small(ish).
Very concretely, this enables n-D linag.vectorization to kick-in as a declarative pattern rewrite that composes nicely with all the other things.
So at some point I will want a way to hook that up with Ops that should not be seen here.

I could extend this into a conditional pattern that is called with a lambda from the proper places.
It also seems OpInterfaces would be a natural fit but it seems a very unnatural thing to say "set of ops for which memrefcast can canonicalize its return type".

OTOH I can also bail here and make this a rewrite pattern locally in the pass that I am experimenting with.
But the way things start looking like passes become a union of loose connected patterns that compose nicely and locally to achieve global effects.
The most natural thing that this pattern made me think of is a canonicalization (modulo the type change), which is why I am trying this maybe unnatural thing.

Thoughts?

Unit tests: pass. 61909 tests passed, 0 failed and 782 were skipped.

clang-tidy: unknown.

clang-format: pass.

Build artifacts: diff.json, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

Unit tests: pass. 61909 tests passed, 0 failed and 782 were skipped.

clang-tidy: unknown.

clang-format: pass.

Build artifacts: diff.json, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

nicolasvasilache marked an inline comment as done.Jan 17 2020, 1:13 PM

In addition to all this I seem to have also uncovered issues in the existing memref_cast folders .. investigating.
It is likely the fact that memref_cast and other casts are considered to be "almost the same thing" is completely wrong.

nicolasvasilache abandoned this revision.Jan 17 2020, 1:28 PM

Scratch that, I am wrong, sorry .. the load(memref) just forwards the operand and that is ok.
It seems my current pattern is not properly testable without the ops I want.

I will move it into Linalg Transforms for now and get the end-to-end story more visible.
When/if it makes sense we can discuss whether canonicalization could ever make sense for this.