@@ -93,17 +93,21 @@ def Linalg_PackOp : Linalg_RelayoutOp<"pack", [
93
93
tensor of rank `n + k` with a tiled and packed layout (maybe with padding)
94
94
and optionally transposes the tiled source tensor dimensions.
95
95
96
- `inner_dims_pos` (mandatory) specifies `k` source tensor dimensions that are
97
- being tiled, where `0 < k <= n`. The order of the dimensions matters:
98
- - The tiled dimensions (of size `inner_tiles`) are added to the end of the result
99
- tensor in the order in which they appear in `inner_dims_pos`.
100
- - `inner_dims_pos[i]` specifies the source tensor dimension tiled by
101
- `inner_tiles[i]`.
102
-
103
96
`inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes
104
97
correspond to the least significant ("inner") result tensor dimension sizes,
105
98
in the same order. Tile sizes can be static or dynamic.
106
99
100
+ `inner_dims_pos` (mandatory) specifies `k` source tensor dimensions that are
101
+ being tiled, where `0 <= k <= n`.
102
+ - `inner_dims_pos[i]` specifies the source tensor dimension tiled by
103
+ `inner_tiles[i]` where `0 <= i < k`. All the values in `inner_dims_pos` are
104
+ within [0, n).
105
+ - The tiled dimensions (of size `inner_tiles`) are added to the end of the
106
+ result tensor in the order in which they appear, i.e.
107
+ `shape(result)[rank(result) + i] = inner_tiles[i]` for `0 <= i < k`.
108
+ - The following relationship for the tiled dimensions holds:
109
+ `shape(result)[inner_dims_pos[i]] = shape(source)[inner_dims_pos[i]] / inner_tiles[i]`.
110
+
107
111
Example: If `inner_tiles = [16, 32]`, the result tensor has a shape of
108
112
`...x16x32`. If `inner_dims_pos = [0, 1]`, the 0th source dimension is tiled
109
113
by 16 and the 1st source dimension is tiled by 32. Other source dimensions
@@ -116,7 +120,19 @@ def Linalg_PackOp : Linalg_RelayoutOp<"pack", [
116
120
%0 = linalg.pack %source inner_dims_pos = [0, 1] inner_tiles = [8, 32]
117
121
into %dest : tensor<128x256xf32> -> tensor<16x8 x 8x32 xf32>
118
122
// \ / \ /
119
- // outer dims inner dims
123
+ // Outer Dims: 16x8 Inner Dims: 8x32
124
+
125
+ // CHW to CHWhw
126
+ %0 = linalg.pack %source inner_dims_pos = [2, 1] inner_tiles = [4, 2]
127
+ into %dest : tensor<3x20x24xf32> -> tensor<3x10x6 x 4x2 xf32>
128
+ // \ / \ /
129
+ // Outer Dims: 3x10x6 Inner Dims: 4x2
130
+
131
+ // HCW to HCWhw
132
+ %0 = linalg.pack %source inner_dims_pos = [2, 0] inner_tiles = [4, 2]
133
+ into %dest : tensor<18x3x32xf32> -> tensor<9x3x8 x 4x2 xf32>
134
+ // \ / \ /
135
+ // Outer Dims: 9x3x8 Inner Dims: 4x2
120
136
```
121
137
122
138
`outer_dims_perm` (optional) specifies a permutation for the outer
@@ -246,13 +262,6 @@ def Linalg_UnPackOp : Linalg_RelayoutOp<"unpack"> {
246
262
The "unpack" operation converts a source tensor of rank `n` with a tiled and
247
263
packed layout to a result tensor of rank `n - k`.
248
264
249
- `inner_dims_pos` (mandatory) specifies `k` source tensor dimensions with
250
- which the last `k` source tensor dimensions are combined, where
251
- `0 < k <= n/2`. Each `inner_dims_pos` element must be `>= 0` and `< n - k`.
252
- The order of the dimensions in `inner_dims_pos` matters: dimension
253
- `inner_dims_pos[i]` is combined with dimension `n - k + i` (assuming that
254
- `outer_dims_perm` is not specified).
255
-
256
265
`inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes
257
266
correspond to the least significant ("inner") source tensor dimension sizes.
258
267
The behavior of this op is undefined if:
@@ -262,21 +271,50 @@ def Linalg_UnPackOp : Linalg_RelayoutOp<"unpack"> {
262
271
`inner_dims_pos[i]` (assuming that `outer_dims_perm` is not specified)
263
272
evenly.
264
273
274
+ `inner_dims_pos` (mandatory) specifies `k` result tensor (i.e. unpacked
275
+ tensor) dimensions that were tiled with the `inner_tiles` to create the
276
+ packed source tensor. The source tensor (i.e. packed tensor) dimensions can
277
+ be unpacked given `inner_dims_pos` as follows.
278
+ - For `0 <= i < k` the following relationship holds:
279
+ `shape(result)[inner_dims_pos[i]] <= shape(source)[n-k+i] * shape(source)[inner_dims_pos[i]]`.
280
+ - For `0 <= j < n-k` and `j` not in `inner_dims_pos` the following relationship holds:
281
+ `shape(result)[j] = shape(source)[j]`.
282
+
265
283
`outer_dims_perm` (optional) specifies a permutation for the outer
266
284
dimensions. If specified, it must have `n - k` elements. If specified, this
267
285
permutation is applied before combining any dimensions.
268
286
269
- Example:
287
+ Note, the unpack operation may drop any padding introduced by the pack
288
+ operation and hence the following holds
289
+ `NumElementsOf(source) >= NumElementsOf(result)`.
290
+
291
+ Examples:
270
292
271
293
```mlir
272
294
// NCnc to NC:
273
295
%0 = linalg.unpack %source inner_dims_pos = [0, 1] inner_tiles = [8, 32]
274
- into %dest : tensor<16x8x8x32xf32> -> tensor<128x256xf32>
296
+ into %dest : tensor<16x8 x 8x32 xf32> -> tensor<128x256xf32>
297
+ // \ / \ /
298
+ // Outer Dims: 16x8 Inner Dims: 8x32
275
299
276
300
// CK to KCck:
277
301
%0 = linalg.unpack %source outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]
278
- inner_tiles = [8, 32] into %dest
279
- : tensor<8x16x8x32xf32> -> tensor<128x256xf32>
302
+ inner_tiles = [8, 32]
303
+ into %dest : tensor<8x16 x 8x32 xf32> -> tensor<128x256xf32>
304
+ // \ / \ /
305
+ // Outer Dims: 8x16 Inner Dims: 8x32
306
+
307
+ // CHW to CHWhw:
308
+ %0 = linalg.unpack %source inner_dims_pos = [2, 1] inner_tiles = [4, 2]
309
+ into %dest : tensor<3x10x6 x 4x2 xf32> -> tensor<3x20x24xf32>
310
+ // \ / \ /
311
+ // Outer Dims: 3x10x6 Inner Dims: 4x2
312
+
313
+ // HCW to HCWhw
314
+ %0 = linalg.unpack %source inner_dims_pos = [2, 0] inner_tiles = [4, 2]
315
+ into %dest : tensor<9x3x8 x 4x2 xf32> -> tensor<18x3x32xf32>
316
+ // \ / \ /
317
+ // Outer Dims: 9x3x8 Inner Dims: 4x2
280
318
```
281
319
}];
282
320
let arguments = (ins AnyRankedTensor:$source,
0 commit comments