2020-04-12 02:38:05 +08:00
|
|
|
# MLIR Language Reference
|
2018-10-25 00:47:36 +08:00
|
|
|
|
2019-07-19 01:34:19 +08:00
|
|
|
MLIR (Multi-Level IR) is a compiler intermediate representation with
|
|
|
|
similarities to traditional three-address SSA representations (like
|
2018-10-25 00:47:36 +08:00
|
|
|
[LLVM IR](http://llvm.org/docs/LangRef.html) or
|
2021-11-04 03:41:24 +08:00
|
|
|
[SIL](https://github.com/apple/swift/blob/main/docs/SIL.rst)), but which
|
2018-10-25 00:47:36 +08:00
|
|
|
introduces notions from polyhedral loop optimization as first-class concepts.
|
|
|
|
This hybrid design is optimized to represent, analyze, and transform high level
|
|
|
|
dataflow graphs as well as target-specific code generated for high performance
|
|
|
|
data parallel systems. Beyond its representational capabilities, its single
|
|
|
|
continuous design provides a framework to lower from dataflow graphs to
|
|
|
|
high-performance target-specific code.
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
This document defines and describes the key concepts in MLIR, and is intended to
|
|
|
|
be a dry reference document - the
|
|
|
|
[rationale documentation](Rationale/Rationale.md),
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
[glossary](../getting_started/Glossary.md), and other content are hosted
|
|
|
|
elsewhere.
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
MLIR is designed to be used in three different forms: a human-readable textual
|
|
|
|
form suitable for debugging, an in-memory form suitable for programmatic
|
2021-10-13 07:14:57 +08:00
|
|
|
transformations and analysis, and a compact serialized form suitable for storage
|
|
|
|
and transport. The different forms all describe the same semantic content. This
|
|
|
|
document describes the human-readable textual form.
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
[TOC]
|
|
|
|
|
2019-04-05 23:19:42 +08:00
|
|
|
## High-Level Structure
|
2018-10-25 00:47:36 +08:00
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
MLIR is fundamentally based on a graph-like data structure of nodes, called
|
|
|
|
*Operations*, and edges, called *Values*. Each Value is the result of exactly
|
2021-10-13 07:14:57 +08:00
|
|
|
one Operation or Block Argument, and has a *Value Type* defined by the
|
|
|
|
[type system](#type-system). [Operations](#operations) are contained in
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
[Blocks](#blocks) and Blocks are contained in [Regions](#regions). Operations
|
|
|
|
are also ordered within their containing block and Blocks are ordered in their
|
2021-10-13 07:14:57 +08:00
|
|
|
containing region, although this order may or may not be semantically meaningful
|
|
|
|
in a given [kind of region](Interfaces.md/#regionkindinterfaces)). Operations
|
|
|
|
may also contain regions, enabling hierarchical structures to be represented.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
Operations can represent many different concepts, from higher-level concepts
|
2021-10-13 07:14:57 +08:00
|
|
|
like function definitions, function calls, buffer allocations, view or slices of
|
|
|
|
buffers, and process creation, to lower-level concepts like target-independent
|
|
|
|
arithmetic, target-specific instructions, configuration registers, and logic
|
|
|
|
gates. These different concepts are represented by different operations in MLIR
|
|
|
|
and the set of operations usable in MLIR can be arbitrarily extended.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
MLIR also provides an extensible framework for transformations on operations,
|
|
|
|
using familiar concepts of compiler [Passes](Passes.md). Enabling an arbitrary
|
2021-10-13 07:14:57 +08:00
|
|
|
set of passes on an arbitrary set of operations results in a significant scaling
|
|
|
|
challenge, since each transformation must potentially take into account the
|
|
|
|
semantics of any operation. MLIR addresses this complexity by allowing operation
|
|
|
|
semantics to be described abstractly using [Traits](Traits.md) and
|
|
|
|
[Interfaces](Interfaces.md), enabling transformations to operate on operations
|
|
|
|
more generically. Traits often describe verification constraints on valid IR,
|
|
|
|
enabling complex invariants to be captured and checked. (see
|
|
|
|
[Op vs Operation](Tutorials/Toy/Ch-2.md/#op-vs-operation-using-mlir-operations))
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
One obvious application of MLIR is to represent an
|
2018-10-25 00:47:36 +08:00
|
|
|
[SSA-based](https://en.wikipedia.org/wiki/Static_single_assignment_form) IR,
|
2021-03-20 09:19:16 +08:00
|
|
|
like the LLVM core IR, with appropriate choice of operation types to define
|
|
|
|
Modules, Functions, Branches, Memory Allocation, and verification constraints to
|
|
|
|
ensure the SSA Dominance property. MLIR includes a collection of dialects which
|
|
|
|
defines just such structures. However, MLIR is intended to be general enough to
|
|
|
|
represent other compiler-like data structures, such as Abstract Syntax Trees in
|
|
|
|
a language frontend, generated instructions in a target-specific backend, or
|
|
|
|
circuits in a High-Level Synthesis tool.
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
Here's an example of an MLIR module:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-01-03 04:32:30 +08:00
|
|
|
// Compute A*B using an implementation of multiply kernel and print the
|
2018-10-25 00:47:36 +08:00
|
|
|
// result using a TensorFlow op. The dimensions of A and B are partially
|
|
|
|
// known. The shapes are assumed to match.
|
2019-01-03 04:32:30 +08:00
|
|
|
func @mul(%A: tensor<100x?xf32>, %B: tensor<?x50xf32>) -> (tensor<100x50xf32>) {
|
2018-10-25 00:47:36 +08:00
|
|
|
// Compute the inner dimension of %A using the dim operation.
|
2021-10-13 07:14:57 +08:00
|
|
|
%n = memref.dim %A, 1 : tensor<100x?xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
// Allocate addressable "buffers" and copy tensors %A and %B into them.
|
2021-10-13 07:14:57 +08:00
|
|
|
%A_m = memref.alloc(%n) : memref<100x?xf32>
|
|
|
|
memref.tensor_store %A to %A_m : memref<100x?xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
%B_m = memref.alloc(%n) : memref<?x50xf32>
|
|
|
|
memref.tensor_store %B to %B_m : memref<?x50xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
|
2019-02-06 08:29:25 +08:00
|
|
|
// Call function @multiply passing memrefs as arguments,
|
2018-10-25 00:47:36 +08:00
|
|
|
// and getting returned the result of the multiplication.
|
|
|
|
%C_m = call @multiply(%A_m, %B_m)
|
|
|
|
: (memref<100x?xf32>, memref<?x50xf32>) -> (memref<100x50xf32>)
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
memref.dealloc %A_m : memref<100x?xf32>
|
|
|
|
memref.dealloc %B_m : memref<?x50xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
// Load the buffer data into a higher level "tensor" value.
|
2021-10-13 07:14:57 +08:00
|
|
|
%C = memref.tensor_load %C_m : memref<100x50xf32>
|
|
|
|
memref.dealloc %C_m : memref<100x50xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
// Call TensorFlow built-in function to print the result tensor.
|
|
|
|
"tf.Print"(%C){message: "mul result"}
|
|
|
|
: (tensor<100x50xf32) -> (tensor<100x50xf32>)
|
|
|
|
|
|
|
|
return %C : tensor<100x50xf32>
|
|
|
|
}
|
|
|
|
|
2019-01-03 04:32:30 +08:00
|
|
|
// A function that multiplies two memrefs and returns the result.
|
|
|
|
func @multiply(%A: memref<100x?xf32>, %B: memref<?x50xf32>)
|
2018-10-25 00:47:36 +08:00
|
|
|
-> (memref<100x50xf32>) {
|
|
|
|
// Compute the inner dimension of %A.
|
2021-10-13 07:14:57 +08:00
|
|
|
%n = memref.dim %A, 1 : memref<100x?xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
// Allocate memory for the multiplication result.
|
2021-10-13 07:14:57 +08:00
|
|
|
%C = memref.alloc() : memref<100x50xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
// Multiplication loop nest.
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 0 to 100 {
|
|
|
|
affine.for %j = 0 to 50 {
|
2021-10-13 07:14:57 +08:00
|
|
|
memref.store 0 to %C[%i, %j] : memref<100x50xf32>
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %k = 0 to %n {
|
2021-10-13 07:14:57 +08:00
|
|
|
%a_v = memref.load %A[%i, %k] : memref<100x?xf32>
|
|
|
|
%b_v = memref.load %B[%k, %j] : memref<?x50xf32>
|
|
|
|
%prod = arith.mulf %a_v, %b_v : f32
|
|
|
|
%c_v = memref.load %C[%i, %j] : memref<100x50xf32>
|
|
|
|
%sum = arith.addf %c_v, %prod : f32
|
|
|
|
memref.store %sum, %C[%i, %j] : memref<100x50xf32>
|
2018-10-25 00:47:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return %C : memref<100x50xf32>
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2019-04-05 23:19:42 +08:00
|
|
|
## Notation
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
MLIR has a simple and unambiguous grammar, allowing it to reliably round-trip
|
2021-10-13 07:14:57 +08:00
|
|
|
through a textual form. This is important for development of the compiler - e.g.
|
|
|
|
for understanding the state of code as it is being transformed and writing test
|
|
|
|
cases.
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
This document describes the grammar using
|
|
|
|
[Extended Backus-Naur Form (EBNF)](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form).
|
|
|
|
|
|
|
|
This is the EBNF grammar used in this document, presented in yellow boxes.
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2018-10-25 00:47:36 +08:00
|
|
|
alternation ::= expr0 | expr1 | expr2 // Either expr0 or expr1 or expr2.
|
|
|
|
sequence ::= expr0 expr1 expr2 // Sequence of expr0 expr1 expr2.
|
|
|
|
repetition0 ::= expr* // 0 or more occurrences.
|
|
|
|
repetition1 ::= expr+ // 1 or more occurrences.
|
|
|
|
optionality ::= expr? // 0 or 1 occurrence.
|
|
|
|
grouping ::= (expr) // Everything inside parens is grouped together.
|
|
|
|
literal ::= `abcd` // Matches the literal `abcd`.
|
|
|
|
```
|
|
|
|
|
|
|
|
Code examples are presented in blue boxes.
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2018-10-25 00:47:36 +08:00
|
|
|
// This is an example use of the grammar above:
|
|
|
|
// This matches things like: ba, bana, boma, banana, banoma, bomana...
|
|
|
|
example ::= `b` (`an` | `om`)* `a`
|
|
|
|
```
|
|
|
|
|
2019-04-05 23:19:42 +08:00
|
|
|
### Common syntax
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
The following core grammar productions are used in this document:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2018-10-25 00:47:36 +08:00
|
|
|
// TODO: Clarify the split between lexing (tokens) and parsing (grammar).
|
|
|
|
digit ::= [0-9]
|
|
|
|
hex_digit ::= [0-9a-fA-F]
|
|
|
|
letter ::= [a-zA-Z]
|
|
|
|
id-punct ::= [$._-]
|
|
|
|
|
2019-02-08 00:36:50 +08:00
|
|
|
integer-literal ::= decimal-literal | hexadecimal-literal
|
|
|
|
decimal-literal ::= digit+
|
|
|
|
hexadecimal-literal ::= `0x` hex_digit+
|
2019-11-26 09:53:20 +08:00
|
|
|
float-literal ::= [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)?
|
2020-07-07 16:35:23 +08:00
|
|
|
string-literal ::= `"` [^"\n\f\v\r]* `"` TODO: define escaping rules
|
2018-10-25 00:47:36 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
Not listed here, but MLIR does support comments. They use standard BCPL syntax,
|
|
|
|
starting with a `//` and going until the end of the line.
|
|
|
|
|
2022-01-21 19:32:39 +08:00
|
|
|
|
|
|
|
### Top level Productions
|
|
|
|
|
|
|
|
```
|
|
|
|
// Top level production
|
|
|
|
toplevel := (operation | attribute-alias-def | type-alias-def)*
|
|
|
|
```
|
|
|
|
|
|
|
|
The production `toplevel` is the top level production that is parsed by any parsing
|
|
|
|
consuming the MLIR syntax. [Operations](#operations),
|
|
|
|
[Attribute alises](#attribute-value-aliases), and [Type aliases](#type-aliases)
|
|
|
|
can be declared on the toplevel.
|
|
|
|
|
2019-04-05 23:19:42 +08:00
|
|
|
### Identifiers and keywords
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
Syntax:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2018-10-25 00:47:36 +08:00
|
|
|
// Identifiers
|
2019-02-27 08:43:12 +08:00
|
|
|
bare-id ::= (letter|[_]) (letter|digit|[_$.])*
|
2018-10-25 00:47:36 +08:00
|
|
|
bare-id-list ::= bare-id (`,` bare-id)*
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
value-id ::= `%` suffix-id
|
2019-12-05 04:05:52 +08:00
|
|
|
suffix-id ::= (digit+ | ((letter|id-punct) (letter|id-punct|digit)*))
|
2018-10-25 00:47:36 +08:00
|
|
|
|
2019-12-05 04:05:52 +08:00
|
|
|
symbol-ref-id ::= `@` (suffix-id | string-literal)
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
value-id-list ::= value-id (`,` value-id)*
|
2018-10-25 00:47:36 +08:00
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
// Uses of value, e.g. in an operand list to an operation.
|
|
|
|
value-use ::= value-id
|
|
|
|
value-use-list ::= value-use (`,` value-use)*
|
2018-10-25 00:47:36 +08:00
|
|
|
```
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
Identifiers name entities such as values, types and functions, and are chosen by
|
|
|
|
the writer of MLIR code. Identifiers may be descriptive (e.g. `%batch_size`,
|
|
|
|
`@matmul`), or may be non-descriptive when they are auto-generated (e.g. `%23`,
|
|
|
|
`@func42`). Identifier names for values may be used in an MLIR text file but are
|
|
|
|
not persisted as part of the IR - the printer will give them anonymous names
|
|
|
|
like `%42`.
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
MLIR guarantees identifiers never collide with keywords by prefixing identifiers
|
2019-04-06 10:36:42 +08:00
|
|
|
with a sigil (e.g. `%`, `#`, `@`, `^`, `!`). In certain unambiguous contexts
|
|
|
|
(e.g. affine expressions), identifiers are not prefixed, for brevity. New
|
|
|
|
keywords may be added to future versions of MLIR without danger of collision
|
|
|
|
with existing identifiers.
|
2018-10-25 00:47:36 +08:00
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
Value identifiers are only [in scope](#value-scoping) for the (nested) region in
|
|
|
|
which they are defined and cannot be accessed or referenced outside of that
|
|
|
|
region. Argument identifiers in mapping functions are in scope for the mapping
|
|
|
|
body. Particular operations may further limit which identifiers are in scope in
|
|
|
|
their regions. For instance, the scope of values in a region with
|
|
|
|
[SSA control flow semantics](#control-flow-and-ssacfg-regions) is constrained
|
|
|
|
according to the standard definition of
|
|
|
|
[SSA dominance](https://en.wikipedia.org/wiki/Dominator_\(graph_theory\)).
|
|
|
|
Another example is the [IsolatedFromAbove trait](Traits.md/#isolatedfromabove),
|
|
|
|
which restricts directly accessing values defined in containing regions.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
Function identifiers and mapping identifiers are associated with
|
2021-10-13 07:14:57 +08:00
|
|
|
[Symbols](SymbolsAndSymbolTables.md) and have scoping rules dependent on symbol
|
|
|
|
attributes.
|
2018-10-25 00:47:36 +08:00
|
|
|
|
2019-08-23 06:53:41 +08:00
|
|
|
## Dialects
|
|
|
|
|
2019-11-16 01:48:54 +08:00
|
|
|
Dialects are the mechanism by which to engage with and extend the MLIR
|
2019-08-23 06:53:41 +08:00
|
|
|
ecosystem. They allow for defining new [operations](#operations), as well as
|
|
|
|
[attributes](#attributes) and [types](#type-system). Each dialect is given a
|
|
|
|
unique `namespace` that is prefixed to each defined attribute/operation/type.
|
|
|
|
For example, the [Affine dialect](Dialects/Affine.md) defines the namespace:
|
|
|
|
`affine`.
|
|
|
|
|
|
|
|
MLIR allows for multiple dialects, even those outside of the main tree, to
|
|
|
|
co-exist together within one module. Dialects are produced and consumed by
|
|
|
|
certain passes. MLIR provides a [framework](DialectConversion.md) to convert
|
2019-11-16 01:48:54 +08:00
|
|
|
between, and within, different dialects.
|
2019-08-23 06:53:41 +08:00
|
|
|
|
|
|
|
A few of the dialects supported by MLIR:
|
|
|
|
|
|
|
|
* [Affine dialect](Dialects/Affine.md)
|
|
|
|
* [GPU dialect](Dialects/GPU.md)
|
|
|
|
* [LLVM dialect](Dialects/LLVM.md)
|
|
|
|
* [SPIR-V dialect](Dialects/SPIR-V.md)
|
|
|
|
* [Standard dialect](Dialects/Standard.md)
|
|
|
|
* [Vector dialect](Dialects/Vector.md)
|
|
|
|
|
|
|
|
### Target specific operations
|
|
|
|
|
|
|
|
Dialects provide a modular way in which targets can expose target-specific
|
|
|
|
operations directly through to MLIR. As an example, some targets go through
|
|
|
|
LLVM. LLVM has a rich set of intrinsics for certain target-independent
|
|
|
|
operations (e.g. addition with overflow check) as well as providing access to
|
2021-10-13 07:14:57 +08:00
|
|
|
target-specific operations for the targets it supports (e.g. vector permutation
|
|
|
|
operations). LLVM intrinsics in MLIR are represented via operations that start
|
|
|
|
with an "llvm." name.
|
2019-08-23 06:53:41 +08:00
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-08-23 06:53:41 +08:00
|
|
|
// LLVM: %x = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)
|
|
|
|
%x:2 = "llvm.sadd.with.overflow.i16"(%a, %b) : (i16, i16) -> (i16, i1)
|
|
|
|
```
|
|
|
|
|
|
|
|
These operations only work when targeting LLVM as a backend (e.g. for CPUs and
|
|
|
|
GPUs), and are required to align with the LLVM definition of these intrinsics.
|
|
|
|
|
2019-08-24 01:08:42 +08:00
|
|
|
## Operations
|
|
|
|
|
|
|
|
Syntax:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2021-04-06 12:32:23 +08:00
|
|
|
operation ::= op-result-list? (generic-operation | custom-operation)
|
|
|
|
trailing-location?
|
|
|
|
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 (`:` bb-arg-list)?
|
|
|
|
region-list ::= `(` region (`,` region)* `)`
|
|
|
|
dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)? `}`
|
|
|
|
trailing-location ::= (`loc` `(` location `)`)?
|
2019-08-24 01:08:42 +08:00
|
|
|
```
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
MLIR introduces a uniform concept called *operations* to enable describing many
|
|
|
|
different levels of abstractions and computations. Operations in MLIR are fully
|
|
|
|
extensible (there is no fixed list of operations) and have application-specific
|
|
|
|
semantics. For example, MLIR supports
|
|
|
|
[target-independent operations](Dialects/Standard.md#memory-operations),
|
|
|
|
[affine operations](Dialects/Affine.md), and
|
|
|
|
[target-specific machine operations](#target-specific-operations).
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
The internal representation of an operation is simple: an operation is
|
|
|
|
identified by a unique string (e.g. `dim`, `tf.Conv2d`, `x86.repmovsb`,
|
2021-10-13 07:14:57 +08:00
|
|
|
`ppc.eieio`, etc), can return zero or more results, take zero or more operands,
|
|
|
|
has a dictionary of [attributes](#attributes), has zero or more successors, and
|
|
|
|
zero or more enclosed [regions](#regions). The generic printing form includes
|
|
|
|
all these elements literally, with a function type to indicate the types of the
|
|
|
|
results and operands.
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-08-24 01:08:42 +08:00
|
|
|
// An operation that produces two results.
|
|
|
|
// The results of %result can be accessed via the <name> `#` <opNo> syntax.
|
|
|
|
%result:2 = "foo_div"() : () -> (f32, i32)
|
|
|
|
|
|
|
|
// Pretty form that defines a unique name for each result.
|
|
|
|
%foo, %bar = "foo_div"() : () -> (f32, i32)
|
|
|
|
|
|
|
|
// Invoke a TensorFlow function called tf.scramble with two inputs
|
|
|
|
// and an attribute "fruit".
|
2021-02-05 08:17:45 +08:00
|
|
|
%2 = "tf.scramble"(%result#0, %bar) {fruit = "banana"} : (f32, i32) -> f32
|
2019-08-24 01:08:42 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
In addition to the basic syntax above, dialects may register known operations.
|
2021-10-13 07:14:57 +08:00
|
|
|
This allows those dialects to support *custom assembly form* for parsing and
|
2019-08-24 01:08:42 +08:00
|
|
|
printing operations. In the operation sets listed below, we show both forms.
|
|
|
|
|
2021-03-20 09:19:16 +08:00
|
|
|
### Builtin Operations
|
2019-08-24 01:08:42 +08:00
|
|
|
|
2021-03-20 09:19:16 +08:00
|
|
|
The [builtin dialect](Dialects/Builtin.md) defines a select few operations that
|
|
|
|
are widely applicable by MLIR dialects, such as a universal conversion cast
|
|
|
|
operation that simplifies inter/intra dialect conversion. This dialect also
|
|
|
|
defines a top-level `module` operation, that represents a useful IR container.
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
## Blocks
|
|
|
|
|
|
|
|
Syntax:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2019-12-05 04:05:52 +08:00
|
|
|
block ::= block-label operation+
|
|
|
|
block-label ::= block-id block-arg-list? `:`
|
|
|
|
block-id ::= caret-id
|
|
|
|
caret-id ::= `^` suffix-id
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
value-id-and-type ::= value-id `:` type
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
// Non-empty list of names and types.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
value-id-and-type-list ::= value-id-and-type (`,` value-id-and-type)*
|
|
|
|
|
|
|
|
block-arg-list ::= `(` value-id-and-type-list? `)`
|
|
|
|
```
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
A *Block* is a list of operations. In
|
|
|
|
[SSACFG regions](#control-flow-and-ssacfg-regions), each block represents a
|
|
|
|
compiler [basic block](https://en.wikipedia.org/wiki/Basic_block) where
|
|
|
|
instructions inside the block are executed in order and terminator operations
|
|
|
|
implement control flow branches between basic blocks.
|
|
|
|
|
|
|
|
A region with a single block may not include a
|
|
|
|
[terminator operation](#terminator-operations). The enclosing op can opt-out of
|
|
|
|
this requirement with the `NoTerminator` trait. The top-level `ModuleOp` is an
|
|
|
|
example of such operation which defined this trait and whose block body does not
|
|
|
|
have a terminator.
|
|
|
|
|
|
|
|
Blocks in MLIR take a list of block arguments, notated in a function-like way.
|
|
|
|
Block arguments are bound to values specified by the semantics of individual
|
|
|
|
operations. Block arguments of the entry block of a region are also arguments to
|
|
|
|
the region and the values bound to these arguments are determined by the
|
|
|
|
semantics of the containing operation. Block arguments of other blocks are
|
|
|
|
determined by the semantics of terminator operations, e.g. Branches, which have
|
|
|
|
the block as a successor. In regions with
|
|
|
|
[control flow](#control-flow-and-ssacfg-regions), MLIR leverages this structure
|
|
|
|
to implicitly represent the passage of control-flow dependent values without the
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
complex nuances of PHI nodes in traditional SSA representations. Note that
|
|
|
|
values which are not control-flow dependent can be referenced directly and do
|
|
|
|
not need to be passed through block arguments.
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
Here is a simple example function showing branches, returns, and block
|
|
|
|
arguments:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-08-24 01:08:42 +08:00
|
|
|
func @simple(i64, i1) -> i64 {
|
|
|
|
^bb0(%a: i64, %cond: i1): // Code dominated by ^bb0 may refer to %a
|
|
|
|
cond_br %cond, ^bb1, ^bb2
|
|
|
|
|
|
|
|
^bb1:
|
|
|
|
br ^bb3(%a: i64) // Branch passes %a as the argument
|
|
|
|
|
|
|
|
^bb2:
|
2021-10-13 07:14:57 +08:00
|
|
|
%b = arith.addi %a, %a : i64
|
2019-08-24 01:08:42 +08:00
|
|
|
br ^bb3(%b: i64) // Branch passes %b as the argument
|
|
|
|
|
|
|
|
// ^bb3 receives an argument, named %c, from predecessors
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
// and passes it on to bb4 along with %a. %a is referenced
|
|
|
|
// directly from its defining operation and is not passed through
|
|
|
|
// an argument of ^bb3.
|
2019-08-24 01:08:42 +08:00
|
|
|
^bb3(%c: i64):
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
br ^bb4(%c, %a : i64, i64)
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
^bb4(%d : i64, %e : i64):
|
2021-10-13 07:14:57 +08:00
|
|
|
%0 = arith.addi %d, %e : i64
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
return %0 : i64 // Return is also a terminator.
|
2019-08-24 01:08:42 +08:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
**Context:** The "block argument" representation eliminates a number of special
|
|
|
|
cases from the IR compared to traditional "PHI nodes are operations" SSA IRs
|
|
|
|
(like LLVM). For example, the
|
|
|
|
[parallel copy semantics](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.524.5461&rep=rep1&type=pdf)
|
|
|
|
of SSA is immediately apparent, and function arguments are no longer a special
|
|
|
|
case: they become arguments to the entry block
|
|
|
|
[[more rationale](Rationale/Rationale.md/#block-arguments-vs-phi-nodes)]. Blocks
|
|
|
|
are also a fundamental concept that cannot be represented by operations because
|
|
|
|
values defined in an operation cannot be accessed outside the operation.
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
## Regions
|
|
|
|
|
|
|
|
### Definition
|
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
A region is an ordered list of MLIR [Blocks](#blocks). The semantics within a
|
|
|
|
region is not imposed by the IR. Instead, the containing operation defines the
|
|
|
|
semantics of the regions it contains. MLIR currently defines two kinds of
|
|
|
|
regions: [SSACFG regions](#control-flow-and-ssacfg-regions), which describe
|
|
|
|
control flow between blocks, and [Graph regions](#graph-regions), which do not
|
2021-10-13 07:14:57 +08:00
|
|
|
require control flow between block. The kinds of regions within an operation are
|
|
|
|
described using the [RegionKindInterface](Interfaces.md/#regionkindinterfaces).
|
2019-08-24 01:08:42 +08:00
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
Regions do not have a name or an address, only the blocks contained in a region
|
|
|
|
do. Regions must be contained within operations and have no type or attributes.
|
|
|
|
The first block in the region is a special block called the 'entry block'. The
|
|
|
|
arguments to the entry block are also the arguments of the region itself. The
|
|
|
|
entry block cannot be listed as a successor of any other block. The syntax for a
|
|
|
|
region is as follows:
|
2019-08-24 01:08:42 +08:00
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2019-12-05 04:05:52 +08:00
|
|
|
region ::= `{` block* `}`
|
2019-08-24 01:08:42 +08:00
|
|
|
```
|
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
A function body is an example of a region: it consists of a CFG of blocks and
|
|
|
|
has additional semantic restrictions that other types of regions may not have.
|
|
|
|
For example, in a function body, block terminators must either branch to a
|
|
|
|
different block, or return from a function where the types of the `return`
|
2021-10-13 07:14:57 +08:00
|
|
|
arguments must match the result types of the function signature. Similarly, the
|
|
|
|
function arguments must match the types and count of the region arguments. In
|
2021-10-29 15:19:11 +08:00
|
|
|
general, operations with regions can define these correspondences arbitrarily.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
### Value Scoping
|
|
|
|
|
|
|
|
Regions provide hierarchical encapsulation of programs: it is impossible to
|
2021-10-13 07:14:57 +08:00
|
|
|
reference, i.e. branch to, a block which is not in the same region as the source
|
|
|
|
of the reference, i.e. a terminator operation. Similarly, regions provides a
|
|
|
|
natural scoping for value visibility: values defined in a region don't escape to
|
|
|
|
the enclosing region, if any. By default, operations inside a region can
|
|
|
|
reference values defined outside of the region whenever it would have been legal
|
|
|
|
for operands of the enclosing operation to reference those values, but this can
|
|
|
|
be restricted using traits, such as
|
2021-05-25 00:40:39 +08:00
|
|
|
[OpTrait::IsolatedFromAbove](Traits.md/#isolatedfromabove), or a custom
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
verifier.
|
2019-08-24 01:08:42 +08:00
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
Example:
|
2019-08-24 01:08:42 +08:00
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
```mlir
|
|
|
|
"any_op"(%a) ({ // if %a is in-scope in the containing region...
|
2021-10-13 07:14:57 +08:00
|
|
|
// then %a is in-scope here too.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
%new_value = "another_op"(%a) : (i64) -> (i64)
|
|
|
|
}) : (i64) -> (i64)
|
|
|
|
```
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
MLIR defines a generalized 'hierarchical dominance' concept that operates across
|
|
|
|
hierarchy and defines whether a value is 'in scope' and can be used by a
|
|
|
|
particular operation. Whether a value can be used by another operation in the
|
|
|
|
same region is defined by the kind of region. A value defined in a region can be
|
|
|
|
used by an operation which has a parent in the same region, if and only if the
|
|
|
|
parent could use the value. A value defined by an argument to a region can
|
|
|
|
always be used by any operation deeply contained in the region. A value defined
|
|
|
|
in a region can never be used outside of the region.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
### Control Flow and SSACFG Regions
|
|
|
|
|
|
|
|
In MLIR, control flow semantics of a region is indicated by
|
2021-10-13 07:14:57 +08:00
|
|
|
[RegionKind::SSACFG](Interfaces.md/#regionkindinterfaces). Informally, these
|
|
|
|
regions support semantics where operations in a region 'execute sequentially'.
|
|
|
|
Before an operation executes, its operands have well-defined values. After an
|
|
|
|
operation executes, the operands have the same values and results also have
|
|
|
|
well-defined values. After an operation executes, the next operation in the
|
|
|
|
block executes until the operation is the terminator operation at the end of a
|
|
|
|
block, in which case some other operation will execute. The determination of the
|
|
|
|
next instruction to execute is the 'passing of control flow'.
|
|
|
|
|
|
|
|
In general, when control flow is passed to an operation, MLIR does not restrict
|
|
|
|
when control flow enters or exits the regions contained in that operation.
|
|
|
|
However, when control flow enters a region, it always begins in the first block
|
|
|
|
of the region, called the *entry* block. Terminator operations ending each block
|
|
|
|
represent control flow by explicitly specifying the successor blocks of the
|
|
|
|
block. Control flow can only pass to one of the specified successor blocks as in
|
|
|
|
a `branch` operation, or back to the containing operation as in a `return`
|
|
|
|
operation. Terminator operations without successors can only pass control back
|
|
|
|
to the containing operation. Within these restrictions, the particular semantics
|
|
|
|
of terminator operations is determined by the specific dialect operations
|
|
|
|
involved. Blocks (other than the entry block) that are not listed as a successor
|
|
|
|
of a terminator operation are defined to be unreachable and can be removed
|
|
|
|
without affecting the semantics of the containing operation.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
Although control flow always enters a region through the entry block, control
|
|
|
|
flow may exit a region through any block with an appropriate terminator. The
|
|
|
|
standard dialect leverages this capability to define operations with
|
|
|
|
Single-Entry-Multiple-Exit (SEME) regions, possibly flowing through different
|
2021-10-13 07:14:57 +08:00
|
|
|
blocks in the region and exiting through any block with a `return` operation.
|
|
|
|
This behavior is similar to that of a function body in most programming
|
|
|
|
languages. In addition, control flow may also not reach the end of a block or
|
|
|
|
region, for example if a function call does not return.
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
func @accelerator_compute(i64, i1) -> i64 { // An SSACFG region
|
2019-08-24 01:08:42 +08:00
|
|
|
^bb0(%a: i64, %cond: i1): // Code dominated by ^bb0 may refer to %a
|
|
|
|
cond_br %cond, ^bb1, ^bb2
|
|
|
|
|
|
|
|
^bb1:
|
|
|
|
// This def for %value does not dominate ^bb2
|
|
|
|
%value = "op.convert"(%a) : (i64) -> i64
|
|
|
|
br ^bb3(%a: i64) // Branch passes %a as the argument
|
|
|
|
|
|
|
|
^bb2:
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
accelerator.launch() { // An SSACFG region
|
2019-08-24 01:08:42 +08:00
|
|
|
^bb0:
|
2019-09-26 02:57:13 +08:00
|
|
|
// Region of code nested under "accelerator.launch", it can reference %a but
|
2019-08-24 01:08:42 +08:00
|
|
|
// not %value.
|
|
|
|
%new_value = "accelerator.do_something"(%a) : (i64) -> ()
|
|
|
|
}
|
|
|
|
// %new_value cannot be referenced outside of the region
|
2019-09-26 02:57:13 +08:00
|
|
|
|
|
|
|
^bb3:
|
|
|
|
...
|
2019-08-24 01:08:42 +08:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
#### Operations with Multiple Regions
|
|
|
|
|
|
|
|
An operation containing multiple regions also completely determines the
|
|
|
|
semantics of those regions. In particular, when control flow is passed to an
|
|
|
|
operation, it may transfer control flow to any contained region. When control
|
2021-10-13 07:14:57 +08:00
|
|
|
flow exits a region and is returned to the containing operation, the containing
|
|
|
|
operation may pass control flow to any region in the same operation. An
|
|
|
|
operation may also pass control flow to multiple contained regions concurrently.
|
|
|
|
An operation may also pass control flow into regions that were specified in
|
|
|
|
other operations, in particular those that defined the values or symbols the
|
|
|
|
given operation uses as in a call operation. This passage of control is
|
|
|
|
generally independent of passage of control flow through the basic blocks of the
|
|
|
|
containing region.
|
2019-08-24 01:08:42 +08:00
|
|
|
|
|
|
|
#### Closure
|
|
|
|
|
|
|
|
Regions allow defining an operation that creates a closure, for example by
|
|
|
|
“boxing” the body of the region into a value they produce. It remains up to the
|
|
|
|
operation to define its semantics. Note that if an operation triggers
|
|
|
|
asynchronous execution of the region, it is under the responsibility of the
|
|
|
|
operation caller to wait for the region to be executed guaranteeing that any
|
|
|
|
directly used values remain live.
|
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
### Graph Regions
|
|
|
|
|
|
|
|
In MLIR, graph-like semantics in a region is indicated by
|
2021-05-25 00:40:39 +08:00
|
|
|
[RegionKind::Graph](Interfaces.md/#regionkindinterfaces). Graph regions are
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
appropriate for concurrent semantics without control flow, or for modeling
|
|
|
|
generic directed graph data structures. Graph regions are appropriate for
|
|
|
|
representing cyclic relationships between coupled values where there is no
|
|
|
|
fundamental order to the relationships. For instance, operations in a graph
|
|
|
|
region may represent independent threads of control with values representing
|
|
|
|
streams of data. As usual in MLIR, the particular semantics of a region is
|
|
|
|
completely determined by its containing operation. Graph regions may only
|
|
|
|
contain a single basic block (the entry block).
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
**Rationale:** Currently graph regions are arbitrarily limited to a single basic
|
|
|
|
block, although there is no particular semantic reason for this limitation. This
|
|
|
|
limitation has been added to make it easier to stabilize the pass infrastructure
|
|
|
|
and commonly used passes for processing graph regions to properly handle
|
|
|
|
feedback loops. Multi-block regions may be allowed in the future if use cases
|
|
|
|
that require it arise.
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
In graph regions, MLIR operations naturally represent nodes, while each MLIR
|
|
|
|
value represents a multi-edge connecting a single source node and multiple
|
2021-10-13 07:14:57 +08:00
|
|
|
destination nodes. All values defined in the region as results of operations are
|
|
|
|
in scope within the region and can be accessed by any other operation in the
|
|
|
|
region. In graph regions, the order of operations within a block and the order
|
|
|
|
of blocks in a region is not semantically meaningful and non-terminator
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
operations may be freely reordered, for instance, by canonicalization. Other
|
|
|
|
kinds of graphs, such as graphs with multiple source nodes and multiple
|
|
|
|
destination nodes, can also be represented by representing graph edges as MLIR
|
|
|
|
operations.
|
|
|
|
|
|
|
|
Note that cycles can occur within a single block in a graph region, or between
|
|
|
|
basic blocks.
|
|
|
|
|
|
|
|
```mlir
|
|
|
|
"test.graph_region"() ({ // A Graph region
|
|
|
|
%1 = "op1"(%1, %3) : (i32, i32) -> (i32) // OK: %1, %3 allowed here
|
|
|
|
%2 = "test.ssacfg_region"() ({
|
2021-10-13 07:14:57 +08:00
|
|
|
%5 = "op2"(%1, %2, %3, %4) : (i32, i32, i32, i32) -> (i32) // OK: %1, %2, %3, %4 all defined in the containing region
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
}) : () -> (i32)
|
|
|
|
%3 = "op2"(%1, %4) : (i32, i32) -> (i32) // OK: %4 allowed here
|
|
|
|
%4 = "op3"(%1) : (i32) -> (i32)
|
|
|
|
}) : () -> ()
|
|
|
|
```
|
|
|
|
|
2019-08-24 01:08:42 +08:00
|
|
|
### Arguments and Results
|
|
|
|
|
|
|
|
The arguments of the first block of a region are treated as arguments of the
|
|
|
|
region. The source of these arguments is defined by the semantics of the parent
|
|
|
|
operation. They may correspond to some of the values the operation itself uses.
|
|
|
|
|
|
|
|
Regions produce a (possibly empty) list of values. The operation semantics
|
|
|
|
defines the relation between the region results and the operation results.
|
|
|
|
|
2019-08-23 07:43:06 +08:00
|
|
|
## Type System
|
|
|
|
|
2021-03-20 09:19:16 +08:00
|
|
|
Each value in MLIR has a type defined by the type system. MLIR has an open type
|
|
|
|
system (i.e. there is no fixed list of types), and types may have
|
|
|
|
application-specific semantics. MLIR dialects may define any number of types
|
|
|
|
with no restrictions on the abstractions they represent.
|
2019-08-23 07:43:06 +08:00
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2020-12-04 09:22:29 +08:00
|
|
|
type ::= type-alias | dialect-type | builtin-type
|
2019-08-23 07:43:06 +08:00
|
|
|
|
|
|
|
type-list-no-parens ::= type (`,` type)*
|
|
|
|
type-list-parens ::= `(` `)`
|
|
|
|
| `(` type-list-no-parens `)`
|
|
|
|
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
// This is a common way to refer to a value with a specified type.
|
2019-08-23 07:43:06 +08:00
|
|
|
ssa-use-and-type ::= ssa-use `:` type
|
|
|
|
|
|
|
|
// Non-empty list of names and types.
|
|
|
|
ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
|
|
|
|
```
|
|
|
|
|
|
|
|
### Type Aliases
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2019-08-23 07:43:06 +08:00
|
|
|
type-alias-def ::= '!' alias-name '=' 'type' type
|
|
|
|
type-alias ::= '!' alias-name
|
|
|
|
```
|
|
|
|
|
|
|
|
MLIR supports defining named aliases for types. A type alias is an identifier
|
|
|
|
that can be used in the place of the type that it defines. These aliases *must*
|
|
|
|
be defined before their uses. Alias names may not contain a '.', since those
|
|
|
|
names are reserved for [dialect types](#dialect-types).
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-08-23 07:43:06 +08:00
|
|
|
!avx_m128 = type vector<4 x f32>
|
|
|
|
|
|
|
|
// Using the original type.
|
|
|
|
"foo"(%x) : vector<4 x f32> -> ()
|
|
|
|
|
|
|
|
// Using the type alias.
|
|
|
|
"foo"(%x) : !avx_m128 -> ()
|
|
|
|
```
|
|
|
|
|
2019-08-23 08:51:06 +08:00
|
|
|
### Dialect Types
|
2019-08-23 06:53:41 +08:00
|
|
|
|
|
|
|
Similarly to operations, dialects may define custom extensions to the type
|
2019-08-23 07:43:06 +08:00
|
|
|
system.
|
2019-08-23 06:53:41 +08:00
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2019-11-26 09:53:20 +08:00
|
|
|
dialect-namespace ::= bare-id
|
|
|
|
|
|
|
|
opaque-dialect-item ::= dialect-namespace '<' string-literal '>'
|
|
|
|
|
|
|
|
pretty-dialect-item ::= dialect-namespace '.' pretty-dialect-item-lead-ident
|
|
|
|
pretty-dialect-item-body?
|
|
|
|
|
|
|
|
pretty-dialect-item-lead-ident ::= '[A-Za-z][A-Za-z0-9._]*'
|
|
|
|
pretty-dialect-item-body ::= '<' pretty-dialect-item-contents+ '>'
|
|
|
|
pretty-dialect-item-contents ::= pretty-dialect-item-body
|
|
|
|
| '(' pretty-dialect-item-contents+ ')'
|
|
|
|
| '[' pretty-dialect-item-contents+ ']'
|
|
|
|
| '{' pretty-dialect-item-contents+ '}'
|
2019-08-23 06:53:41 +08:00
|
|
|
| '[^[<({>\])}\0]+'
|
2019-11-26 09:53:20 +08:00
|
|
|
|
|
|
|
dialect-type ::= '!' opaque-dialect-item
|
|
|
|
dialect-type ::= '!' pretty-dialect-item
|
2019-08-23 06:53:41 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
Dialect types can be specified in a verbose form, e.g. like this:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-08-23 06:53:41 +08:00
|
|
|
// LLVM type that wraps around llvm IR types.
|
|
|
|
!llvm<"i32*">
|
|
|
|
|
|
|
|
// Tensor flow string type.
|
|
|
|
!tf.string
|
|
|
|
|
|
|
|
// Complex type
|
|
|
|
!foo<"something<abcd>">
|
|
|
|
|
|
|
|
// Even more complex type
|
|
|
|
!foo<"something<a%%123^^^>>>">
|
|
|
|
```
|
|
|
|
|
|
|
|
Dialect types that are simple enough can use the pretty format, which is a
|
|
|
|
lighter weight syntax that is equivalent to the above forms:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-08-23 06:53:41 +08:00
|
|
|
// Tensor flow string type.
|
|
|
|
!tf.string
|
|
|
|
|
|
|
|
// Complex type
|
|
|
|
!foo.something<abcd>
|
|
|
|
```
|
|
|
|
|
|
|
|
Sufficiently complex dialect types are required to use the verbose form for
|
|
|
|
generality. For example, the more complex type shown above wouldn't be valid in
|
|
|
|
the lighter syntax: `!foo.something<a%%123^^^>>>` because it contains characters
|
|
|
|
that are not allowed in the lighter syntax, as well as unbalanced `<>`
|
|
|
|
characters.
|
|
|
|
|
2021-03-20 09:19:16 +08:00
|
|
|
See [here](Tutorials/DefiningAttributesAndTypes.md) to learn how to define
|
|
|
|
dialect types.
|
2019-08-23 06:53:41 +08:00
|
|
|
|
2020-12-04 09:22:29 +08:00
|
|
|
### Builtin Types
|
2018-10-25 00:47:36 +08:00
|
|
|
|
2021-03-20 09:19:16 +08:00
|
|
|
The [builtin dialect](Dialects/Builtin.md) defines a set of types that are
|
|
|
|
directly usable by any other dialect in MLIR. These types cover a range from
|
|
|
|
primitive integer and floating-point types, function types, and more.
|
2019-04-28 09:35:04 +08:00
|
|
|
|
2019-04-05 23:19:42 +08:00
|
|
|
## Attributes
|
2018-10-25 00:47:36 +08:00
|
|
|
|
|
|
|
Syntax:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2021-02-05 08:17:45 +08:00
|
|
|
attribute-entry ::= (bare-id | string-literal) `=` attribute-value
|
|
|
|
attribute-value ::= attribute-alias | dialect-attribute | builtin-attribute
|
2018-10-25 00:47:36 +08:00
|
|
|
```
|
|
|
|
|
2019-08-23 08:51:06 +08:00
|
|
|
Attributes are the mechanism for specifying constant data on operations in
|
2021-02-05 05:27:25 +08:00
|
|
|
places where a variable is never allowed - e.g. the comparison predicate of a
|
2021-02-05 08:17:45 +08:00
|
|
|
[`cmpi` operation](Dialects/Standard.md#stdcmpi-cmpiop). Each operation has an
|
|
|
|
attribute dictionary, which associates a set of attribute names to attribute
|
|
|
|
values. MLIR's builtin dialect provides a rich set of
|
|
|
|
[builtin attribute values](#builtin-attribute-values) out of the box (such as
|
|
|
|
arrays, dictionaries, strings, etc.). Additionally, dialects can define their
|
|
|
|
own [dialect attribute values](#dialect-attribute-values).
|
|
|
|
|
|
|
|
The top-level attribute dictionary attached to an operation has special
|
|
|
|
semantics. The attribute entries are considered to be of two different kinds
|
|
|
|
based on whether their dictionary key has a dialect prefix:
|
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
- *inherent attributes* are inherent to the definition of an operation's
|
|
|
|
semantics. The operation itself is expected to verify the consistency of
|
|
|
|
these attributes. An example is the `predicate` attribute of the
|
|
|
|
`arith.cmpi` op. These attributes must have names that do not start with a
|
|
|
|
dialect prefix.
|
|
|
|
|
|
|
|
- *discardable attributes* have semantics defined externally to the operation
|
|
|
|
itself, but must be compatible with the operations's semantics. These
|
|
|
|
attributes must have names that start with a dialect prefix. The dialect
|
|
|
|
indicated by the dialect prefix is expected to verify these attributes. An
|
|
|
|
example is the `gpu.container_module` attribute.
|
2021-02-05 08:17:45 +08:00
|
|
|
|
|
|
|
Note that attribute values are allowed to themselves be dictionary attributes,
|
|
|
|
but only the top-level dictionary attribute attached to the operation is subject
|
|
|
|
to the classification above.
|
2019-03-03 14:34:18 +08:00
|
|
|
|
2019-08-23 08:51:06 +08:00
|
|
|
### Attribute Value Aliases
|
2019-03-03 14:34:18 +08:00
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2021-02-05 05:27:25 +08:00
|
|
|
attribute-alias-def ::= '#' alias-name '=' attribute-value
|
2019-08-23 08:51:06 +08:00
|
|
|
attribute-alias ::= '#' alias-name
|
|
|
|
```
|
|
|
|
|
|
|
|
MLIR supports defining named aliases for attribute values. An attribute alias is
|
|
|
|
an identifier that can be used in the place of the attribute that it defines.
|
|
|
|
These aliases *must* be defined before their uses. Alias names may not contain a
|
|
|
|
'.', since those names are reserved for
|
|
|
|
[dialect attributes](#dialect-attribute-values).
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2020-01-14 05:12:37 +08:00
|
|
|
#map = affine_map<(d0) -> (d0 + 10)>
|
2019-08-23 08:51:06 +08:00
|
|
|
|
|
|
|
// Using the original attribute.
|
2020-01-14 05:12:37 +08:00
|
|
|
%b = affine.apply affine_map<(d0) -> (d0 + 10)> (%a)
|
2019-08-23 08:51:06 +08:00
|
|
|
|
|
|
|
// Using the attribute alias.
|
|
|
|
%b = affine.apply #map(%a)
|
|
|
|
```
|
|
|
|
|
|
|
|
### Dialect Attribute Values
|
|
|
|
|
2019-11-26 09:53:20 +08:00
|
|
|
Similarly to operations, dialects may define custom attribute values. The
|
|
|
|
syntactic structure of these values is identical to custom dialect type values,
|
2020-12-03 04:42:01 +08:00
|
|
|
except that dialect attribute values are distinguished with a leading '#', while
|
|
|
|
dialect types are distinguished with a leading '!'.
|
2019-08-23 08:51:06 +08:00
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```
|
2020-12-03 04:42:01 +08:00
|
|
|
dialect-attribute-value ::= '#' opaque-dialect-item
|
|
|
|
dialect-attribute-value ::= '#' pretty-dialect-item
|
2019-08-23 08:51:06 +08:00
|
|
|
```
|
|
|
|
|
2020-12-03 04:42:01 +08:00
|
|
|
Dialect attribute values can be specified in a verbose form, e.g. like this:
|
2019-08-23 08:51:06 +08:00
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2020-12-03 04:42:01 +08:00
|
|
|
// Complex attribute value.
|
2019-08-23 08:51:06 +08:00
|
|
|
#foo<"something<abcd>">
|
|
|
|
|
2020-12-03 04:42:01 +08:00
|
|
|
// Even more complex attribute value.
|
2019-08-23 08:51:06 +08:00
|
|
|
#foo<"something<a%%123^^^>>>">
|
|
|
|
```
|
|
|
|
|
2020-12-03 04:42:01 +08:00
|
|
|
Dialect attribute values that are simple enough can use the pretty format, which
|
|
|
|
is a lighter weight syntax that is equivalent to the above forms:
|
2019-08-23 08:51:06 +08:00
|
|
|
|
2019-12-10 19:00:29 +08:00
|
|
|
```mlir
|
2019-08-23 08:51:06 +08:00
|
|
|
// Complex attribute
|
|
|
|
#foo.something<abcd>
|
|
|
|
```
|
|
|
|
|
2020-12-03 04:42:01 +08:00
|
|
|
Sufficiently complex dialect attribute values are required to use the verbose
|
|
|
|
form for generality. For example, the more complex type shown above would not be
|
|
|
|
valid in the lighter syntax: `#foo.something<a%%123^^^>>>` because it contains
|
|
|
|
characters that are not allowed in the lighter syntax, as well as unbalanced
|
|
|
|
`<>` characters.
|
2019-08-23 08:51:06 +08:00
|
|
|
|
2020-12-03 04:42:01 +08:00
|
|
|
See [here](Tutorials/DefiningAttributesAndTypes.md) on how to define dialect
|
2019-08-23 08:51:06 +08:00
|
|
|
attribute values.
|
|
|
|
|
2020-12-04 09:22:57 +08:00
|
|
|
### Builtin Attribute Values
|
2019-08-23 08:51:06 +08:00
|
|
|
|
2021-03-20 09:19:16 +08:00
|
|
|
The [builtin dialect](Dialects/Builtin.md) defines a set of attribute values
|
|
|
|
that are directly usable by any other dialect in MLIR. These types cover a range
|
|
|
|
from primitive integer and floating-point values, attribute dictionaries, dense
|
|
|
|
multi-dimensional arrays, and more.
|