Skip to content

Commit 57dd987

Browse files
authored
Merge pull request #185 from Xilinx/tiagot.constant_fold_tile
feat: constant fold tosa.tile.
2 parents e7188da + 4f85c12 commit 57dd987

File tree

5 files changed

+268
-41
lines changed

5 files changed

+268
-41
lines changed

mlir/include/mlir/Dialect/Tosa/Transforms/Passes.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ void populateTosaDecomposeTransposeConv(MLIRContext *ctx,
3030
RewritePatternSet &patterns);
3131
void populateTosaDecomposeDepthwise(MLIRContext *ctx,
3232
RewritePatternSet &patterns);
33-
void populateTosaFoldConstantPatterns(MLIRContext *ctx,
34-
RewritePatternSet &patterns,
35-
bool foldSplatOrSingleUseOnly,
36-
bool enableIntCastFolding);
33+
void populateTosaFoldConstantPatterns(
34+
MLIRContext *ctx, RewritePatternSet &patterns,
35+
const TosaLayerwiseConstantFoldPassOptions &options);
3736
void populateTosaConstantReduction(MLIRContext *ctx,
3837
RewritePatternSet &patterns,
3938
bool aggressiveReduceConstant);

mlir/include/mlir/Dialect/Tosa/Transforms/Passes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ def TosaLayerwiseConstantFoldPass : Pass<"tosa-layerwise-constant-fold", "func::
3232
/*default=*/"false",
3333
"Always perform the reduce constant optimization"
3434
"May add more tosa.const but would reduce runtime calculations">,
35+
Option<"enableTileFolding", "enable-tile-folding", "bool",
36+
/*default=*/"false",
37+
"Enables folding of tosa.tile operation. May generate bigger constant values.">,
3538
];
3639
}
3740

mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp

Lines changed: 146 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,7 +1659,7 @@ struct TosaFoldConstantPad : public TosaFoldConstantBase<tosa::PadOp> {
16591659
if (!matchPattern(input, m_Constant(&inputValues)))
16601660
return failure();
16611661

1662-
// Only fold op with multiple users if foldSplatOrSingleUseOnly == true.
1662+
// Only fold op with multiple users if foldSplatOrSingleUseOnly is false.
16631663
if (!llvm::hasSingleElement(input.getDefiningOp()->getUsers()) &&
16641664
foldSplatOrSingleUseOnly)
16651665
return failure();
@@ -1684,6 +1684,116 @@ struct TosaFoldConstantPad : public TosaFoldConstantBase<tosa::PadOp> {
16841684
}
16851685
};
16861686

1687+
template <typename BaseType, typename RangeT>
1688+
void tileArray(ShapedType inputType, RangeT inputValues, ShapedType outputType,
1689+
SmallVector<BaseType> &outputValues) {
1690+
1691+
auto inputShape = inputType.getShape();
1692+
auto outputShape = outputType.getShape();
1693+
1694+
SmallVector<int64_t> indexInTarget(outputType.getRank());
1695+
1696+
for (size_t outIndex = 0, e = outputValues.size(); outIndex < e; ++outIndex) {
1697+
auto index = offsetToIndex(outputShape, outIndex);
1698+
for (auto i = 0; i < outputType.getRank(); ++i) {
1699+
indexInTarget[i] = index[i] % inputShape[i];
1700+
}
1701+
auto inputIndexOffset = indexToOffset(inputShape, indexInTarget);
1702+
BaseType value = inputValues[inputIndexOffset];
1703+
outputValues[outIndex] = value;
1704+
}
1705+
}
1706+
1707+
template <typename BaseType>
1708+
DenseElementsAttr tileTypeRaw(DenseElementsAttr attr, ShapedType inputType,
1709+
ShapedType outputType) {
1710+
ArrayRef<BaseType> inputValues =
1711+
cast<DenseIntOrFPElementsAttr>(attr).getNonSplatRawData<BaseType>();
1712+
1713+
SmallVector<BaseType> outputValues;
1714+
outputValues.resize_for_overwrite(outputType.getNumElements());
1715+
tileArray<BaseType>(inputType, inputValues, /*out*/ outputType, outputValues);
1716+
1717+
ArrayRef rawOutputValues(reinterpret_cast<const char *>(outputValues.data()),
1718+
outputValues.size() * sizeof(BaseType));
1719+
return DenseElementsAttr::getFromRawBuffer(outputType, rawOutputValues);
1720+
}
1721+
1722+
template <typename BaseType>
1723+
DenseElementsAttr tileType(DenseElementsAttr attr, ShapedType inputType,
1724+
ShapedType outputType) {
1725+
1726+
auto inputValues = attr.getValues<BaseType>();
1727+
SmallVector<BaseType> outputValues(outputType.getNumElements(),
1728+
*std::begin(inputValues));
1729+
tileArray<BaseType>(inputType, inputValues, outputType, /*out*/ outputValues);
1730+
return DenseElementsAttr::get(outputType,
1731+
llvm::ArrayRef<BaseType>(outputValues));
1732+
}
1733+
1734+
DenseElementsAttr tile(DenseElementsAttr inputValues, ShapedType outputType) {
1735+
1736+
auto inputType = inputValues.getType();
1737+
auto baseType = inputType.getElementType();
1738+
1739+
// Handle possible integer types
1740+
if (auto intType = dyn_cast<IntegerType>(baseType)) {
1741+
switch (intType.getWidth()) {
1742+
case 1:
1743+
// i1 has special alignment which is not handled by transposeTypeRaw.
1744+
return tileType<bool>(inputValues, inputType, outputType);
1745+
case 8:
1746+
return tileTypeRaw<uint8_t>(inputValues, inputType, outputType);
1747+
case 16:
1748+
return tileTypeRaw<uint16_t>(inputValues, inputType, outputType);
1749+
case 32:
1750+
return tileTypeRaw<uint32_t>(inputValues, inputType, outputType);
1751+
case 64:
1752+
return tileTypeRaw<uint64_t>(inputValues, inputType, outputType);
1753+
default:
1754+
return tileType<APInt>(inputValues, inputType, outputType);
1755+
}
1756+
}
1757+
1758+
// Handle possible float types
1759+
if (baseType.isF32()) {
1760+
return tileTypeRaw<uint32_t>(inputValues, inputType, outputType);
1761+
}
1762+
if (baseType.isF64()) {
1763+
return tileTypeRaw<uint64_t>(inputValues, inputType, outputType);
1764+
}
1765+
if (baseType.isBF16()) {
1766+
return tileTypeRaw<uint16_t>(inputValues, inputType, outputType);
1767+
}
1768+
return tileType<APFloat>(inputValues, inputType, outputType);
1769+
}
1770+
1771+
struct TosaFoldConstantTile : public TosaFoldConstantBase<tosa::TileOp> {
1772+
using TosaFoldConstantBase::TosaFoldConstantBase;
1773+
1774+
LogicalResult matchAndRewrite(tosa::TileOp op,
1775+
PatternRewriter &rewriter) const override {
1776+
auto outputType = cast<ShapedType>(op.getType());
1777+
// TOSA doesn't support quantized types.
1778+
if (!outputType.getElementType().isIntOrIndexOrFloat())
1779+
return failure();
1780+
1781+
auto input = op.getInput1();
1782+
DenseElementsAttr inputValues;
1783+
if (!matchPattern(input, m_Constant(&inputValues)))
1784+
return failure();
1785+
1786+
// Only fold op with multiple users if foldSplatOrSingleUseOnly is false.
1787+
if (!llvm::hasSingleElement(input.getDefiningOp()->getUsers()) &&
1788+
foldSplatOrSingleUseOnly)
1789+
return failure();
1790+
1791+
rewriter.replaceOpWithNewOp<tosa::ConstOp>(op, outputType,
1792+
tile(inputValues, outputType));
1793+
return success();
1794+
}
1795+
};
1796+
16871797
/// Getting the axes position of the element which is located
16881798
/// in the tensor at the counter index
16891799

@@ -1836,41 +1946,42 @@ struct ReduceConstantOptimization : public OpRewritePattern<OperationType> {
18361946

18371947
void mlir::tosa::populateTosaFoldConstantPatterns(
18381948
MLIRContext *ctx, RewritePatternSet &patterns,
1839-
bool foldSplatOrSingleUseOnly,
1840-
bool enableIntCastFolding) {
1841-
1842-
patterns.add<TosaFoldConstantTranspose>(ctx, foldSplatOrSingleUseOnly);
1843-
patterns.add<TosaFoldConstantReciprocal>(ctx, foldSplatOrSingleUseOnly);
1844-
patterns.add<TosaFoldConstantReshape>(ctx, foldSplatOrSingleUseOnly);
1845-
patterns.add<TosaFoldConstantRSQRT>(ctx, foldSplatOrSingleUseOnly);
1846-
patterns.add<TosaFoldConstantLogicalNot>(ctx, foldSplatOrSingleUseOnly);
1847-
patterns.add<TosaFoldConstantPow>(ctx, foldSplatOrSingleUseOnly);
1848-
patterns.add<TosaFoldConstantMul>(ctx, foldSplatOrSingleUseOnly);
1849-
patterns.add<TosaFoldConstantClamp>(ctx, foldSplatOrSingleUseOnly);
1850-
if (enableIntCastFolding) {
1851-
patterns.add<TosaFoldConstantCast>(ctx, foldSplatOrSingleUseOnly);
1949+
const TosaLayerwiseConstantFoldPassOptions &options) {
1950+
1951+
patterns.add<TosaFoldConstantTranspose>(ctx, options.foldSplatOrSingleUseOnly);
1952+
patterns.add<TosaFoldConstantReciprocal>(ctx, options.foldSplatOrSingleUseOnly);
1953+
patterns.add<TosaFoldConstantReshape>(ctx, options.foldSplatOrSingleUseOnly);
1954+
patterns.add<TosaFoldConstantRSQRT>(ctx, options.foldSplatOrSingleUseOnly);
1955+
patterns.add<TosaFoldConstantLogicalNot>(ctx, options.foldSplatOrSingleUseOnly);
1956+
patterns.add<TosaFoldConstantPow>(ctx, options.foldSplatOrSingleUseOnly);
1957+
patterns.add<TosaFoldConstantMul>(ctx, options.foldSplatOrSingleUseOnly);
1958+
patterns.add<TosaFoldConstantClamp>(ctx, options.foldSplatOrSingleUseOnly);
1959+
if (options.enableIntCastFolding) {
1960+
patterns.add<TosaFoldConstantCast>(ctx, options.foldSplatOrSingleUseOnly);
18521961
} else {
1853-
patterns.add<TosaFoldConstantFloatCasts>(ctx, foldSplatOrSingleUseOnly);
1854-
}
1855-
patterns.add<TosaFoldConstantAdd>(ctx, foldSplatOrSingleUseOnly);
1856-
patterns.add<TosaFoldConstantSub>(ctx, foldSplatOrSingleUseOnly);
1857-
patterns.add<TosaFoldConstantGreater>(ctx, foldSplatOrSingleUseOnly);
1858-
patterns.add<TosaFoldConstantBitwiseNot>(ctx, foldSplatOrSingleUseOnly);
1859-
patterns.add<TosaFoldConstantFloor>(ctx, foldSplatOrSingleUseOnly);
1860-
patterns.add<TosaFoldConstantCeil>(ctx, foldSplatOrSingleUseOnly);
1861-
patterns.add<TosaFoldConstantErf>(ctx, foldSplatOrSingleUseOnly);
1862-
patterns.add<TosaFoldConstantExp>(ctx, foldSplatOrSingleUseOnly);
1863-
patterns.add<TosaFoldConstantLog>(ctx, foldSplatOrSingleUseOnly);
1864-
patterns.add<TosaFoldConstantCos>(ctx, foldSplatOrSingleUseOnly);
1865-
patterns.add<TosaFoldConstantSin>(ctx, foldSplatOrSingleUseOnly);
1866-
patterns.add<TosaFoldConstantBitwiseAnd>(ctx, foldSplatOrSingleUseOnly);
1867-
patterns.add<TosaFoldConstantBitwiseOr>(ctx, foldSplatOrSingleUseOnly);
1868-
patterns.add<TosaFoldConstantGreaterEqual>(ctx, foldSplatOrSingleUseOnly);
1869-
patterns.add<TosaFoldConstantEqual>(ctx, foldSplatOrSingleUseOnly);
1870-
patterns.add<TosaFoldConstantMinimum>(ctx, foldSplatOrSingleUseOnly);
1871-
patterns.add<TosaFoldConstantMaximum>(ctx, foldSplatOrSingleUseOnly);
1872-
patterns.add<TosaFoldConstantPad>(ctx, foldSplatOrSingleUseOnly);
1873-
patterns.add<TosaFoldConstantMatMul>(ctx, foldSplatOrSingleUseOnly);
1962+
patterns.add<TosaFoldConstantFloatCasts>(ctx, options.foldSplatOrSingleUseOnly);
1963+
}
1964+
patterns.add<TosaFoldConstantAdd>(ctx, options.foldSplatOrSingleUseOnly);
1965+
patterns.add<TosaFoldConstantSub>(ctx, options.foldSplatOrSingleUseOnly);
1966+
patterns.add<TosaFoldConstantGreater>(ctx, options.foldSplatOrSingleUseOnly);
1967+
patterns.add<TosaFoldConstantBitwiseNot>(ctx, options.foldSplatOrSingleUseOnly);
1968+
patterns.add<TosaFoldConstantFloor>(ctx, options.foldSplatOrSingleUseOnly);
1969+
patterns.add<TosaFoldConstantCeil>(ctx, options.foldSplatOrSingleUseOnly);
1970+
patterns.add<TosaFoldConstantErf>(ctx, options.foldSplatOrSingleUseOnly);
1971+
patterns.add<TosaFoldConstantExp>(ctx, options.foldSplatOrSingleUseOnly);
1972+
patterns.add<TosaFoldConstantLog>(ctx, options.foldSplatOrSingleUseOnly);
1973+
patterns.add<TosaFoldConstantCos>(ctx, options.foldSplatOrSingleUseOnly);
1974+
patterns.add<TosaFoldConstantSin>(ctx, options.foldSplatOrSingleUseOnly);
1975+
patterns.add<TosaFoldConstantBitwiseAnd>(ctx, options.foldSplatOrSingleUseOnly);
1976+
patterns.add<TosaFoldConstantBitwiseOr>(ctx, options.foldSplatOrSingleUseOnly);
1977+
patterns.add<TosaFoldConstantGreaterEqual>(ctx, options.foldSplatOrSingleUseOnly);
1978+
patterns.add<TosaFoldConstantEqual>(ctx, options.foldSplatOrSingleUseOnly);
1979+
patterns.add<TosaFoldConstantMinimum>(ctx, options.foldSplatOrSingleUseOnly);
1980+
patterns.add<TosaFoldConstantMaximum>(ctx, options.foldSplatOrSingleUseOnly);
1981+
patterns.add<TosaFoldConstantPad>(ctx, options.foldSplatOrSingleUseOnly);
1982+
patterns.add<TosaFoldConstantMatMul>(ctx, options.foldSplatOrSingleUseOnly);
1983+
if (options.enableTileFolding)
1984+
patterns.add<TosaFoldConstantTile>(ctx, options.foldSplatOrSingleUseOnly);
18741985
}
18751986

18761987
void mlir::tosa::populateTosaConstantReduction(MLIRContext *ctx,

mlir/lib/Dialect/Tosa/Transforms/TosaLayerwiseConstantFoldPass.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,13 @@ struct TosaLayerwiseConstantFoldPass
5252
RewritePatternSet patterns(ctx);
5353
auto func = getOperation();
5454

55-
mlir::tosa::populateTosaFoldConstantPatterns(
56-
ctx, patterns, foldSplatOrSingleUseOnly, enableIntCastFolding);
55+
TosaLayerwiseConstantFoldPassOptions options;
56+
options.enableIntCastFolding = enableIntCastFolding;
57+
options.foldSplatOrSingleUseOnly = foldSplatOrSingleUseOnly;
58+
options.aggressiveReduceConstant = aggressiveReduceConstant;
59+
options.enableTileFolding = enableTileFolding;
60+
61+
mlir::tosa::populateTosaFoldConstantPatterns(ctx, patterns, options);
5762
mlir::tosa::populateTosaConstantReduction(ctx, patterns,
5863
aggressiveReduceConstant);
5964
populateTosaOpsCanonicalizationPatterns(ctx, patterns);
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// RUN: mlir-opt --split-input-file --tosa-layerwise-constant-fold=enable-tile-folding=true %s | FileCheck %s
2+
// RUN: mlir-opt --split-input-file --tosa-layerwise-constant-fold %s | FileCheck --check-prefix=NO-FOLDING-CHECK %s
3+
4+
// CHECK-LABEL: @tile_int_one_dim
5+
func.func @tile_int_one_dim() -> (tensor<6xi32>) {
6+
// CHECK: "tosa.const"() <{value = dense
7+
// CHECK-SAME: {{\[}}1, 2, 3, 1, 2, 3]
8+
%0 = "tosa.const"() {value = dense<[1, 2, 3]> : tensor<3xi32>} : () -> tensor<3xi32>
9+
%1 = tosa.tile %0 {multiples = array<i64: 2>} : (tensor<3xi32>) -> tensor<6xi32>
10+
return %1 : tensor<6xi32>
11+
// NO-FOLDING-CHECK: tosa.tile
12+
}
13+
14+
// CHECK-LABEL: @tile_bool
15+
func.func @tile_bool() -> (tensor<1x3x2x3xi1>) {
16+
// CHECK: "tosa.const"() <{value = dense
17+
// CHECK-SAME: {{\[\[}}{{\[\[}}true, true, true],
18+
// CHECK-SAME: [true, true, true]],
19+
// CHECK-SAME: [false, false, false],
20+
// CHECK-SAME: [false, false, false]],
21+
// CHECK-SAME: [true, true, true],
22+
// CHECK-SAME: [true, true, true]]]]
23+
%0 = "tosa.const"() {value = dense<[[[[true]], [[false]], [[true]]]]> : tensor<1x3x1x1xi1>} : () -> tensor<1x3x1x1xi1>
24+
%1 = tosa.tile %0 {multiples = array<i64: 1, 1, 2, 3>} : (tensor<1x3x1x1xi1>) -> tensor<1x3x2x3xi1>
25+
return %1 : tensor<1x3x2x3xi1>
26+
// NO-FOLDING-CHECK: tosa.tile
27+
}
28+
29+
// CHECK-LABEL: @tile_bf16
30+
func.func @tile_bf16() -> (tensor<1x3x2x2xbf16>) {
31+
// CHECK: "tosa.const"() <{value = dense
32+
// CHECK-SAME: {{\[\[}}{{\[\[}}2.500000e-01, 1.250000e-01],
33+
// CHECK-SAME: [2.500000e-01, 1.250000e-01]],
34+
// CHECK-SAME: [5.000000e-01, 1.000000e+00],
35+
// CHECK-SAME: [5.000000e-01, 1.000000e+00]],
36+
// CHECK-SAME: [2.000000e+00, 4.000000e+00],
37+
// CHECK-SAME: [2.000000e+00, 4.000000e+00]]]]
38+
%0 = "tosa.const"() {value = dense<[[[[0.25, 0.125]], [[0.5, 1.0]], [[2.0, 4.0]]]]> : tensor<1x3x1x2xbf16>} : () -> tensor<1x3x1x2xbf16>
39+
%1 = tosa.tile %0 {multiples = array<i64: 1, 1, 2, 1>} : (tensor<1x3x1x2xbf16>) -> tensor<1x3x2x2xbf16>
40+
return %1 : tensor<1x3x2x2xbf16>
41+
// NO-FOLDING-CHECK: tosa.tile
42+
}
43+
44+
// CHECK-LABEL: @tile_f32
45+
func.func @tile_f32() -> (tensor<4x4xf32>) {
46+
// CHECK: "tosa.const"() <{value = dense
47+
// CHECK-SAME: {{\[\[}}2.500000e-01, 1.250000e+00, 2.500000e-01, 1.250000e+00],
48+
// CHECK-SAME: [2.250000e+00, 3.250000e+00, 2.250000e+00, 3.250000e+00],
49+
// CHECK-SAME: [2.500000e-01, 1.250000e+00, 2.500000e-01, 1.250000e+00],
50+
// CHECK-SAME: [2.250000e+00, 3.250000e+00, 2.250000e+00, 3.250000e+00]]
51+
%0 = "tosa.const"() {value = dense<[[0.25, 1.25],[2.25, 3.25]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32>
52+
%1 = tosa.tile %0 {multiples = array<i64: 2, 2>} : (tensor<2x2xf32>) -> tensor<4x4xf32>
53+
return %1 : tensor<4x4xf32>
54+
// NO-FOLDING-CHECK: tosa.tile
55+
}
56+
57+
// CHECK-LABEL: @tile_int_many_dimensions
58+
func.func @tile_int_many_dimensions() -> (tensor<4x6x4xi32>) {
59+
// CHECK: "tosa.const"() <{value = dense
60+
// CHECK-SAME: {{\[\[\[}}1, 2, 1, 2],
61+
// CHECK-SAME: [3, 4, 3, 4],
62+
// CHECK-SAME: [5, 6, 5, 6],
63+
// CHECK-SAME: [1, 2, 1, 2],
64+
// CHECK-SAME: [3, 4, 3, 4],
65+
// CHECK-SAME: [5, 6, 5, 6]],
66+
// CHECK-SAME: {{\[\[}}7, 8, 7, 8],
67+
// CHECK-SAME: [9, 10, 9, 10],
68+
// CHECK-SAME: [11, 12, 11, 12],
69+
// CHECK-SAME: [7, 8, 7, 8],
70+
// CHECK-SAME: [9, 10, 9, 10],
71+
// CHECK-SAME: [11, 12, 11, 12]],
72+
// CHECK-SAME: {{\[\[}}1, 2, 1, 2],
73+
// CHECK-SAME: [3, 4, 3, 4],
74+
// CHECK-SAME: [5, 6, 5, 6],
75+
// CHECK-SAME: [1, 2, 1, 2],
76+
// CHECK-SAME: [3, 4, 3, 4],
77+
// CHECK-SAME: [5, 6, 5, 6]],
78+
// CHECK-SAME: {{\[\[}}7, 8, 7, 8],
79+
// CHECK-SAME: [9, 10, 9, 10],
80+
// CHECK-SAME: [11, 12, 11, 12],
81+
// CHECK-SAME: [7, 8, 7, 8],
82+
// CHECK-SAME: [9, 10, 9, 10],
83+
// CHECK-SAME: [11, 12, 11, 12]]]
84+
%0 = "tosa.const"() {value = dense<[[[1, 2],[3, 4],[5, 6]], [[7, 8],[9, 10],[11, 12]]]> : tensor<2x3x2xi32>} : () -> tensor<2x3x2xi32>
85+
%1 = tosa.tile %0 {multiples = array<i64: 2, 2, 2>} : (tensor<2x3x2xi32>) -> tensor<4x6x4xi32>
86+
// NO-FOLDING-CHECK: tosa.tile
87+
return %1 : tensor<4x6x4xi32>
88+
}
89+
90+
// CHECK-LABEL: @tile_f16_many_dimensions
91+
func.func @tile_f16_many_dimensions() -> (tensor<6x2x2xf16>) {
92+
// CHECK: "tosa.const"() <{value = dense
93+
// CHECK-SAME: {{\[\[\[}}1.000000e+00, 1.000000e+00],
94+
// CHECK-SAME: [1.000000e+00, 1.000000e+00]],
95+
// CHECK-SAME: {{\[\[}}2.000000e+00, 2.000000e+00],
96+
// CHECK-SAME: [2.000000e+00, 2.000000e+00]],
97+
// CHECK-SAME: {{\[\[}}3.000000e+00, 3.000000e+00],
98+
// CHECK-SAME: [3.000000e+00, 3.000000e+00]],
99+
// CHECK-SAME: {{\[\[}}1.000000e+00, 1.000000e+00],
100+
// CHECK-SAME: [1.000000e+00, 1.000000e+00]],
101+
// CHECK-SAME: {{\[\[}}2.000000e+00, 2.000000e+00],
102+
// CHECK-SAME: [2.000000e+00, 2.000000e+00]],
103+
// CHECK-SAME: {{\[\[}}3.000000e+00, 3.000000e+00],
104+
// CHECK-SAME: [3.000000e+00, 3.000000e+00]]]
105+
%0 = "tosa.const"() {value = dense<[[[1.0]], [[2.0]], [[3.0]]]> : tensor<3x1x1xf16>} : () -> tensor<3x1x1xf16>
106+
%1 = tosa.tile %0 {multiples = array<i64: 3, 2, 1>} : (tensor<3x1x1xf16>) -> tensor<6x2x2xf16>
107+
// NO-FOLDING-CHECK: tosa.tile
108+
return %1 : tensor<6x2x2xf16>
109+
}

0 commit comments

Comments
 (0)