One of the operations in my custom dialect lowers to arith.addui_extended
which not only returns a sum, but also a flag indicating if there was an overflow. The following code snippet is a simplified example of what happens:
func.func @get_input() -> index {
%a = arith.constant 1 : index
return %a : index
}
func.func @main() -> i64 {
%a = func.call @get_input() : () -> index
%b = arith.constant 2 : index
%result, %overflow = arith.addui_extended %a, %b : index, i1
%d = index.casts %result : index to i64
return %d : i64
}
Please note that I onyl have the @get_input()
func so the addition is not constant folded. I then continued to lower the code to llvm using the following command:
mlir-opt \
--convert-func-to-llvm \
--convert-arith-to-llvm \
--convert-index-to-llvm \
./addition.mlir
This result in the error message:
./addition.mlir:9:24: error: 'llvm.extractvalue' op result #0 must be LLVM dialect-compatible type, but got 'index'
%result, %overflow = arith.addui_extended %a, %b : index, i1
Using the --mlir-print-ir-after-all
flag I was able to introspect the lowering into the MLIR LLVM dialect that look like so:
"builtin.module"() ({
"llvm.func"() ({
%0 = "llvm.mlir.constant"() {value = 1 : index} : () -> i64
"llvm.return"(%0) : (i64) -> ()
}) {CConv = #llvm.cconv<ccc>, function_type = !llvm.func<i64 ()>, linkage = #llvm.linkage<external>, sym_name = "get_input"} : () -> ()
"llvm.func"() ({
%0 = "llvm.call"() {callee = @get_input, fastmathFlags = #llvm.fastmath<none>} : () -> i64
%1 = "llvm.mlir.constant"() {value = 2 : index} : () -> i64
%2 = "llvm.intr.uadd.with.overflow"(%0, %1) : (i64, i64) -> !llvm.struct<(index, i1)>
%3 = "llvm.extractvalue"(%2) {position = array<i64: 0>} : (!llvm.struct<(index, i1)>) -> index
// ^-- Problematic operation
%4 = "llvm.extractvalue"(%2) {position = array<i64: 1>} : (!llvm.struct<(index, i1)>) -> i1
%5 = "index.casts"(%3) : (index) -> i64
"llvm.return"(%5) : (i64) -> ()
}) {CConv = #llvm.cconv<ccc>, function_type = !llvm.func<i64 ()>, linkage = #llvm.linkage<external>, sym_name = "main"} : () -> ()
}) {llvm.data_layout = ""} : () -> ()
The arith.addui_extended
operation was lowered into llvm.intr.uadd.with.overflow
that returns a llvm struct consisting of the result of type index
and the overflow bit. However, since I continue using the result of the addition, the lowering introduces a llvm.extractvalue
operation that extracts the result of the addition. However, index
seems to not be compatible here.
I am happy to get some feedback on this problem, or a hint into the right direction. Unfortunately, I cannot convert all index
values to i64
upfront, as both other operations of my dialect as well as some builtin operation expect index
values.