One shot bufferization does not support bufferizing the cast between unranked tensors. To prevent the crash, we can check the compatibility of the result type in advance. Reported in https://github.com/llvm/llvm-project/issues/62369.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp | ||
---|---|---|
97–101 | This can be bufferized. The crash is caused by the fact that unraked->unranked casting is valid on tensor but not on memrefs for some reason. (I think we should handle it the same way on memrefs/tensors.) In that case, we can directly replaceOpWithBufferizedValues(rewriter, op, *resultBuffer);. |
@springerm Thanks for the advice.
Lowering memref.cast op with unranked memref for input and output to another dialect (e.g. LLVM) is not allowed for now.
./bin/mlir-opt cast.mlir cast.mlir:2:8: error: 'memref.cast' op operand type 'memref<4x?xi32>' and result type 'memref<4x?xf32>' are cast incompatible %0 = memref.cast %arg : memref<4x?xi32> to memref<4x?xf32> ^ cast.mlir:2:8: note: see current operation: %0 = "memref.cast"(%arg0) : (memref<4x?xi32>) -> memref<4x?xf32>
We can support a bufferization from unranked to unranked somehow, but it may cause runtime errors later after lowering more. Casting the unranked tensor to an unranked tensor looks like just passing the responsibility to the bufferization with unranked memref, so I did not find any good hint from that.
So what we can do is to make the pass return the failure instead of catching in the assertion?
Lowering memref.cast op with unranked memref for input and output to another dialect (e.g. LLVM) is not allowed for now.
Really? I thought the reason why we have unranked memrefs is so that we can call external functions. How does this work if we cannot lower it to LLVM?
Casting unranked tensor to unranked tensor looks like just passing the responsibility to the bufferization with unranked memref so I did not find any good hint with that.
Casting unranked -> unranked is a no-op. Such casts should fold away. This could be done during bufferization to work around the inconsistency that unranked->unranked is allowed on tensors but not on memrefs:
if (resultBuffer->getType() == *resultMemRefType) { // This cast is a no-op. replaceOpWithBufferizedValues(rewriter, op, *resultBuffer); return success(); }
Casting unranked -> unranked is a no-op. Such casts should fold away. This could be done during bufferization to work around the inconsistency that unranked->unranked is allowed on tensors but not on memrefs:
Thanks for the advice. I think that should work. I'll try to eliminate the cast as no-op.
@springerm No-op casting simply seems to be working as you said. Could you review this change when you get a chance?
@springerm Sorry for bothering you from time to time, but could you review this change when you get a good chance?
This can be bufferized. The crash is caused by the fact that unraked->unranked casting is valid on tensor but not on memrefs for some reason. (I think we should handle it the same way on memrefs/tensors.) In that case, we can directly replaceOpWithBufferizedValues(rewriter, op, *resultBuffer);.