Maybe it’s because I don’t understand it or maybe there’s an assumption that I’m going to be doing everything from C++, but it’s incredibly difficult to get a handle on what actual MLIR is supposed to look like. I’m trying to generate MLIR by hand, but the examples I come across in the docs don’t seem to translate to LLVM IR without an error. There’s also pieces of MLIR that I’m seeing that I can’t find documentation for what it is or why it’s there.
Take this section for example: LLVM IR Target - MLIR
The MLIR at the top is:
func @foo(%arg0: i32, %arg1: i64) -> (i32, i64) {
return %arg0, %arg1 : i32, i64
}
func @bar() {
%0 = arith.constant 42 : i32
%1 = arith.constant 17 : i64
%2:2 = call @foo(%0, %1) : (i32, i64) -> (i32, i64)
"use_i32"(%2#0) : (i32) -> ()
"use_i64"(%2#1) : (i64) -> ()
}
But trying to convert this to LLVM IR results in an error. Like I said before, I’m not using C++ and not using bindings or anything like that. My goal is to generate MLIR by hand so I’m using a combination of mlir-opt
and mlir-translate
(I don’t understand why I have to use two different tools for this) to convert MLIR to… the dialect version of MLIR? And then onto LLVM IR.
The commands I’m using are:
-
mlir-opt --convert-complex-to-llvm --convert-linalg-to-llvm --convert-math-to-llvm --convert-memref-to-llvm --convert-openacc-to-llvm --convert-openmp-to-llvm --convert-spirv-to-llvm --convert-std-to-llvm --convert-vector-to-llvm --gpu-to-llvm --llvm-legalize-for-export --std-expand mlir/test.mlir
(if I add--convert-async-to-llvm
it prints out a stack dump) -
mlir-translate --mlir-to-llvmir test.mlir
Using the first command the error I receive is:
mlir/test.mlir:6:8: error: custom op 'arith.constant' is unknown
%0 = arith.constant 42 : i32
^
If I try the second command I get:
mlir/test.mlir:2:3: error: custom op 'return' is unknown
return %arg0, %arg1 : i32, i64
^
The error from the first command seems to indicate it doesn’t know what arith
is and the error from the second command appears to need to have the “dialect’d” form of MLIR converted by the first command.
My questions are as follows:
- Why do I need to use two different tools to convert MLIR to MLIR to LLVM IR?
- Why does MLIR Language Reference - MLIR not explain what something like
"foo_div"() : () -> (f32, i32)
does? Why are there quotes around the name? Is that supposed to call a function calledfoo_div
specified elsewhere? If you try to convert that it complains about not knowing what the dialect is. I saw thistf.scramble
in that doc too and it seems like it might call out to another dialect? - How are you supposed to assign most types?
!foo = type i32
func @bar(%a: i32) -> !foo {
return %a : i32
}
That converts just fine and so does:
!foo = type () -> (i32, i32)
func @bar(%a: !foo) -> !foo {
return %a : !foo
}
But how am I supposed to assign to !foo
?
!foo = type () -> (i32, i32)
func @bar() -> !foo {
%a = ???
return %a : !foo
}
- What does
error: expected operation name in quotes
actually mean and how I figure out what the problem is when I see that?
Any help or tips are much appreciated.