Hi all,
Today MLIR has a relatively rich syntactic framework based on SSA form. Fundamentally, this means that every value is defined by a single operation (single-def), and every value is defined before it is used (dominance). When combined with some other basic primitives (e.g. Ops, Attrs, SymbolTables, Blocks, and Regions) and Transformations, we have a syntactic foundation to build and manipulate many dialects.
These might include the traditional notion of CDFGs (e.g. LLVM dialect), CDFGs restricted to structured control flow (Loop/SCF dialect), and higher level abstractions (Affine+Tensorflow dialects).
However, not all operations or all dialects require all of the richness of the structural foundation. For instance, operations can opt-out of some complexity of Blocks using the SingleBlockImplicitTerminator trait. Itâs also possible to constrain the use of hierarchy. Some of this is opt-in (e.g., an op declare that it has regions, the default is no regions) and some is opt-out (e.g., the HasParent<> trait restricts the potential containers of an operation).
Iâd like to propose that we offer dialects an additional configuration mechanism to enable or disable the SSA-dominance property. This property is important for CDFG analysis and semantics, but is not necessary for some other semantic models. This would allow dialects to express that this kind of IR is legal:
%1 = op(%2) %2 = op(%1)
Currently, the feedback loop has to be broken in some way using a terminator that preserves the dominance property, for instance something like:
func @simple(%arg : i32) { br ^bb1(%arg : i32) ^bb1 (%a: i32): %1 = "testop"(%a) : (i32) -> (i32) %2 = "testop"(%1) : (i32) -> (i32) br ^bb1(%2 : i32) }
In particular, weâre interested in various hardware-oriented semantic models where feedback and concurrency are common.
One such kind of model is dataflow/Kahn Process Network models. We have a prototype of such a dialect implemented in MLIR today. In the future, we expect to build RTL-style models used for composing IP in a chip design. While not completely a a showstopper, the syntactic constraints of SSA-dominance makes implementing these models significantly more awkward. Our existing prototype relies on disabling the verifier check relating to dominance, but most other mechanisms seem to work as expected. In particular, printing and parsing work fine. We currently transform into this dialect, but do not perform optimizations on this dialect. I expect that the existing algorithms should work fine or require minimal modification. In particular, Iâd expect that we can build a system using declarative rewrite rules where matching the two connected op possibilities %1 â %2 and %2 â 1 are equivalent, which is not possible in the existing system (which would require having some rewrite rule match around a back edge).
So basically, I have two questions:
- What are peopleâs reactions to this? Are there fundamental objections? In particular, Iâm sensitive that some may feel that this is completely out of scope for what MLIR is trying to do, to the extent that it should be actively discouraged. In such case, I can see us needing to build our own MLIR-like syntactic framework (or more likely fork MLIR to allow this).
- In lieu of fundamental objections: What form should this take? opt-in, requring the addition of a Dominance traits to (most) existing operations with regions? This trait could presumably be responsible for verifying the condition itself, taking ownership of code which is currently in the global verifier. opt-out, disabling the existing verifier code for some operations with regions, or some other form?