MLIR relationship with LLVM

Hi all,

I’ve been reading up the MLIR project and I think it’s awesome work. I was curious about the relationship between MLIR and LLVM. If anyone can answer the following questions or give any insight, that would be great (I hope this is the place for this kind of discussion)

  1. How does the LLVM IR dialect relate to the actual LLVM IR project? Once lowered to from another dialect, does it enjoy the same optimizations done on stand alone LLVM IR inside MLIR as MLIR passes?

  2. Does there exist any tools to load LLVM IR into MLIR? For experimental purposes, it would be neat to compile some C code down to LLVM IR and then load into MLIR as the LLVM dialect.

The LLVM dialect in MLIR is primarily a means to exit MLIR and enter LLVM. It is mostly isomorphic with the LLVM IR, making this conversion easy. However, currently there is no conversion from LLVM IR back to the LLVM dialect. This is because of 2 reasons, primarily. First: no one has needed it for their projects! If it’s interesting to you, it’s definitely something that could be added. Secondly, I believe there are some aspects of LLVM IR which cannot be today represented in the MLIR LLVM dialect, so this probably will require some extensions to represent 100% of LLVM IR and be able to round-trip in a lossless way.

Most of the work in MLIR is looking at higher levels of abstraction, so just getting into the LLVM dialect doesn’t really help very much. One possibility would be to implement ‘raising’ transformations which try to recover higher level structure from the LLVM dialect. However, the belief among those involved is that generally it’s much better to start with high level abstractions (like tensors or loops) from a high-level language, rather than try to recover this structure. We’d be more interested in a path from Clang to the MLIR loop dialect for instance.



Just a nit on what Stephen mentioned: mlir-translate --import-llvm allows to import LLVM IR into the LLVM Dialect, the test is here:
This conversion is not complete and not an actively developed path, for all the reasons Stephen mentioned.

There are (almost) no transformations happening at the LLVM dialect level. The idea is that these transformations are better handled by LLVM itself and replicating them as-is in MLIR (as opposed to writing generalized passes that work across multiple dialects) is just duplicate work.

Identified structs are unrepresentable as of today. I sent an RFC last week proposing a solution for that. Is there something else?

Thanks for the answers everyone–makes sense that LLVM IR exists as an exit point for MLIR. Then, as Stephen alluded to, MLIR integration into a C compiler would look something like Clang → C IR → Loops etc.

I’m also curious what can’t (if anything else) from LLVM IR represented in MLIR.

Named struct type (not for long hopefully), metadata, and block address (not exhaustive list).

I have struct types like this in LLVM:

%struct.test1 = type { [4 x i32], i32 }                                                                                            
%struct.test2 = type { %struct.test1,  i32, i8* }

Is it possible to represent them in MLIR so far? Many thanks if someone can point me out a similar example of generating such LLVM struct types in MLIR.

This is in the process of being added. You can already express this using the test LLVM dialect as !llvm2.struct<"test1", (array<4 x i32>, i32)> for the first type and
!llvm2.struct<"test2", (struct<"test1", (array<4 x i32>, i32)>, i32, ptr<i8>)> for the second type. Note that the second type is self-consistent, you don’t need to “declare” types before using them in MLIR. will make this model default.

1 Like

This is a good news. Many thanks!