Skip to content

Commit 55f4c72

Browse files
committed
[mlir][tensor][linalg] Move Pack/Unpack Ops to Linalg (4/4)
This is merely moving code around, no new functionality is added. PATCH 4: Remove `tensor.{pack|unpack}` and all the associated code (e.g. transfromations, verifiers, etc). CONTEXT: This change was discussed in the following RFC: * https://discourse.llvm.org/t/rfc-move-tensor-pack-and-tensor-unpack-into-linalg
1 parent 1d2686e commit 55f4c72

File tree

6 files changed

+2
-2053
lines changed

6 files changed

+2
-2053
lines changed

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td

Lines changed: 0 additions & 308 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,314 +1818,6 @@ def Tensor_SplatOp : Tensor_Op<"splat", [
18181818
let hasVerifier = 1;
18191819
}
18201820

1821-
//===----------------------------------------------------------------------===//
1822-
// RelayoutOp
1823-
//===----------------------------------------------------------------------===//
1824-
1825-
class Tensor_RelayoutOp<string mnemonic, list<Trait> traits = []> :
1826-
Tensor_Op<mnemonic, !listconcat(traits, [
1827-
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
1828-
DestinationStyleOpInterface,
1829-
ConditionallySpeculatable, NoMemoryEffect,
1830-
DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface>,
1831-
TypesMatchWith<"result type matches type of dest",
1832-
"dest", "result",
1833-
"$_self">])> {
1834-
1835-
code commonExtraClassDeclaration = [{
1836-
size_t getSourceRank() { return getSourceType().getRank(); };
1837-
size_t getDestRank() { return getDestType().getRank(); };
1838-
RankedTensorType getSourceType() {
1839-
return ::llvm::cast<RankedTensorType>(getSource().getType()); };
1840-
RankedTensorType getDestType() {
1841-
return ::llvm::cast<RankedTensorType>(getDest().getType()); };
1842-
1843-
MutableOperandRange getDpsInitsMutable() { return getDestMutable(); }
1844-
1845-
/// Interface method for ConditionallySpeculatable.
1846-
Speculation::Speculatability getSpeculatability();
1847-
1848-
/// Return a mapping from positions `inner_dims_pos` to their
1849-
/// tile factors.
1850-
DenseMap<int64_t, OpFoldResult> getDimAndTileMapping();
1851-
1852-
/// Return the tile sizes as OpFoldResult.
1853-
SmallVector<OpFoldResult> getMixedTiles();
1854-
1855-
/// Return the tile sizes as `int64_t`. If a tile size is dynamic
1856-
/// a sentinel `kDynamic` is introduced at that position in
1857-
/// the returned vector.
1858-
SmallVector<int64_t> getStaticTiles();
1859-
1860-
/// Retrieve all outer dims for this Pack/UnPack Op, i.e. all the leading
1861-
/// dims excluding the trailing dims corresponding to `innerTiles`. Note
1862-
/// that this will include both tiled and non-tiled dimensions. The order
1863-
/// of the output dimensions is consistent with the shape of the packed
1864-
/// tensor.
1865-
ArrayRef<int64_t> getAllOuterDims();
1866-
1867-
/// Similar to `getAllOuterDims`, but only retrieve the outer dims that
1868-
/// have been tiled. Also, the order of the output dimensions is consistent
1869-
/// with `inner_dims_pos` rather than the packed tensor.
1870-
SmallVector<int64_t> getTiledOuterDims();
1871-
}];
1872-
1873-
let hasVerifier = 1;
1874-
}
1875-
1876-
//===----------------------------------------------------------------------===//
1877-
// PackOp
1878-
//===----------------------------------------------------------------------===//
1879-
1880-
def Tensor_PackOp : Tensor_RelayoutOp<"pack", [
1881-
AttrSizedOperandSegments]> {
1882-
let summary = "tensor pack operation";
1883-
let description = [{
1884-
The "pack" operation converts a source tensor of rank `n` into a result
1885-
tensor of rank `n + k` with a tiled and packed layout (maybe with padding)
1886-
and optionally transposes the tiled source tensor dimensions.
1887-
1888-
`inner_dims_pos` (mandatory) specifies `k` source tensor dimensions that are
1889-
being tiled, where `0 < k <= n`. The order of the dimensions matters:
1890-
- The tiled dimensions (of size `inner_tiles`) are added to the end of the result
1891-
tensor in the order in which they appear in `inner_dims_pos`.
1892-
- `inner_dims_pos[i]` specifies the source tensor dimension tiled by
1893-
`inner_tiles[i]`.
1894-
1895-
`inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes
1896-
correspond to the least significant ("inner") result tensor dimension sizes,
1897-
in the same order. Tile sizes can be static or dynamic.
1898-
1899-
Example: If `inner_tiles = [16, 32]`, the result tensor has a shape of
1900-
`...x16x32`. If `inner_dims_pos = [0, 1]`, the 0th source dimension is tiled
1901-
by 16 and the 1st source dimension is tiled by 32. Other source dimensions
1902-
(if any) are not tiled. If `inner_dims_pos = [1, 0]`, the 1st dimension is
1903-
tiled by 16 and the 0th dimension is tiled by 32.
1904-
1905-
Example:
1906-
```mlir
1907-
// NC to NCnc
1908-
%0 = tensor.pack %source inner_dims_pos = [0, 1] inner_tiles = [8, 32]
1909-
into %dest : tensor<128x256xf32> -> tensor<16x8 x 8x32 xf32>
1910-
// \ / \ /
1911-
// outer dims inner dims
1912-
```
1913-
1914-
`outer_dims_perm` (optional) specifies a permutation for the outer
1915-
dimensions. If specified, it must have `n` elements.
1916-
1917-
Example:
1918-
```mlir
1919-
// CK to KCck
1920-
%0 = tensor.pack %source outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]
1921-
inner_tiles = [8, 32] into %dest
1922-
: tensor<128x256xf32> -> tensor<8x16 x 8x32 xf32>
1923-
// \ /
1924-
// compare with "NC to NCnc": outer dims are transposed
1925-
```
1926-
1927-
`padding_value` specifies a padding value at the boundary on non-perfectly
1928-
divisible dimensions. Padding is optional:
1929-
- If absent, it is UB if the tile does not perfectly divide the dimension.
1930-
- If present, it will pad along high dimensions (high-padding) to make the
1931-
tile complete.
1932-
1933-
Example:
1934-
```mlir
1935-
%0 = tensor.pack %arg0 padding_value(%pad : f32) outer_dims_perm = [2, 1, 0]
1936-
inner_dims_pos = [1] inner_tiles = [2] into %arg1
1937-
: tensor<200x127x256xf32> -> tensor<256x64x200x2xf32>
1938-
// \
1939-
// padded and tiled dim
1940-
//
1941-
// Source dimension 1 is tiled. 64 does not divide 127 evenly, so 1 padded
1942-
// element is added at the end.
1943-
//
1944-
// Note: Only tiled dimensions can be padded.
1945-
```
1946-
}];
1947-
let arguments = (ins AnyRankedTensor:$source,
1948-
AnyRankedTensor:$dest,
1949-
Optional<AnyType>:$padding_value,
1950-
DefaultValuedOptionalAttr<DenseI64ArrayAttr, "{}">:$outer_dims_perm,
1951-
DenseI64ArrayAttr:$inner_dims_pos,
1952-
Variadic<Index>:$inner_tiles,
1953-
DenseI64ArrayAttr:$static_inner_tiles);
1954-
let results = (outs AnyRankedTensor:$result);
1955-
let assemblyFormat = [{
1956-
$source
1957-
(`padding_value` `(` $padding_value^ `:` type($padding_value) `)`)?
1958-
(`outer_dims_perm` `=` $outer_dims_perm^)?
1959-
`inner_dims_pos` `=` $inner_dims_pos
1960-
`inner_tiles` `=`
1961-
custom<DynamicIndexList>($inner_tiles, $static_inner_tiles)
1962-
`into` $dest attr-dict `:` type($source) `->` type($dest)
1963-
}];
1964-
1965-
let builders = [
1966-
OpBuilder<(ins "Value":$source, "Value":$dest,
1967-
"ArrayRef<int64_t>":$innerDimsPos,
1968-
"ArrayRef<OpFoldResult>":$innerTiles,
1969-
CArg<"std::optional<Value>", "std::nullopt">:$paddingValue,
1970-
CArg<"ArrayRef<int64_t>", "{}">:$outerDimsPerm)>
1971-
];
1972-
1973-
let extraClassDeclaration = commonExtraClassDeclaration # [{
1974-
// Method to get the shape of the result as `SmallVector<OpFoldResult>`.
1975-
// This is a static method to allow getting the shape of the destination
1976-
// expected while creating a `pack` op.
1977-
static SmallVector<OpFoldResult> getResultShape(OpBuilder &builder,
1978-
Location loc, ArrayRef<OpFoldResult> sourceDims,
1979-
ArrayRef<OpFoldResult> innerTileDims, ArrayRef<int64_t> innerDimsPos,
1980-
ArrayRef<int64_t> outerDimsPerm = {});
1981-
1982-
// Method to get the `RankedTensorType` of the result based on the inner
1983-
// tiles, position of the inner tiles (innerDimsPos) and interchange vector
1984-
// of outer loops (outerDimsPerm).
1985-
static RankedTensorType inferPackedType(RankedTensorType sourceType,
1986-
ArrayRef<int64_t> innerTileSizes, ArrayRef<int64_t> innerDimsPos,
1987-
ArrayRef<int64_t> outerDimsPerm = {});
1988-
1989-
// Returns true if we have enough static information to catch undefined
1990-
// behavior when the tile size does not divide perfectly the dimension of
1991-
// the input tensor. Detecting UB requires that the input size and either
1992-
// corresponding tile or output size are static.
1993-
static bool requirePaddingValue(ArrayRef<int64_t> inputShape,
1994-
ArrayRef<int64_t> innerDimsPos,
1995-
ArrayRef<int64_t> outputShape,
1996-
ArrayRef<int64_t> outerDimsPerm,
1997-
ArrayRef<OpFoldResult> innerTiles);
1998-
1999-
static Value createDestinationTensor(OpBuilder &b, Location loc,
2000-
Value source, ArrayRef<OpFoldResult> innerTileSizes,
2001-
ArrayRef<int64_t> innerDimsPos, ArrayRef<int64_t> outerDimsPerm);
2002-
2003-
/// Build and return a new PackOp that is a clone of the current PackOp with
2004-
/// (innerDimsPos, innerTiles) (resp. outerDimsPerm) are permuted by
2005-
/// innerPermutation (resp. outerPermutation).
2006-
/// A new `tensor.empty` of the proper shape is built in the process.
2007-
/// Asserts that:
2008-
/// - At least one of innerPermutation or outerPermutation is non-empty.
2009-
/// - If not empty, innerPermutation is a valid permutation of size
2010-
/// matching innerDimPos.
2011-
/// - If not empty, outerPermutation is a valid permutation of size
2012-
/// matching outerDimsPerm.
2013-
PackOp createTransposedClone(OpBuilder &b,
2014-
Location loc,
2015-
ArrayRef<int64_t> innerPermutation,
2016-
ArrayRef<int64_t> outerPermutation);
2017-
2018-
/// Check if this PackOp is like a simple pad operation.
2019-
/// In other words, this operation:
2020-
/// 1. adds useless dimensions (dimension of size 1),
2021-
/// 2. pads the other ones, and
2022-
/// 3. doesn't shuffle the dimensions
2023-
bool isLikePad();
2024-
}];
2025-
2026-
let hasCanonicalizeMethod = 1;
2027-
2028-
let hasFolder = 1;
2029-
}
2030-
2031-
//===----------------------------------------------------------------------===//
2032-
// UnPackOp
2033-
//===----------------------------------------------------------------------===//
2034-
2035-
def Tensor_UnPackOp : Tensor_RelayoutOp<"unpack"> {
2036-
let summary = "tensor unpack operation";
2037-
let description = [{
2038-
The "unpack" operation converts a source tensor of rank `n` with a tiled and
2039-
packed layout to a result tensor of rank `n - k`.
2040-
2041-
`inner_dims_pos` (mandatory) specifies `k` source tensor dimensions with
2042-
which the last `k` source tensor dimensions are combined, where
2043-
`0 < k <= n/2`. Each `inner_dims_pos` element must be `>= 0` and `< n - k`.
2044-
The order of the dimensions in `inner_dims_pos` matters: dimension
2045-
`inner_dims_pos[i]` is combined with dimension `n - k + i` (assuming that
2046-
`outer_dims_perm` is not specified).
2047-
2048-
`inner_tiles` (mandatory) specifies `k` tile sizes. These tile sizes
2049-
correspond to the least significant ("inner") source tensor dimension sizes.
2050-
The behavior of this op is undefined if:
2051-
- `inner_tiles` do not exactly match with the corresponding source tensor
2052-
dimension sizes.
2053-
- Or, `inner_tiles[i]` does not divide the size of dimension
2054-
`inner_dims_pos[i]` (assuming that `outer_dims_perm` is not specified)
2055-
evenly.
2056-
2057-
`outer_dims_perm` (optional) specifies a permutation for the outer
2058-
dimensions. If specified, it must have `n - k` elements. If specified, this
2059-
permutation is applied before combining any dimensions.
2060-
2061-
Example:
2062-
2063-
```mlir
2064-
// NCnc to NC:
2065-
%0 = tensor.unpack %source inner_dims_pos = [0, 1] inner_tiles = [8, 32]
2066-
into %dest : tensor<16x8x8x32xf32> -> tensor<128x256xf32>
2067-
2068-
// CK to KCck:
2069-
%0 = tensor.unpack %source outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]
2070-
inner_tiles = [8, 32] into %dest
2071-
: tensor<8x16x8x32xf32> -> tensor<128x256xf32>
2072-
```
2073-
}];
2074-
let arguments = (ins AnyRankedTensor:$source,
2075-
AnyRankedTensor:$dest,
2076-
DefaultValuedOptionalAttr<DenseI64ArrayAttr, "{}">:$outer_dims_perm,
2077-
DenseI64ArrayAttr:$inner_dims_pos,
2078-
Variadic<Index>:$inner_tiles,
2079-
DenseI64ArrayAttr:$static_inner_tiles);
2080-
let results = (outs AnyRankedTensor:$result);
2081-
let assemblyFormat = [{
2082-
$source
2083-
(`outer_dims_perm` `=` $outer_dims_perm^)?
2084-
`inner_dims_pos` `=` $inner_dims_pos
2085-
`inner_tiles` `=`
2086-
custom<DynamicIndexList>($inner_tiles, $static_inner_tiles)
2087-
`into` $dest attr-dict `:` type($source) `->` type($dest)
2088-
}];
2089-
2090-
let builders = [
2091-
OpBuilder<(ins "Value":$source, "Value":$dest,
2092-
"ArrayRef<int64_t>":$innerDimsPos,
2093-
"ArrayRef<OpFoldResult>":$innerTiles,
2094-
CArg<"ArrayRef<int64_t>", "{}">:$outerDimsPerm)>
2095-
];
2096-
2097-
let extraClassDeclaration = commonExtraClassDeclaration # [{
2098-
static Value createDestinationTensor(OpBuilder &b, Location loc,
2099-
Value source, ArrayRef<OpFoldResult> innerTileSizes,
2100-
ArrayRef<int64_t> innerDimsPos, ArrayRef<int64_t> outerDimsPerm);
2101-
2102-
/// Build and return a new UnPackOp that is a clone of the current UnPackOp
2103-
/// with (innerDimsPos, innerTiles) (resp. outerDimsPerm) are permuted by
2104-
/// innerPermutation (resp. outerPermutation).
2105-
/// Asserts that:
2106-
/// - At least one of innerPermutation or outerPermutation is non-empty.
2107-
/// - If not empty, innerPermutation is a valid permutation of size
2108-
/// matching innerDimPos.
2109-
/// - If not empty, outerPermutation is a valid permutation of size
2110-
/// matching outerDimsPerm.
2111-
UnPackOp createTransposedClone(OpBuilder &b,
2112-
Location loc,
2113-
Value transposedSource,
2114-
ArrayRef<int64_t> innerPermutation,
2115-
ArrayRef<int64_t> outerPermutation);
2116-
2117-
/// Check if this UnPackOp is like a simple unpad operation.
2118-
/// In other words, this operation:
2119-
/// 1. drops useless dimensions (dimension of size 1), and
2120-
/// 2. reduces dimensions in place (i.e., no transpose.)
2121-
bool isLikeUnPad();
2122-
}];
2123-
2124-
let hasCanonicalizeMethod = 1;
2125-
2126-
let hasFolder = 1;
2127-
}
2128-
21291821
//===----------------------------------------------------------------------===//
21301822
// YieldOp
21311823
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/Tensor/Utils/Utils.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,6 @@ FailureOr<RankedTensorType>
4242
computeTransposedType(RankedTensorType rankedTensorType,
4343
ArrayRef<int64_t> transposeVector);
4444

45-
/// Shell function to compute the Destination Permutation of PackOp
46-
/// This function uses the helper function `computePackUnPackPerm` to get
47-
/// the permutation vector. Only major difference between UnPack and Pack is
48-
/// that packOp uses destination rank whereas unpack Uses source rank.
49-
SmallVector<int64_t> getPackInverseDestPerm(tensor::PackOp packOp);
50-
51-
/// Shell function to compute the Source Permutation of unPackOp.
52-
/// This function, like the getPackInverseDestPerm uses the helper function
53-
/// computePackUnPackPerm` to get the permutation vector.
54-
/// Only major difference between UnPack and Pack is that packOp uses
55-
/// destination rank whereas unpack Uses source rank.
56-
SmallVector<int64_t> getUnPackInverseSrcPerm(tensor::UnPackOp unpackOp);
57-
58-
/// Shell function to compute the Source rank permutation for unpackOp
59-
/// Unpack requires some packing metadata data information, so created
60-
/// another function where this value is passed by reference.
61-
SmallVector<int64_t> getUnPackInverseSrcPerm(tensor::UnPackOp,
62-
PackingMetadata &metadata);
63-
6445
/// A tensor.insert_slice is a cast-like operation if it merely rank-extends the
6546
/// source tensor or inserts the source tensor into a destination tensor with
6647
/// the same shape.

mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void TensorDialect::initialize() {
6363
declarePromisedInterfaces<SubsetInsertionOpInterface, InsertSliceOp,
6464
ParallelInsertSliceOp>();
6565
declarePromisedInterface<SubsetExtractionOpInterface, ExtractSliceOp>();
66-
declarePromisedInterfaces<TilingInterface, PadOp, PackOp, UnPackOp>();
66+
declarePromisedInterfaces<TilingInterface, PadOp>();
6767
declarePromisedInterfaces<ValueBoundsOpInterface, CastOp, DimOp, EmptyOp,
6868
ExtractSliceOp, PadOp, RankOp>();
6969
}

0 commit comments

Comments
 (0)