@@ -93,17 +93,21 @@ def Linalg_PackOp : Linalg_RelayoutOp<"pack", [
9393 tensor of rank `n + k` with a tiled and packed layout (maybe with padding)
9494 and optionally transposes the tiled source tensor dimensions.
9595
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-
10396 `inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes
10497 correspond to the least significant ("inner") result tensor dimension sizes,
10598 in the same order. Tile sizes can be static or dynamic.
10699
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+
107111 Example: If `inner_tiles = [16, 32]`, the result tensor has a shape of
108112 `...x16x32`. If `inner_dims_pos = [0, 1]`, the 0th source dimension is tiled
109113 by 16 and the 1st source dimension is tiled by 32. Other source dimensions
@@ -116,7 +120,19 @@ def Linalg_PackOp : Linalg_RelayoutOp<"pack", [
116120 %0 = linalg.pack %source inner_dims_pos = [0, 1] inner_tiles = [8, 32]
117121 into %dest : tensor<128x256xf32> -> tensor<16x8 x 8x32 xf32>
118122 // \ / \ /
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
120136 ```
121137
122138 `outer_dims_perm` (optional) specifies a permutation for the outer
@@ -246,13 +262,6 @@ def Linalg_UnPackOp : Linalg_RelayoutOp<"unpack"> {
246262 The "unpack" operation converts a source tensor of rank `n` with a tiled and
247263 packed layout to a result tensor of rank `n - k`.
248264
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-
256265 `inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes
257266 correspond to the least significant ("inner") source tensor dimension sizes.
258267 The behavior of this op is undefined if:
@@ -262,21 +271,50 @@ def Linalg_UnPackOp : Linalg_RelayoutOp<"unpack"> {
262271 `inner_dims_pos[i]` (assuming that `outer_dims_perm` is not specified)
263272 evenly.
264273
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+
265283 `outer_dims_perm` (optional) specifies a permutation for the outer
266284 dimensions. If specified, it must have `n - k` elements. If specified, this
267285 permutation is applied before combining any dimensions.
268286
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:
270292
271293 ```mlir
272294 // NCnc to NC:
273295 %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
275299
276300 // CK to KCck:
277301 %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
280318 ```
281319 }];
282320 let arguments = (ins AnyRankedTensor:$source,
0 commit comments