Swift and MLIR

Question

I write Swift. What’s the best way to lower S-expressions representing a high-level, feature-rich language like Swift to MLIR?

What is Swift?

Swift is high-level and feature-rich. Some features:

  • let constant variable bindings and var mutable variable bindings.
  • Structs (value types), classes (reference types), enums (algebraic data types).
  • Statically typed: all values have a compile-time type and a runtime type.
  • Protocols and conformances: traits/typeclasses and their implementations/instances for specific conforming types.
  • First-class functions: need “lambdas” in the language representation.
  • Higher-order functions: Array.map, Array.filter, Array.flatMap, Array.forEach.
  • C-style structured control flow constructs: if, for-in, while.
  • Exceptions: try and catch.
  • Separate compilation: function declarations may exist that have no body. “Optimizations required for correctness” like inlining are bad.
  • More! Let’s start with a small core and grow our coverage (ambition) though.

What do I want from MLIR?

Plugging a frontend language into MLIR (e.g. implementing Swift → MLIR) is easiest when there is a MLIR dialect (or multiple) that is similar in abstraction level to the frontend language.

I would like an MLIR dialect that’s the easiest target for Swift, which is described above.

Any ideas? Also, I’m going to need some MLIR builder C APIs so I can import them in Swift. (until Swift gets sufficiently powerful C++ interop)

Thanks!

1 Like

Hey Dan,

I’m missing where S-expressions come in. Meaning, what changes due to this. I think it is the “what do you want to achieve” part I’m missing :slight_smile:

Is the idea to represent the entire Swift language in MLIR? Have it be a frontend for a specific domain? Make it easy to target via Swift’s function builders? (I assume you know Eugene and Alex’s work there. Represent SIL (effectively) as a dialect etc.

Some good progress there which you may have seen on the other threads/code. And I believe @GeorgeL was also looking at that area from Swift side.

1 Like

Hey Jacques!

I’m still hacking, so I don’t have a clear goal (use case) yet. S-expressions and MLIR IR are just program representations, right - they don’t inherently have a goal.

I guess I’d like to translate to MLIR as a first step. Then Swift can do whatever the MLIR dialects support!

lib/IRGen transforms SIL into LLVM IR
how about starting with
lib/MLIRGen to transform SIL into a SIL dialect in MLIR?

Swift compiler + MLIR integration could make sense some day (a SIL dialect). That’s pretty heavyweight.

I’m trying a more lightweight approach, pushing as much “compilation” to runtime as possible. See:

Hey Dan, as Jacques mentioned, I’d sync up with @GeorgeL about this. He’s starting to investigate MLIR bindings for Swift, for exactly the sort of purposes that you’re interested in.

1 Like

Howdy @GeorgeL. Have you looked into importing MLIR into Swift? I saw you wrote some question posts about various MLIR C APIs.

Hi Dan,

The way I see it, Swift bindings for MLIR is actually two projects: The first is simply binding the MLIR C API, and the second is creating a TableGen backend to generate Swift code for arbitrary dialects. I’ve made some good progress on the first bit, but haven’t yet begun to tackle the second bit. My work is not currently in a shareable state, but it wouldn’t be too hard to clean it up enough so that other folks can play around with it after reading a long disclaimer :slight_smile: . I’d also be happy to jump on a call at some point and chat about what you are working on.

In response to your other question, I’m by no means an expert on MLIR, but the way I see it “Swift on MLIR” would involve a set of dialects. Some of the lower-level things are likely handled by existing dialects, but we would almost certainly need to create new dialects for the various higher level Swift concepts.

1 Like

Thanks for the context George!

I’d be interested in calling maybe when one of us has code in a shareable state. I’m happy to play with your bindings whenever they’re ready :smiley:

Open discussion: which parts of Swift are representable in existing dialects and which (from the list in the OP) need new dialects?

Do you want to represent Swift in MLIR?
Do you want a dialect in MLIR that is semantically equivalent to SIL?

Probably not, to start. SIL is complex and this would be a heavyweight effort.

Yes, for some higher-level representation of Swift. The Swift IR would be general, with nodes like Symbol("x") and Op("name", arguments: [...]). I’d like to translate the Swift IR to MLIR.

My questions:

  • The obvious approach is to create a brand new Swift dialect in MLIR and represent everything in that dialect. I wonder what can I represent from Swift IR in MLIR using existing dialects?
    • Programs using primitive types like Int and Float? Mutation? Loops?
  • Swift has struct, class, and enum types. Can I avoid creating a Swift dialect to represent these in MLIR?

There are builtin types for integers and floats. I’m not sure about mutation but there are loop-like constructs in the “SCF” dialect.

OK, so insert-long-disclaimer-here, but I’ve cleaned up my Swift bindings project enough to let folks take a look. I removed any dependencies on commits to LLVM I haven’t yet upstreamed, but as of this writing check-mlir fails for me on master. The most recent commit I’ve used that works is 29807a023ce.

I would love for whoever-is-interested to take a look (@ftynse @stellaraccident: no pressure, but if you’ve been wondering why I’ve been bugging you so much here it is :slight_smile: ). The code is still a little rough and specific to my use case, but I think it is good enough to serve as a basis for discussion of what Swift bindings for MLIR should look like. I’m not committed to any of the design decisions I’ve made up to this point, and I’m very interested in more folks getting involved so I would love to hear your thoughts!

1 Like

Fantastic! I’m having some build trouble, do you have time to call? I’ll DM you.

$ cmake -G Ninja ../llvm \
  -DCMAKE_INSTALL_PREFIX=${MLIR_INSTALL_LOCATION} \
  -DCMAKE_BUILD_TYPE=Release \
  -DLLVM_ENABLE_ASSERTIONS=ON \
  -DLLVM_OPTIMIZED_TABLEGEN=ON \
  -DLLVM_ENABLE_PROJECTS=mlir \
  -DLLVM_TARGETS_TO_BUILD=x86 \
  -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=x86

...

CMake Error at cmake/modules/LLVM-Config.cmake:136 (message):
  Target x86 is not in the set of libraries.
Call Stack (most recent call first):
  cmake/modules/LLVM-Config.cmake:254 (llvm_expand_pseudo_components)
  cmake/modules/LLVM-Config.cmake:100 (llvm_map_components_to_libnames)
  cmake/modules/LLVM-Config.cmake:93 (explicit_llvm_config)
  cmake/modules/AddLLVM.cmake:905 (llvm_config)
  cmake/modules/AddLLVM.cmake:1206 (add_llvm_executable)
  tools/llvm-gsymutil/CMakeLists.txt:11 (add_llvm_tool)


-- Configuring incomplete, errors occurred!
See also "/Users/danielzheng/llvm-project/build/CMakeFiles/CMakeOutput.log".
See also "/Users/danielzheng/llvm-project/build/CMakeFiles/CMakeError.log"

I think this might be a typo, and the target should be X86 (with a capital X). I was using “host” before but needed to pick a specific one when I unwound some of my other LLVM changes, so hopefully we can make it easier to choose different targets in the future.

1 Like

Thanks! It works:

$ ninja check-mlir
[0/1] Running the MLIR regression tests

Testing Time: 7.79s
  Unsupported:  93
  Passed     : 616

$ ninja $(~/MLIRSwift/Utilities/mlir-install-targets)
[0/156] cd /Users/danielzheng/llvm-pr...lvm-project/build/cmake_install.cmake
-- Install configuration: "Release"
-- Installing: /Users/danielzheng/mlir/include/mlir
-- Installing: /Users/danielzheng/mlir/include/mlir/InitAllTranslations.h
-- Installing: /Users/danielzheng/mlir/include/mlir/Rewrite
-- Installing: /Users/danielzheng/mlir/include/mlir/Rewrite/PatternApplicator.h
-- Installing: /Users/danielzheng/mlir/include/mlir/Rewrite/FrozenRewritePatternList.h
-- Installing: /Users/danielzheng/mlir/include/mlir/Analysis
...

I wonder what is the ninja $(MLIRSwift/Utilities/mlir-install-targets) install location?

The install location will be whatever you specified for CMAKE_INSTALL_PREFIX

1 Like

Hi George,
I work for Stella Lorenzo at Google and would like to chat with you about your work and the Swift work I’ve been doing this year. I’m new on the forum, so I don’t seem to be able to message you directly yet.

Thanks, Ed

Welcome to the community, Ed! I myself am somewhat new and learning as I go but I’ve recently been bestowed direct messaging privileges and sent you one.

Not sure who is still interested, but I just pushed a big update to the bindings (https://github.com/GeorgeLyon/MLIRSwift), and updated it to work with a recent MLIR commit. There are a number of improvements, not the least of which is a new ownership system, which tracks whether an MLIR value is owned by Swift or MLIR using generics. This project is getting pretty close to a point where I’d love to start getting feedback, so if you are curious I encourage you to take a look!

2 Likes