Why don't operations in "predefined" dialects follow MLIR opertions syntex?

Hello everyone! I am learning MLIR and have a question about the MLIR operation syntax.

From my understanding, all operations in MLIRIR should follow the syntax shown below based on MLIR Language Ref.

operation            ::= op-result-list? (generic-operation | custom-operation)
generic-operation    ::= string-literal `(` value-use-list? `)`  successor-list?
                         region-list? dictionary-attribute? `:` function-type
custom-operation     ::= bare-id custom-operation-format
op-result-list       ::= op-result (`,` op-result)* `=`
op-result            ::= value-id (`:` integer-literal)
successor-list       ::= `[` successor (`,` successor)* `]`
successor            ::= caret-id (`:` block-arg-list)?
region-list          ::= `(` region (`,` region)* `)`
dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)? `}`
trailing-location    ::= (`loc` `(` location `)`)?

But, I found almost all operations in “predefined” dialect don’t follow this syntax, for example,

func.func operation:

func.func @scribble(i32, i64, memref<? x 128 x f32, #layout_map0>) -> f64

arith.addf operation:

%a = arith.addf %b, %c : f64

affine.for operation:

affine.for %i = 0 to %N { ... }

and many many others.

Are there something I misunderstood? or “predefined” operations are indeed special.

Thank you!

The language guide describes the generic syntax that is used if an op or dialect doesn’t define a custom/pretty form. Any op in any dialect can define its only syntax. So its not anything special or predefined, its something any dialect can opt-in to. Many uses Operation Definition Specification (ODS) - MLIR or custom C++ code to print it in a form that it is easier to read for specific group. E.g., func.func shows operand attributes inline as its more intuitive for folks while the generic shows it at end. --mlir-print-op-generic shows the generic form for ops by default/avoids usage of custom/pretty format.

1 Like

There’s nothing privileged about these operations. The dialects they’re in aren’t “pre-defined”. They just happened to have their code in the monorepo. Any operation can define a custom syntax. That’s the custom-operation bit in your code block. This is mentioned briefly in that documentation block and there’s more info on how those can get defined in tablegen in the ODS docs. It does seem like that could be called out more explicitly with links to supporting documentation in the LangRef though. @River707 is there a place it could link to that’s about the general concept of custom assembly rather than the specific ODS implementation?

1 Like

Thank you, @jpienaar and @gcmn, for the kind explanation. It is really helpful!