Description
The ArithToLLVM pass fails with an error message when the IR contains an arith.index_cast
operation with a memref operand and an integer element type type that does not match the width of the index type. E.g., on AMD64:
$ cat debug/index_cast_i32.mlir
module {
func.func @main(%arg0: memref<3xi32>) -> memref<3xindex> {
%0 = arith.index_cast %arg0 : memref<3xi32> to memref<3xindex>
return %0 : memref<3xindex>
}
}
$ mlir-opt debug/index_cast_i32.mlir --convert-func-to-llvm
debug/index_cast_i32.mlir:3:10: error: 'llvm.sext' op operand #0 must be integer or LLVM dialect-compatible vector of integer, but got '!llvm.struct<(ptr<i32>, ptr<i32>, i64, array<1 x i64>, array<1 x i64>)>'
%0 = arith.index_cast %arg0 : memref<3xi32> to memref<3xindex>
^
debug/sext_i32.mlir:3:10: note: see current operation: %6 = "llvm.sext"(%5) : (!llvm.struct<(ptr<i32>, ptr<i32>, i64, array<1 x i64>, array<1 x i64>)>) -> !llvm.struct<(ptr<i64>, ptr<i64>, i64, array<1 x i64>, array<1 x i64>)>
This is because the code of the rewriting pattern from IndexCastOpLowering<OpTy, ExtCastTy>::matchAndRewrite()
in mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp only handles scalar and vector operands. Memref operands are treated the same way as scalars, resulting in an llvm.sext
operation with the converted type of a memref, i.e., an !llvm.struct<...>
, which fails verification later on.
I'd love to extend the pattern so that it also handles operations with memref operands, but the semantics of arith.index_cast
operating on memrefs are unclear to me. I wouldn't expect the operation to allocate a new memref, but since there is no "output" operand, this is the only option to store the result. However, allocation of a new buffer would have consequences on memory management that cannot be treated directly in the pass, which would make it no longer self-contained.
Maybe @Mogball can clarify the semantics?