Elixir FE for MLIR

GitHub: GitHub - beaver-lodge/beaver: Beaver is a LLVM/MLIR Toolkit in Elixir and Zig.

The idea is that you could generate IR and run passes in one pipeline

mlir ctx: test_context[:ctx] do
  module do
    Func.func test_multi_broadcast(
                function_type: ~a"(tensor<1x3xf32>, tensor<2x1xf32>) -> tensor<2x3xf32>"
              ) do
      region do
        block entry(
                arg0 >>> Type.ranked_tensor([1, 3], Type.f32()),
                arg1 >>> Type.ranked_tensor([2, 1], Type.f32())
              ) do
          v0 = TOSA.add(arg0, arg1) >>> Type.ranked_tensor([2, 3], Type.f32())

          v0 =
            TOSA.mul(v0, arg1, {:shift, ~a{0 : i32}}) >>>
              Type.ranked_tensor([2, 3], Type.f32())

          Func.return(v0) >>> []
        end
      end
    end
  end
end
|> MLIR.Operation.verify!()
|> canonicalize
|> cse
|> tosa_to_scf
|> tosa_to_arith
|> tosa_to_tensor()
|> convert_tensor_to_linalg()
|> MLIR.Pass.Composer.nested("func.func", [
  tosa_to_linalg(),
  linalg_fuse_elementwise_ops(),
  linalg_bufferize(),
  convert_linalg_to_loops(),
  lower_affine(),
  convert_math_to_llvm(),
  convert_scf_to_cf(),
  "arith-expand",
  "memref-expand"
])
|> MLIR.Pass.Composer.nested("func.func", "tensor-bufferize")
|> MLIR.Pass.Composer.append("func-bufferize")
|> MLIR.Pass.Composer.nested("func.func", "llvm-request-c-wrappers")
|> convert_vector_to_llvm
|> convert_memref_to_llvm
|> convert_func_to_llvm
|> reconcile_unrealized_casts
|> MLIR.Pass.Composer.run!()
1 Like

Very interesting! I like the full end to end too , beaver/tosa_test.exs at main · beaver-lodge/beaver · GitHub . I haven’t looked in any detail, but my first two questions that came to mind from that example:

Can one access interfaces?

What about alternative build methods? (And this is me also not knowing the language).

They are not supported. Everything related to C++ template and TableGen is not supported.
The dialect/op registry is being used at Elixir compile time to generate functions.
Is there anything in the upstream could be leveraged to support interface and alternative build methods?

Good question, depends on if you are using the C API or C++ one? If the former, not that I’m aware of (but I’m planning on exposing one or two method “soon” that could enable a currently interface of interest there via C API but it’s more on my wishlist than anything blocking).

That’s nice, and so this is done without any ODS info? Then your generators are quite nice, I didn’t think we had enough introspective info without ODS.

I’m using CAPI whenever it is possible. Feel free to shared some points where I might be able to contribute. I guess we could start by adding CAPI to check if an Op overrides an interface🤔.

It’s done without using ODS by iterating every op in every dialect. But I haven’t found a approach applicable for attributes.

This is really cool. I like Elixir and I have been hopeful some work in Elixir for MLIR might show up. I’m especially interested in the goals section of the README. It seems like the focus has been on using Elixir as a FE to MLIR, but you do mention compiling Elixir as a goal. Does that mean using Beaver to define IR(s) and compiler transformations for Elixir/Erlang programs? If so, I’m interested to see where that goes.

I am unfortunately on the Erlang side. There is an MLIR Erlang compiler.

1 Like

(I’ll make a plug for Users of MLIR - MLIR and mlir-www/_index.md at main · llvm/mlir-www · GitHub where folks can propose additions)

Yes unfortunately ODS is the only place where we have those today. From ODS we could dump some metadata which you could consume or utilize it, it’ll be a bit heuristical/match on strings for some of these.

Yes, you can do it by transforming Elixir AST into MLIR. There is a dummy example here beaver/cf_test.exs at main · beaver-lodge/beaver · GitHub

1 Like

A PR is created~ Add Beaver by jackalcooper · Pull Request #130 · llvm/mlir-www · GitHub