Goal
To define a new, lightweight class of dialects that exist for the purpose of interop between projects in the ecosystem.
Motivation
I’ve been having discussions with a few folks about introducing an explicit class of “border dialects” (I have sometimes referred to these as “interface dialects” but this is easily confused with “dialect interfaces”) and wanted to get some pre-feedback on the line of thought before spending a ton of time on formalizing it.
As the MLIR ecosystem is growing, we are facing various interop frictions between projects, and so far this has created an asymmetry between in-tree and out-of-tree projects with respect to their ability to foster their own ecosystems without fragmenting the overall space. For things that are aligned with eventually going upstream, there are clear answers here (i.e. upstream your project), but there are legitimate reasons for projects to exist apart from the llvm-project
proper yet still seek to interop with the ecosystem.
In my part of the world, this includes projects like IREE, TensorFlow, MHLO, JAX, ONNX, TOSA, etc. We’ve collectively made different decisions or non-decisions about each of these – for the Google aligned projects, we lean heavily on the “big Google integrate” to produce regular stable commits that are consistent. We do this at a pretty high cost, and even for us, it is an ultimately unmaintainable mechanism to be using to assure a fairly basic level of interoperability between components. This process is also quite opaque and inaccessible to anyone not-Google. I would like to start taking steps to unwinding our dependence on this while increasing the level of decoupling that we can support within the MLIR ecosystem.
The lack of solutions in this area has arguably also prompted some other degenerate behavior: since upstream is the only place that projects can effectively intersect, there is some motivation to push bits and pieces of tech where the utility only emerges within the full assembly of a downstream project (I don’t ascribe ill-intent here: I think there is often an intent to build out a more complete upstream component, but reality and other priorities can intervene).
I don’t think that there is any single mechanism or convention that will set all of this onto a better path, but I would like to advocate for one thing that I think we could introduce which would at least allow for downstream projects to design for decoupling and interop: an open registry of border dialects.
The idea is simple: Whereas most of the dialects in the MLIR system are accepted as a matter of design (i.e. do they serve a purpose to the upstream community, are they orthogonal or have well understood overlap with adjacent dialects, etc), we can introduce a new class of dialects that is specifically about interoperability between components. The justification for such a dialect to be accepted would be based on whether there exists a community to support it, it met certain standards, and it existed to aid interop between projects.
Definition
I would argue that introducing such a class of dialects would give us a rallying point to build out further infra important for interfacing components:
- Tooling and conventions for dialect versioning
- Efficient binary serialization (i.e. an equivalent to bitcode)
- Tools for upgrading/downgrading/etc
- Namespacing conventions
- Build tooling for managing/registering dialects
Since these dialects are about interfacing components and not transformation, we could likely enforce some further restrictions on them in order to minimize maintenance costs:
- Tablegen ODS only (limited use of advanced, C++ features)
- Upgrade/downgrade via DRR (or PDL in the future?)
- Requires version stability for ops and types
- Self contained
Examples
To give some concrete examples, with some refactoring, all of the following could be characterized as Border Dialects:
- TOSA: Stable, versioned representation of mid-level ML operations, intended to be used as an input specification for ML compilers.
- IREE’s
flow
dialect: Structural ingress dialect representing the input to the IREE compiler, including types and ops that expose features specific to IREE’s conception of a runtime. - IREE’s
hal
dialect: Plugin dialect for inputs to separately compiled target-specific compiler backends. - MHLO: Mid-level MLIR representation of the historic XLA op set.
- ONNX: Standards-based ML frontend dialect for representing whole ML models
It seems likely that for non trivial systems (i.e. IREE, XLA, etc), the system may choose to expose a set of public Border Dialects directly in the upstream llvm-project
while maintaining other private, transformation oriented implementation dialects internally (possibly even duplicating the border dialects between import and implementation layers in order to facilitate decoupling).
Feedback?
I think that if we started small on this with some basic standards and a namespace, we could unlock some really nice benefits and create some room for more stability/ecosystem focused work in the future. Curious what others think about this approach specifically? Also curious if there are other ecosystem-stability related things we should be considering.
Thanks.
Stella