Skip to content

Commit a87db48

Browse files
committed
[mlir] Support partial folding of affine.min/max
Originally, these operations were folded only if all expressions in their affine maps could be folded to a constant expression that can be then subject to numeric min/max computation. This introduces a more advanced version that partially folds the affine map by lifting individual constant expression in it even if some of the expressions remain variable. The folding can update the operation in place to use a simpler map. Note that this is not as powerful as canonicalization, in particular this does not remove dimensions or symbols that became useless. This allows for better composition of Linalg tiling and promotion transformation, where the latter can handle some canonical forms of affine.min that the folding can now produce. Differential Revision: https://reviews.llvm.org/D79502
1 parent 717bef6 commit a87db48

File tree

6 files changed

+104
-69
lines changed

6 files changed

+104
-69
lines changed

mlir/include/mlir/IR/AffineMap.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ class AffineMap {
144144
LogicalResult constantFold(ArrayRef<Attribute> operandConstants,
145145
SmallVectorImpl<Attribute> &results) const;
146146

147+
/// Propagates the constant operands into this affine map. Operands are
148+
/// allowed to be null, at which point they are treated as non-constant. This
149+
/// does not change the number of symbols and dimensions. Returns a new map,
150+
/// which may be equal to the old map if no folding happened. If `results` is
151+
/// provided and if all expressions in the map were folded to constants,
152+
/// `results` will contain the values of these constants.
153+
AffineMap
154+
partialConstantFold(ArrayRef<Attribute> operandConstants,
155+
SmallVectorImpl<int64_t> *results = nullptr) const;
156+
147157
/// Returns the AffineMap resulting from composing `this` with `map`.
148158
/// The resulting AffineMap has as many AffineDimExpr as `map` and as many
149159
/// AffineSymbolExpr as the concatenation of `this` and `map` (in which case

mlir/lib/Dialect/Affine/IR/AffineOps.cpp

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,6 +2089,38 @@ static ParseResult parseAffineMinMaxOp(OpAsmParser &parser,
20892089
parser.addTypeToList(indexType, result.types));
20902090
}
20912091

2092+
/// Fold an affine min or max operation with the given operands. The operand
2093+
/// list may contain nulls, which are interpreted as the operand not being a
2094+
/// constant.
2095+
template <typename T>
2096+
OpFoldResult foldMinMaxOp(T op, ArrayRef<Attribute> operands) {
2097+
static_assert(llvm::is_one_of<T, AffineMinOp, AffineMaxOp>::value,
2098+
"expected affine min or max op");
2099+
2100+
// Fold the affine map.
2101+
// TODO(andydavis, ntv) Fold more cases:
2102+
// min(some_affine, some_affine + constant, ...), etc.
2103+
SmallVector<int64_t, 2> results;
2104+
auto foldedMap = op.map().partialConstantFold(operands, &results);
2105+
2106+
// If some of the map results are not constant, try changing the map in-place.
2107+
if (results.empty()) {
2108+
// If the map is the same, report that folding did not happen.
2109+
if (foldedMap == op.map())
2110+
return {};
2111+
op.setAttr("map", AffineMapAttr::get(foldedMap));
2112+
return op.getResult();
2113+
}
2114+
2115+
// Otherwise, completely fold the op into a constant.
2116+
auto resultIt = std::is_same<T, AffineMinOp>::value
2117+
? std::min_element(results.begin(), results.end())
2118+
: std::max_element(results.begin(), results.end());
2119+
if (resultIt == results.end())
2120+
return {};
2121+
return IntegerAttr::get(IndexType::get(op.getContext()), *resultIt);
2122+
}
2123+
20922124
//===----------------------------------------------------------------------===//
20932125
// AffineMinOp
20942126
//===----------------------------------------------------------------------===//
@@ -2097,26 +2129,7 @@ static ParseResult parseAffineMinMaxOp(OpAsmParser &parser,
20972129
//
20982130

20992131
OpFoldResult AffineMinOp::fold(ArrayRef<Attribute> operands) {
2100-
// Fold the affine map.
2101-
// TODO(andydavis, ntv) Fold more cases: partial static information,
2102-
// min(some_affine, some_affine + constant, ...).
2103-
SmallVector<Attribute, 2> results;
2104-
if (failed(map().constantFold(operands, results)))
2105-
return {};
2106-
2107-
// Compute and return min of folded map results.
2108-
int64_t min = std::numeric_limits<int64_t>::max();
2109-
int minIndex = -1;
2110-
for (unsigned i = 0, e = results.size(); i < e; ++i) {
2111-
auto intAttr = results[i].cast<IntegerAttr>();
2112-
if (intAttr.getInt() < min) {
2113-
min = intAttr.getInt();
2114-
minIndex = i;
2115-
}
2116-
}
2117-
if (minIndex < 0)
2118-
return {};
2119-
return results[minIndex];
2132+
return foldMinMaxOp(*this, operands);
21202133
}
21212134

21222135
void AffineMinOp::getCanonicalizationPatterns(
@@ -2132,26 +2145,7 @@ void AffineMinOp::getCanonicalizationPatterns(
21322145
//
21332146

21342147
OpFoldResult AffineMaxOp::fold(ArrayRef<Attribute> operands) {
2135-
// Fold the affine map.
2136-
// TODO(andydavis, ntv, ouhang) Fold more cases: partial static information,
2137-
// max(some_affine, some_affine + constant, ...).
2138-
SmallVector<Attribute, 2> results;
2139-
if (failed(map().constantFold(operands, results)))
2140-
return {};
2141-
2142-
// Compute and return max of folded map results.
2143-
int64_t max = std::numeric_limits<int64_t>::min();
2144-
int maxIndex = -1;
2145-
for (unsigned i = 0, e = results.size(); i < e; ++i) {
2146-
auto intAttr = results[i].cast<IntegerAttr>();
2147-
if (intAttr.getInt() > max) {
2148-
max = intAttr.getInt();
2149-
maxIndex = i;
2150-
}
2151-
}
2152-
if (maxIndex < 0)
2153-
return {};
2154-
return results[maxIndex];
2148+
return foldMinMaxOp(*this, operands);
21552149
}
21562150

21572151
void AffineMaxOp::getCanonicalizationPatterns(

mlir/lib/IR/AffineMap.cpp

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,22 +234,51 @@ AffineExpr AffineMap::getResult(unsigned idx) const {
234234
LogicalResult
235235
AffineMap::constantFold(ArrayRef<Attribute> operandConstants,
236236
SmallVectorImpl<Attribute> &results) const {
237+
// Attempt partial folding.
238+
SmallVector<int64_t, 2> integers;
239+
partialConstantFold(operandConstants, &integers);
240+
241+
// If all expressions folded to a constant, populate results with attributes
242+
// containing those constants.
243+
if (integers.empty())
244+
return failure();
245+
246+
auto range = llvm::map_range(integers, [this](int64_t i) {
247+
return IntegerAttr::get(IndexType::get(getContext()), i);
248+
});
249+
results.append(range.begin(), range.end());
250+
return success();
251+
}
252+
253+
AffineMap
254+
AffineMap::partialConstantFold(ArrayRef<Attribute> operandConstants,
255+
SmallVectorImpl<int64_t> *results) const {
237256
assert(getNumInputs() == operandConstants.size());
238257

239258
// Fold each of the result expressions.
240259
AffineExprConstantFolder exprFolder(getNumDims(), operandConstants);
241-
// Constant fold each AffineExpr in AffineMap and add to 'results'.
260+
SmallVector<AffineExpr, 4> exprs;
261+
exprs.reserve(getNumResults());
262+
242263
for (auto expr : getResults()) {
243264
auto folded = exprFolder.constantFold(expr);
244-
// If we didn't fold to a constant, then folding fails.
245-
if (!folded)
246-
return failure();
247-
248-
results.push_back(folded);
265+
// If did not fold to a constant, keep the original expression, and clear
266+
// the integer results vector.
267+
if (folded) {
268+
exprs.push_back(
269+
getAffineConstantExpr(folded.getInt(), folded.getContext()));
270+
if (results)
271+
results->push_back(folded.getInt());
272+
} else {
273+
exprs.push_back(expr);
274+
if (results) {
275+
results->clear();
276+
results = nullptr;
277+
}
278+
}
249279
}
250-
assert(results.size() == getNumResults() &&
251-
"constant folding produced the wrong number of results");
252-
return success();
280+
281+
return get(getNumDims(), getNumSymbols(), exprs, getContext());
253282
}
254283

255284
/// Walk all of the AffineExpr's in this mapping. Each node in an expression

mlir/test/Dialect/Linalg/tile.mlir

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
// TILE-002-DAG: #[[strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
1414
// TILE-234-DAG: #[[strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
1515

16-
// TILE-2-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (d0, d1 - d2)>
17-
// TILE-02-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (d0, d1 - d2)>
18-
// TILE-002-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (d0, d1 - d2)>
19-
// TILE-234-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (d0, d1 - d2)>
16+
// TILE-2-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (2, d1 - d2)>
17+
// TILE-02-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (2, d1 - d2)>
18+
// TILE-002-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (2, d1 - d2)>
19+
// TILE-234-DAG: #[[bound_map_2:.*]] = affine_map<(d0, d1, d2) -> (2, d1 - d2)>
20+
// TILE-234-DAG: #[[bound_map_3:.*]] = affine_map<(d0, d1, d2) -> (3, d1 - d2)>
21+
// TILE-234-DAG: #[[bound_map_4:.*]] = affine_map<(d0, d1, d2) -> (4, d1 - d2)>
2022

2123
// TILE-2-DAG: #[[strided1D_dynamic:.*]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>
2224
// TILE-02-DAG: #[[strided1D_dynamic:.*]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>
@@ -97,19 +99,19 @@ func @matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: memref<?
9799
// TILE-234: loop.for %[[J:.*]] = %{{.*}}{{.*}} to %[[ubN]] step %{{.*}} {
98100
// TILE-234: loop.for %[[K:.*]] = %{{.*}}{{.*}} to %[[ubK]] step %{{.*}} {
99101
// TILE-234: %[[localM:.*]] = dim %{{.*}}, 0
100-
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map]](%[[C2]], %[[localM]], %[[I]])
102+
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map_2]](%[[C2]], %[[localM]], %[[I]])
101103
// TILE-234: %[[localK:.*]] = dim %{{.*}}, 1
102-
// TILE-234: %[[szK:.*]] = affine.min #[[bound_map]](%[[C4]], %[[localK]], %[[K]])
104+
// TILE-234: %[[szK:.*]] = affine.min #[[bound_map_4]](%[[C4]], %[[localK]], %[[K]])
103105
// TILE-234: %[[sAik:.*]] = subview %{{.*}}[%[[I]], %[[K]]] [%[[szM]], %[[szK]]] [%[[C1]], %[[C1]]] : memref<?x?xf32, #[[strided2D]]> to memref<?x?xf32, #[[strided2D_dynamic]]>
104106
// TILE-234: %[[localK:.*]] = dim %{{.*}}, 0
105-
// TILE-234: %[[szK:.*]] = affine.min #[[bound_map]](%[[C4]], %[[localK]], %[[K]])
107+
// TILE-234: %[[szK:.*]] = affine.min #[[bound_map_4]](%[[C4]], %[[localK]], %[[K]])
106108
// TILE-234: %[[localN:.*]] = dim %{{.*}}, 1
107-
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map]](%[[C3]], %[[localN]], %[[J]])
109+
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map_3]](%[[C3]], %[[localN]], %[[J]])
108110
// TILE-234: %[[sBkj:.*]] = subview %{{.*}}[%[[K]], %[[J]]] [%[[szK]], %[[szN]]] [%[[C1]], %[[C1]]] : memref<?x?xf32, #[[strided2D]]> to memref<?x?xf32, #[[strided2D_dynamic]]>
109111
// TILE-234: %[[localM:.*]] = dim %{{.*}}, 0
110-
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map]](%[[C2]], %[[localM]], %[[I]])
112+
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map_2]](%[[C2]], %[[localM]], %[[I]])
111113
// TILE-234: %[[localN:.*]] = dim %{{.*}}, 1
112-
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map]](%[[C3]], %[[localN]], %[[J]])
114+
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map_3]](%[[C3]], %[[localN]], %[[J]])
113115
// TILE-234: %[[sCij:.*]] = subview %{{.*}}[%[[I]], %[[J]]] [%[[szM]], %[[szN]]] [%[[C1]], %[[C1]]] : memref<?x?xf32, #[[strided2D]]> to memref<?x?xf32, #[[strided2D_dynamic]]>
114116
//
115117
// TILE-234: linalg.matmul(%[[sAik]], %[[sBkj]], %[[sCij]]) : memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?x?xf32, #[[strided2D_dynamic]]>
@@ -230,15 +232,15 @@ func @matvec(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: memref<?
230232
// TILE-234: loop.for %[[I:.*]] = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
231233
// TILE-234: loop.for %[[J:.*]] = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
232234
// TILE-234: %[[localM:.*]] = dim %{{.*}}, 0
233-
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map]](%[[C2]], %[[localM]], %[[I]])
235+
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map_2]](%[[C2]], %[[localM]], %[[I]])
234236
// TILE-234: %[[localN:.*]] = dim %{{.*}}, 1
235-
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map]](%[[C3]], %[[localN]], %[[J]])
237+
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map_3]](%[[C3]], %[[localN]], %[[J]])
236238
// TILE-234: %[[sAij:.*]] = subview %{{.*}}[%[[I]], %[[J]]] [%[[szM]], %[[szN]]] [%[[C1]], %[[C1]]] : memref<?x?xf32, #[[strided2D]]> to memref<?x?xf32, #[[strided2D_dynamic]]>
237239
// TILE-234: %[[localN:.*]] = dim %{{.*}}, 0
238-
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map]](%[[C3]], %[[localN]], %[[J]])
240+
// TILE-234: %[[szN:.*]] = affine.min #[[bound_map_3]](%[[C3]], %[[localN]], %[[J]])
239241
// TILE-234: %[[sBj:.*]] = subview %{{.*}}[%[[J]]] [%[[szN]]] [%[[C1]]] : memref<?xf32, #[[strided1D]]> to memref<?xf32, #[[strided1D_dynamic]]>
240242
// TILE-234: %[[localM:.*]] = dim %{{.*}}, 0
241-
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map]](%[[C2]], %[[localM]], %[[I]])
243+
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map_2]](%[[C2]], %[[localM]], %[[I]])
242244
// TILE-234: %[[sCi:.*]] = subview %{{.*}}[%[[I]]] [%[[szM]]] [%[[C1]]] : memref<?xf32, #[[strided1D]]> to memref<?xf32, #[[strided1D_dynamic]]>
243245
//
244246
// TILE-234: linalg.matvec(%[[sAij]], %[[sBj]], %[[sCi]]) : memref<?x?xf32, #[[strided2D_dynamic]]>, memref<?xf32, #[[strided1D_dynamic]]>, memref<?xf32, #[[strided1D_dynamic]]>
@@ -274,10 +276,10 @@ func @dot(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: memref<?xf32, of
274276
// TILE-234: %[[ubK:.*]] = dim %{{.*}}, 0 : memref<?xf32, #[[strided1D]]>
275277
// TILE-234: loop.for %[[I:.*]] = %{{.*}} to %[[ubK]] step %{{.*}} {
276278
// TILE-234: %[[localM:.*]] = dim %{{.*}}, 0
277-
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map]](%[[C2]], %[[localM]], %[[I]])
279+
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map_2]](%[[C2]], %[[localM]], %[[I]])
278280
// TILE-234: %[[sAi:.*]] = subview %{{.*}}[%[[I]]] [%[[szM]]] [%[[C1]]] : memref<?xf32, #[[strided1D]]> to memref<?xf32, #[[strided1D_dynamic]]>
279281
// TILE-234: %[[localM:.*]] = dim %{{.*}}, 0
280-
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map]](%[[C2]], %[[localM]], %[[I]])
282+
// TILE-234: %[[szM:.*]] = affine.min #[[bound_map_2]](%[[C2]], %[[localM]], %[[I]])
281283
// TILE-234: %[[sBi:.*]] = subview %{{.*}}[%[[I]]] [%[[szM]]] [%[[C1]]] : memref<?xf32, #[[strided1D]]> to memref<?xf32, #[[strided1D_dynamic]]>
282284
// TILE-234: linalg.dot(%[[sAi]], %[[sBi]], %{{.*}}) : memref<?xf32, #[[strided1D_dynamic]]>, memref<?xf32, #[[strided1D_dynamic]]>, memref<f32>
283285

mlir/test/Dialect/Linalg/tile_conv.mlir

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// TILE-23004-DAG: #[[S0x10p90:.*]] = affine_map<()[s0] -> (s0 * 10 + 90)>
55
// TILE-23004-DAG: #[[strided4D:.*]] = affine_map<(d0, d1, d2, d3)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3)>
66
// TILE-23004-DAG: #[[strided4D_dynamic:.*]] = affine_map<(d0, d1, d2, d3)[s0, s1, s2, s3, s4] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3 * s4)>
7-
// TILE-23004-DAG: #[[bound_map:.*]] = affine_map<(d0, d1, d2) -> (d0, d1 - d2)>
7+
// TILE-23004-DAG: #[[bound_map_4:.*]] = affine_map<(d0, d1, d2) -> (4, d1 - d2)>
88

99
func @conv(%arg0: memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>, %arg1: memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>, %arg2: memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>) {
1010
linalg.conv(%arg0, %arg1, %arg2) {dilations = [10, 20], strides = [30, 40]} : memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>, memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>, memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>
@@ -27,15 +27,15 @@ func @conv(%arg0: memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>, %arg1:
2727
// TILE-23004: %[[Z0:.*]] = dim %{{.*}}, 0 : memref<?x?x?x?xf32, #[[strided4D]]>
2828
// TILE-23004: %[[Z1:.*]] = dim %{{.*}}, 1 : memref<?x?x?x?xf32, #[[strided4D]]>
2929
// TILE-23004: %[[Z2:.*]] = dim %{{.*}}, 2 : memref<?x?x?x?xf32, #[[strided4D]]>
30-
// TILE-23004: %[[szK:.*]] = affine.min #[[bound_map]](%[[C4]], %[[Z2]], %[[ivK]])
30+
// TILE-23004: %[[szK:.*]] = affine.min #[[bound_map_4]](%[[C4]], %[[Z2]], %[[ivK]])
3131
// TILE-23004: %[[K:.*]] = dim %{{.*}}, 3 : memref<?x?x?x?xf32, #[[strided4D]]>
3232
// TILE-23004: %[[FilterView:.*]] = subview %{{.*}}[%[[C0]], %[[C0]], %[[ivK]], %[[C0]]] [%[[Z0]], %[[Z1]], %[[szK]], %[[K]]] [%[[C1]], %[[C1]], %[[C1]], %[[C1]]] : memref<?x?x?x?xf32, #[[strided4D]]> to memref<?x?x?x?xf32, #[[strided4D_dynamic]]>
3333
//
3434
// TILE-23004: %[[J1:.*]] = affine.apply #[[D0x30pS0x10]](%[[ivJ]])
3535
// T__ILE-23004: %[[I1pStep:.*]] = affine.apply #[[S0x10p90]]()[%[[I1]]]
3636
// TILE-23004: %[[SZ2:.*]] = dim %{{.*}}, 2 : memref<?x?x?x?xf32, #[[strided4D]]>
3737
// TILE-23004: %[[dim3:.*]] = dim %{{.*}}, 3
38-
// TILE-23004: %[[sz3:.*]] = affine.min #[[bound_map]](%[[C4]], %[[dim3]], %[[ivK]]
38+
// TILE-23004: %[[sz3:.*]] = affine.min #[[bound_map_4]](%[[C4]], %[[dim3]], %[[ivK]]
3939
// TILE-23004: %[[InputView:.*]] = subview %{{.*}}[%[[ivI]], %[[J1]], %[[C0]], %[[ivK]]] [%{{.*}}, %{{.*}}, %[[SZ2]], %[[sz3]]] [%[[C1]], %[[C1]], %[[C1]], %[[C1]]] : memref<?x?x?x?xf32, #[[strided4D]]> to memref<?x?x?x?xf32, #[[strided4D_dynamic]]>
4040
//
4141
// TILE-23004: %[[X0:.*]] = dim %{{.*}}, 2 : memref<?x?x?x?xf32, #[[strided4D]]>

mlir/test/Dialect/Linalg/tile_conv_padding.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// TILE-23004-DAG: #[[strided4D:.*]] = affine_map<(d0, d1, d2, d3)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3)>
55
// TILE-20000-DAG: #[[strided4D:.*]] = affine_map<(d0, d1, d2, d3)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3)>
6-
// TILE-20000-DAG: #[[minmap:.*]] = affine_map<(d0, d1, d2) -> (d0, d1 - d2)>
6+
// TILE-20000-DAG: #[[minmap:.*]] = affine_map<(d0, d1, d2) -> (2, d1 - d2)>
77
// TILE-20000-DAG: #[[subviewstride:.*]] = affine_map<(d0, d1, d2, d3)[s0, s1, s2, s3, s4] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3 * s4)>
88

99
func @conv_padding(%arg0: memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>, %arg1: memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>, %arg2: memref<?x?x?x?xf32, offset: ?, strides: [?, ?, ?, 1]>) {

0 commit comments

Comments
 (0)