blob: 89d9d89964f947bd7763d7859821b3bf8f388a6c [file] [log] [blame] [view]
River Riddle01c857b2020-03-30 19:25:001# 'affine' Dialect
River Riddle6f7470a2019-02-06 00:29:252
3This dialect provides a powerful abstraction for affine operations and analyses.
4
5[TOC]
6
Andy Davis59100a02019-05-13 18:05:597## Polyhedral Structures
8
9MLIR uses techniques from polyhedral compilation to make dependence analysis and
10loop transformations efficient and reliable. This section introduces some of the
11core concepts that are used throughout the document.
12
13### Dimensions and Symbols
14
15Dimensions and symbols are the two kinds of identifiers that can appear in the
Mogballa54f4ea2021-10-12 23:14:5716polyhedral structures, and are always of [`index`](Builtin.md/#indextype) type.
17Dimensions are declared in parentheses and symbols are declared in square
MLIR Team5a91b982019-05-29 21:56:4118brackets.
Andy Davis59100a02019-05-13 18:05:5919
20Examples:
21
Alex Zinenkoac487332019-12-10 11:00:2922```mlir
Andy Davis59100a02019-05-13 18:05:5923// A 2d to 3d affine mapping.
24// d0/d1 are dimensions, s0 is a symbol
River Riddle4268e4f2020-01-13 21:12:3725#affine_map2to3 = affine_map<(d0, d1)[s0] -> (d0, d1 + s0, d1 - s0)>
Andy Davis59100a02019-05-13 18:05:5926```
27
28Dimensional identifiers correspond to the dimensions of the underlying structure
29being represented (a map, set, or more concretely a loop nest or a tensor); for
30example, a three-dimensional loop nest has three dimensional identifiers. Symbol
31identifiers represent an unknown quantity that can be treated as constant for a
32region of interest.
33
34Dimensions and symbols are bound to SSA values by various operations in MLIR and
35use the same parenthesized vs square bracket list to distinguish the two.
36
37Syntax:
38
Alex Zinenkoac487332019-12-10 11:00:2939```
Andy Davis59100a02019-05-13 18:05:5940// Uses of SSA values that are passed to dimensional identifiers.
41dim-use-list ::= `(` ssa-use-list? `)`
42
43// Uses of SSA values that are used to bind symbols.
44symbol-use-list ::= `[` ssa-use-list? `]`
45
46// Most things that bind SSA values bind dimensions and symbols.
47dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
48```
49
50SSA values bound to dimensions and symbols must always have 'index' type.
51
52Example:
53
Alex Zinenkoac487332019-12-10 11:00:2954```mlir
River Riddle4268e4f2020-01-13 21:12:3755#affine_map2to3 = affine_map<(d0, d1)[s0] -> (d0, d1 + s0, d1 - s0)>
Andy Davis59100a02019-05-13 18:05:5956// Binds %N to the s0 symbol in affine_map2to3.
Mogballa54f4ea2021-10-12 23:14:5757%x = memref.alloc()[%N] : memref<40x50xf32, #affine_map2to3>
Andy Davis59100a02019-05-13 18:05:5958```
59
60### Restrictions on Dimensions and Symbols
River Riddle6f7470a2019-02-06 00:29:2561
62The affine dialect imposes certain restrictions on dimension and symbolic
Uday Bondhugula48034532020-04-29 00:08:2363identifiers to enable powerful analysis and transformation. An SSA value's use
Mogballa54f4ea2021-10-12 23:14:5764can be bound to a symbolic identifier if that SSA value is either 1. a region
65argument for an op with trait `AffineScope` (eg. `FuncOp`), 2. a value defined
66at the top level of an `AffineScope` op (i.e., immediately enclosed by the
67latter), 3. a value that dominates the `AffineScope` op enclosing the value's
68use, 4. the result of a
River Riddle23aa5a72022-02-26 22:49:5469constant operation, 5. the result of an
Mogballa54f4ea2021-10-12 23:14:5770[`affine.apply` operation](#affineapply-affineapplyop) that recursively takes as
71arguments any valid symbolic identifiers, or 6. the result of a
72[`dim` operation](MemRef.md/#memrefdim-mlirmemrefdimop) on either a memref that
73is an argument to a `AffineScope` op or a memref where the corresponding
74dimension is either static or a dynamic one in turn bound to a valid symbol.
Alex Zinenko36150c32020-06-15 09:40:5675*Note:* if the use of an SSA value is not contained in any op with the
76`AffineScope` trait, only the rules 4-6 can be applied.
Uday Bondhugula48034532020-04-29 00:08:2377
78Note that as a result of rule (3) above, symbol validity is sensitive to the
Mogballa54f4ea2021-10-12 23:14:5779location of the SSA use. Dimensions may be bound not only to anything that a
Uday Bondhugula48034532020-04-29 00:08:2380symbol is bound to, but also to induction variables of enclosing
Markus Böck9b993362021-05-25 12:50:5981[`affine.for`](#affinefor-affineforop) and
Mogballa54f4ea2021-10-12 23:14:5782[`affine.parallel`](#affineparallel-affineparallelop) operations, and the result
83of an [`affine.apply` operation](#affineapply-affineapplyop) (which recursively
84may use other dimensions and symbols).
River Riddle6f7470a2019-02-06 00:29:2585
Andy Davis59100a02019-05-13 18:05:5986### Affine Expressions
87
88Syntax:
89
Alex Zinenkoac487332019-12-10 11:00:2990```
Andy Davis59100a02019-05-13 18:05:5991affine-expr ::= `(` affine-expr `)`
92 | affine-expr `+` affine-expr
93 | affine-expr `-` affine-expr
94 | `-`? integer-literal `*` affine-expr
95 | affine-expr `ceildiv` integer-literal
96 | affine-expr `floordiv` integer-literal
97 | affine-expr `mod` integer-literal
98 | `-`affine-expr
99 | bare-id
100 | `-`? integer-literal
101
Nicolas Vasilache47ec8702020-03-10 19:10:34102multi-dim-affine-expr ::= `(` `)`
103 | `(` affine-expr (`,` affine-expr)* `)`
Andy Davis59100a02019-05-13 18:05:59104```
105
106`ceildiv` is the ceiling function which maps the result of the division of its
107first argument by its second argument to the smallest integer greater than or
108equal to that result. `floordiv` is a function which maps the result of the
109division of its first argument by its second argument to the largest integer
110less than or equal to that result. `mod` is the modulo operation: since its
111second argument is always positive, its results are always positive in our
112usage. The `integer-literal` operand for ceildiv, floordiv, and mod is always
113expected to be positive. `bare-id` is an identifier which must have type
Markus Böck9b993362021-05-25 12:50:59114[index](Builtin.md/#indextype). The precedence of operations in an affine
MLIR Team5a91b982019-05-29 21:56:41115expression are ordered from highest to lowest in the order: (1)
116parenthesization, (2) negation, (3) modulo, multiplication, floordiv, and
117ceildiv, and (4) addition and subtraction. All of these operators associate from
118left to right.
Andy Davis59100a02019-05-13 18:05:59119
Mogballa54f4ea2021-10-12 23:14:57120A *multidimensional affine expression* is a comma separated list of
Andy Davis59100a02019-05-13 18:05:59121one-dimensional affine expressions, with the entire list enclosed in
122parentheses.
123
124**Context:** An affine function, informally, is a linear function plus a
lewuathe4ae79522021-01-06 01:59:45125constant. More formally, a function f defined on a vector $\vec{v} \in
Mogballa54f4ea2021-10-12 23:14:57126\mathbb{Z}^n$ is a multidimensional affine function of $\vec{v}$ if $f(\vec{v})$
127can be expressed in the form $M \vec{v} + \vec{c}$ where $M$ is a constant
128matrix from $\mathbb{Z}^{m \times n}$ and $\vec{c}$ is a constant vector from
129$\mathbb{Z}$. $m$ is the dimensionality of such an affine function. MLIR further
130extends the definition of an affine function to allow 'floordiv', 'ceildiv', and
131'mod' with respect to positive integer constants. Such extensions to affine
132functions have often been referred to as quasi-affine functions by the
133polyhedral compiler community. MLIR uses the term 'affine map' to refer to these
134multidimensional quasi-affine functions. As examples, $(i+j+1, j)$, $(i \mod 2,
135j+i)$, $(j, i/4, i \mod 4)$, $(2i+1, j)$ are two-dimensional affine functions of
136$(i, j)$, but $(i \cdot j, i^2)$, $(i \mod j, i/j)$ are not affine functions of
137$(i, j)$.
Andy Davis59100a02019-05-13 18:05:59138
139### Affine Maps
140
141Syntax:
142
Alex Zinenkoac487332019-12-10 11:00:29143```
Andy Davis59100a02019-05-13 18:05:59144affine-map-inline
145 ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
Andy Davis59100a02019-05-13 18:05:59146```
147
148The identifiers in the dimensions and symbols lists must be unique. These are
MLIR Team5a91b982019-05-29 21:56:41149the only identifiers that may appear in 'multi-dim-affine-expr'. Affine maps
Andy Davis59100a02019-05-13 18:05:59150with one or more symbols in its specification are known as "symbolic affine
MLIR Team5a91b982019-05-29 21:56:41151maps", and those with no symbols as "non-symbolic affine maps".
Andy Davis59100a02019-05-13 18:05:59152
153**Context:** Affine maps are mathematical functions that transform a list of
154dimension indices and symbols into a list of results, with affine expressions
155combining the indices and symbols. Affine maps distinguish between
156[indices and symbols](#dimensions-and-symbols) because indices are inputs to the
reinerp02b3ea62019-10-18 17:28:02157affine map when the map is called (through an operation such as
Mogballa54f4ea2021-10-12 23:14:57158[affine.apply](#affineapply-affineapplyop)), whereas symbols are bound when the
159map is established (e.g. when a memref is formed, establishing a memory
160[layout map](Builtin.md/#layout-map)).
Andy Davis59100a02019-05-13 18:05:59161
162Affine maps are used for various core structures in MLIR. The restrictions we
163impose on their form allows powerful analysis and transformation, while keeping
164the representation closed with respect to several operations of interest.
165
166#### Named affine mappings
167
168Syntax:
169
Alex Zinenkoac487332019-12-10 11:00:29170```
Andy Davis59100a02019-05-13 18:05:59171affine-map-id ::= `#` suffix-id
172
173// Definitions of affine maps are at the top of the file.
174affine-map-def ::= affine-map-id `=` affine-map-inline
175module-header-def ::= affine-map-def
176
177// Uses of affine maps may use the inline form or the named form.
178affine-map ::= affine-map-id | affine-map-inline
179```
180
181Affine mappings may be defined inline at the point of use, or may be hoisted to
182the top of the file and given a name with an affine map definition, and used by
183name.
184
185Examples:
186
Alex Zinenkoac487332019-12-10 11:00:29187```mlir
Andy Davis59100a02019-05-13 18:05:59188// Affine map out-of-line definition and usage example.
River Riddle4268e4f2020-01-13 21:12:37189#affine_map42 = affine_map<(d0, d1)[s0] -> (d0, d0 + d1 + s0 floordiv 2)>
Andy Davis59100a02019-05-13 18:05:59190
191// Use an affine mapping definition in an alloc operation, binding the
192// SSA value %N to the symbol s0.
Mogballa54f4ea2021-10-12 23:14:57193%a = memref.alloc()[%N] : memref<4x4xf32, #affine_map42>
Andy Davis59100a02019-05-13 18:05:59194
195// Same thing with an inline affine mapping definition.
Mogballa54f4ea2021-10-12 23:14:57196%b = memref.alloc()[%N] : memref<4x4xf32, affine_map<(d0, d1)[s0] -> (d0, d0 + d1 + s0 floordiv 2)>>
Andy Davis59100a02019-05-13 18:05:59197```
198
199### Semi-affine maps
200
201Semi-affine maps are extensions of affine maps to allow multiplication,
202`floordiv`, `ceildiv`, and `mod` with respect to symbolic identifiers.
203Semi-affine maps are thus a strict superset of affine maps.
204
205Syntax of semi-affine expressions:
206
Alex Zinenkoac487332019-12-10 11:00:29207```
Andy Davis59100a02019-05-13 18:05:59208semi-affine-expr ::= `(` semi-affine-expr `)`
209 | semi-affine-expr `+` semi-affine-expr
210 | semi-affine-expr `-` semi-affine-expr
211 | symbol-or-const `*` semi-affine-expr
MLIR Team3191f9c2019-08-16 18:00:31212 | semi-affine-expr `ceildiv` symbol-or-const
213 | semi-affine-expr `floordiv` symbol-or-const
Andy Davis59100a02019-05-13 18:05:59214 | semi-affine-expr `mod` symbol-or-const
215 | bare-id
216 | `-`? integer-literal
217
218symbol-or-const ::= `-`? integer-literal | symbol-id
219
220multi-dim-semi-affine-expr ::= `(` semi-affine-expr (`,` semi-affine-expr)* `)`
221```
222
223The precedence and associativity of operations in the syntax above is the same
224as that for [affine expressions](#affine-expressions).
225
226Syntax of semi-affine maps:
227
Alex Zinenkoac487332019-12-10 11:00:29228```
Andy Davis59100a02019-05-13 18:05:59229semi-affine-map-inline
230 ::= dim-and-symbol-id-lists `->` multi-dim-semi-affine-expr
Andy Davis59100a02019-05-13 18:05:59231```
232
233Semi-affine maps may be defined inline at the point of use, or may be hoisted to
234the top of the file and given a name with a semi-affine map definition, and used
235by name.
236
Alex Zinenkoac487332019-12-10 11:00:29237```
Andy Davis59100a02019-05-13 18:05:59238semi-affine-map-id ::= `#` suffix-id
239
240// Definitions of semi-affine maps are at the top of file.
241semi-affine-map-def ::= semi-affine-map-id `=` semi-affine-map-inline
242module-header-def ::= semi-affine-map-def
243
244// Uses of semi-affine maps may use the inline form or the named form.
245semi-affine-map ::= semi-affine-map-id | semi-affine-map-inline
246```
247
248### Integer Sets
249
250An integer set is a conjunction of affine constraints on a list of identifiers.
251The identifiers associated with the integer set are separated out into two
252classes: the set's dimension identifiers, and the set's symbolic identifiers.
253The set is viewed as being parametric on its symbolic identifiers. In the
254syntax, the list of set's dimension identifiers are enclosed in parentheses
255while its symbols are enclosed in square brackets.
256
257Syntax of affine constraints:
258
Alex Zinenkoac487332019-12-10 11:00:29259```
Andy Davis59100a02019-05-13 18:05:59260affine-constraint ::= affine-expr `>=` `0`
261 | affine-expr `==` `0`
262affine-constraint-conjunction ::= affine-constraint (`,` affine-constraint)*
263```
264
265Integer sets may be defined inline at the point of use, or may be hoisted to the
266top of the file and given a name with an integer set definition, and used by
267name.
268
Alex Zinenkoac487332019-12-10 11:00:29269```
Andy Davis59100a02019-05-13 18:05:59270integer-set-id ::= `#` suffix-id
271
272integer-set-inline
273 ::= dim-and-symbol-id-lists `:` '(' affine-constraint-conjunction? ')'
274
275// Declarations of integer sets are at the top of the file.
276integer-set-decl ::= integer-set-id `=` integer-set-inline
277
278// Uses of integer sets may use the inline form or the named form.
279integer-set ::= integer-set-id | integer-set-inline
280```
281
282The dimensionality of an integer set is the number of identifiers appearing in
283dimension list of the set. The affine-constraint non-terminals appearing in the
284syntax above are only allowed to contain identifiers from dims and symbols. A
285set with no constraints is a set that is unbounded along all of the set's
286dimensions.
287
288Example:
289
Alex Zinenkoac487332019-12-10 11:00:29290```mlir
Andy Davis59100a02019-05-13 18:05:59291// A example two-dimensional integer set with two symbols.
River Riddle4268e4f2020-01-13 21:12:37292#set42 = affine_set<(d0, d1)[s0, s1]
293 : (d0 >= 0, -d0 + s0 - 1 >= 0, d1 >= 0, -d1 + s1 - 1 >= 0)>
Andy Davis59100a02019-05-13 18:05:59294
River Riddlee7d594b2019-07-03 20:21:24295// Inside a Region
Andy Davis59100a02019-05-13 18:05:59296affine.if #set42(%i, %j)[%M, %N] {
297 ...
298}
299```
300
301`d0` and `d1` correspond to dimensional identifiers of the set, while `s0` and
302`s1` are symbol identifiers.
303
River Riddle465ef552019-04-05 15:19:42304## Operations
River Riddle6f7470a2019-02-06 00:29:25305
River Riddle16f27b72020-03-30 05:00:26306[include "Dialects/AffineOps.md"]
River Riddle6f7470a2019-02-06 00:29:25307
River Riddle16f27b72020-03-30 05:00:26308### 'affine.load' operation
Andy Davis1efc5112019-11-06 22:31:02309
310Syntax:
311
Alex Zinenkoac487332019-12-10 11:00:29312```
Andy Davis1efc5112019-11-06 22:31:02313operation ::= ssa-id `=` `affine.load` ssa-use `[` multi-dim-affine-map-of-ssa-ids `]` `:` memref-type
314```
Alex Zinenkoac487332019-12-10 11:00:29315
316The `affine.load` op reads an element from a memref, where the index for each
317memref dimension is an affine expression of loop induction variables and
318symbols. The output of 'affine.load' is a new value with the same type as the
319elements of the memref. An affine expression of loop IVs and symbols must be
320specified for each dimension of the memref. The keyword 'symbol' can be used to
321indicate SSA identifiers which are symbolic.
Andy Davis1efc5112019-11-06 22:31:02322
323Example:
324
Alex Zinenkoac487332019-12-10 11:00:29325```mlir
Andy Davis1efc5112019-11-06 22:31:02326
327 Example 1:
328
329 %1 = affine.load %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>
330
331 Example 2: Uses 'symbol' keyword for symbols '%n' and '%m'.
332
333 %1 = affine.load %0[%i0 + symbol(%n), %i1 + symbol(%m)]
334 : memref<100x100xf32>
335
336```
337
River Riddle16f27b72020-03-30 05:00:26338### 'affine.store' operation
Andy Davis1efc5112019-11-06 22:31:02339
340Syntax:
341
Alex Zinenkoac487332019-12-10 11:00:29342```
Andy Davis1efc5112019-11-06 22:31:02343operation ::= ssa-id `=` `affine.store` ssa-use, ssa-use `[` multi-dim-affine-map-of-ssa-ids `]` `:` memref-type
344```
Alex Zinenkoac487332019-12-10 11:00:29345
346The `affine.store` op writes an element to a memref, where the index for each
347memref dimension is an affine expression of loop induction variables and
348symbols. The 'affine.store' op stores a new value which is the same type as the
349elements of the memref. An affine expression of loop IVs and symbols must be
350specified for each dimension of the memref. The keyword 'symbol' can be used to
351indicate SSA identifiers which are symbolic.
Andy Davis1efc5112019-11-06 22:31:02352
353Example:
354
Alex Zinenkoac487332019-12-10 11:00:29355```mlir
Andy Davis1efc5112019-11-06 22:31:02356
357 Example 1:
358
359 affine.store %v0, %0[%i0 + 3, %i1 + 7] : memref<100x100xf32>
360
361 Example 2: Uses 'symbol' keyword for symbols '%n' and '%m'.
362
363 affine.store %v0, %0[%i0 + symbol(%n), %i1 + symbol(%m)]
364 : memref<100x100xf32>
365
366```
367
River Riddle16f27b72020-03-30 05:00:26368### 'affine.dma_start' operation
Andy Davis1efc5112019-11-06 22:31:02369
370Syntax:
371
Alex Zinenkoac487332019-12-10 11:00:29372```
Andy Davis1efc5112019-11-06 22:31:02373operation ::= `affine.dma_Start` ssa-use `[` multi-dim-affine-map-of-ssa-ids `]`, `[` multi-dim-affine-map-of-ssa-ids `]`, `[` multi-dim-affine-map-of-ssa-ids `]`, ssa-use `:` memref-type
374```
375
376The `affine.dma_start` op starts a non-blocking DMA operation that transfers
377data from a source memref to a destination memref. The source and destination
378memref need not be of the same dimensionality, but need to have the same
Mogballa54f4ea2021-10-12 23:14:57379elemental type. The operands include the source and destination memref's each
380followed by its indices, size of the data transfer in terms of the number of
381elements (of the elemental type of the memref), a tag memref with its indices,
382and optionally at the end, a stride and a number_of_elements_per_stride
383arguments. The tag location is used by an AffineDmaWaitOp to check for
384completion. The indices of the source memref, destination memref, and the tag
385memref have the same restrictions as any affine.load/store. In particular, index
386for each memref dimension must be an affine expression of loop induction
387variables and symbols. The optional stride arguments should be of 'index' type,
388and specify a stride for the slower memory space (memory space with a lower
389memory space id), transferring chunks of number_of_elements_per_stride every
390stride until %num_elements are transferred. Either both or no stride arguments
391should be specified. The value of 'num_elements' must be a multiple of
Andy Davis1efc5112019-11-06 22:31:02392'number_of_elements_per_stride'.
393
Andy Davis1efc5112019-11-06 22:31:02394Example:
395
Alex Zinenkoac487332019-12-10 11:00:29396```mlir
Andy Davis1efc5112019-11-06 22:31:02397For example, a DmaStartOp operation that transfers 256 elements of a memref
398'%src' in memory space 0 at indices [%i + 3, %j] to memref '%dst' in memory
399space 1 at indices [%k + 7, %l], would be specified as follows:
400
Mogballcb3aa492021-10-14 16:55:33401 %num_elements = arith.constant 256
Mogballa54f4ea2021-10-12 23:14:57402 %idx = arith.constant 0 : index
403 %tag = memref.alloc() : memref<1xi32, 4>
Andy Davis1efc5112019-11-06 22:31:02404 affine.dma_start %src[%i + 3, %j], %dst[%k + 7, %l], %tag[%idx],
405 %num_elements :
406 memref<40x128xf32, 0>, memref<2x1024xf32, 1>, memref<1xi32, 2>
407
408 If %stride and %num_elt_per_stride are specified, the DMA is expected to
409 transfer %num_elt_per_stride elements every %stride elements apart from
410 memory space 0 until %num_elements are transferred.
411
412 affine.dma_start %src[%i, %j], %dst[%k, %l], %tag[%idx], %num_elements,
413 %stride, %num_elt_per_stride : ...
Andy Davis1efc5112019-11-06 22:31:02414```
Alex Zinenkoac487332019-12-10 11:00:29415
River Riddle16f27b72020-03-30 05:00:26416### 'affine.dma_wait' operation
Andy Davis1efc5112019-11-06 22:31:02417
418Syntax:
419
Alex Zinenkoac487332019-12-10 11:00:29420```
Andy Davis1efc5112019-11-06 22:31:02421operation ::= `affine.dma_Start` ssa-use `[` multi-dim-affine-map-of-ssa-ids `]`, `[` multi-dim-affine-map-of-ssa-ids `]`, `[` multi-dim-affine-map-of-ssa-ids `]`, ssa-use `:` memref-type
422```
423
424The `affine.dma_start` op blocks until the completion of a DMA operation
Mogballa54f4ea2021-10-12 23:14:57425associated with the tag element '%tag[%index]'. %tag is a memref, and %index has
426to be an index with the same restrictions as any load/store index. In
427particular, index for each memref dimension must be an affine expression of loop
428induction variables and symbols. %num_elements is the number of elements
Andy Davis1efc5112019-11-06 22:31:02429associated with the DMA operation. For example:
430
431Example:
432
Alex Zinenkoac487332019-12-10 11:00:29433```mlir
River Riddle16f27b72020-03-30 05:00:26434affine.dma_start %src[%i, %j], %dst[%k, %l], %tag[%index], %num_elements :
435 memref<2048xf32, 0>, memref<256xf32, 1>, memref<1xi32, 2>
436...
437...
438affine.dma_wait %tag[%index], %num_elements : memref<1xi32, 2>
Andy Davis1efc5112019-11-06 22:31:02439```