This revision adds support for bufferization by using a mix of tensor_load, subview, linalg.copy and tensor_to_memref.
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
mlir/lib/Dialect/Linalg/Transforms/Bufferize.cpp | ||
---|---|---|
242 | This shouldn't be needed. See below. | |
250 | This shouldn't be needed, see below. | |
279 | The conversion framework guarantees that operands are all legal types (which would be memref here). So you shouldn't need this if condition and can proceed assuming that sourceMemref is a memref. | |
283 | You can use getTypeConverter()->convertType(op.getType()). | |
296 | You should not be creating TensorLoad / TensorToMemref ops yourself. The dialect conversion framework does it automatically. You can replace this line with rewriter.replaceOp(op, alloc) and it will automatically insert tensor_load if needed. | |
331 | Same comment. This isn't needed. The conversion is guaranteed by the framework. | |
384 | not needed. | |
mlir/test/Dialect/Linalg/bufferize.mlir | ||
232 | This is not correct. Sorry :( Consider %t = std.get_global_memref @some_constant_memref. There's no way of getting out of a non-peephole analysis here to prove that a memref is writable and not aliased in a way that prevents this optimization. Let's land this without attempting any tricks, and then do a "whiteboarding" session to look at ways to get the desired optimization here (I can think of many ways, but I think we will need to stare at the "inefficient but correct" versions to really make a decision on the tradeoffs here). |
Thanks @silvas
FYI @ulysseB @albertcohen
mlir/test/Dialect/Linalg/bufferize.mlir | ||
---|---|---|
232 | Actually, note that the TensorToMemRefOp says: Create a memref from a tensor. This is equivalent to allocating a new memref of the appropriate (possibly dynamic) shape, and then copying the elements (as if by a tensor_store op) into the newly allocated memref. I dropped all the copies that are unnecessary according to this semantics. |
mlir/lib/Dialect/Linalg/Transforms/Bufferize.cpp | ||
---|---|---|
244 | nit: remove tensor_to_memref here, as it no longer reflects the code in the pattern body. | |
mlir/test/Dialect/Linalg/bufferize.mlir | ||
232 | Ugh, I wrote that line, and somehow I didn't piece together the ramifications of these semantics. In practice, tensor_to_memref(tensor_load(memref)) -> memref pattern gets applied in many places without considering this semantic... which is a huge latent bug. This is partially just due to how the dialect converion framework works. It elides them "on the fly" without considering the aliasing implications of removing copies.... I'll need to think more about how to fix this..... Thanks for reminding me of this. Example: func @f(%arg0: memref<?xf32>) { %0 = tensor_to_memref(tensor_load(%arg0)) %1 = tensor_to_memref(tensor_load(%arg0)) // In current code, %0 and %1 will alias each other. // In corrected code, %0 and %1 must not alias each other unless it's provable that it doesn't matter :/ } |
mlir/lib/Dialect/Linalg/Transforms/Bufferize.cpp | ||
---|---|---|
244 | Addressed: squashed into the commit but forgot to update phab. |
This shouldn't be needed. See below.