Skip to content

Commit 461a6e6

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 60d1e17 commit 461a6e6

File tree

6 files changed

+2
-2055
lines changed

6 files changed

+2
-2055
lines changed

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

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

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

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)