Hi,
TL;DR Is it okay to run DCE during a conversion pass, in particular the MemRefToLLVM
one?
- Context *
Nicolas (@nicolasvasilache) and I have been working on handling some of the MemRef
lowering logic directly within the MemRef
dialect using composable rewriter patterns. (The rationale is some of these operators can be tricky to lower, e.g., subview
, expand_shape
, and we wanted to centralize that code in one place, so that different lowering passes wouldn’t have to reimplement it.)
Thanks to these patterns, we can get rid of a lot of code in the MemRefToLLVM
pass. (See a preview of what it can look like at https://github.com/llvm/llvm-project/commit/b8758baa1b68e58d017384ab5028e4cf26202cdf.)
The problem is these patterns don’t play nicely with the conversion ones. That is, if you run them with the conversion “driver” alongside the existing ones, it’s going to break. (They break the conversion driver, because they don’t necessarily follow the “replace-the-whole-op” pattern that is expected in the conversion framework, thus we end up with an assertion failure that the pattern needs to replace the whole op (see at the end of this post). E.g., some of our patterns rewrite only the uses of certain results of an op, not necessarily the whole operation.)
Since they are not technically conversion patterns, this is somewhat expected, and it makes sense to run them in isolation before the conversion patterns. This is where the problem arises!
- Why do we want to run DCE during a conversion pass? *
When we use rewriter patterns with the regular applyPatternsAndFoldGreedily
, we get a trivial DCE at the same time. This is something that we can’t control (should we be able to?). Therefore, it’s not really that we want to run DCE, but we have to at this point.
- Questions *
How do people feel about having a DCE pass during MemRefToLLVM
?
Generally speaking, are we okay with allowing DCE during conversions?
CC: @Mogball , @mehdi_amini , @River707, @ftynse
The assert in mlir/lib/Transforms/Utils/DialectConversion.cpp
assert((replacedRoot() || updatedRootInPlace()) &&
"expected pattern to replace the root operation");