diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td @@ -503,9 +503,7 @@ OptionalAttr:$doc, OptionalAttr:$library_call, // ArrayAttr of StrArrayAttr: - OptionalAttr:$sparse, - Confined, [IntMinValue<0>]> - :$symbol_source); + OptionalAttr:$sparse); let results = (outs Variadic:$result_tensors); let regions = (region AnyRegion:$region); let extraClassDeclaration = [{ @@ -513,18 +511,13 @@ return SmallVector{ getDocAttrName(), getIndexingMapsAttrName(), getLibraryCallAttrName(), - getIteratorTypesAttrName(), getSymbolSourceAttrName() + getIteratorTypesAttrName(), }; } std::string getLibraryCallName() { return library_call().hasValue() ? library_call()->str() : "op_has_no_registered_library_name"; } - llvm::Optional getSymbolSource() { - auto ss = symbol_source(); - return ss.hasValue() ? - llvm::Optional(ss.getValue()) : llvm::None; - } static std::function getRegionBuilder() { return nullptr; @@ -566,10 +559,6 @@ parallel, reduction, window - sparse: an optional list with per-dimension sparsity annotations (either "D" for dense or "S" for sparse) for each input and output view. - - symbol_source: index of the operand whose dimensions will be propagated - as symbols to the indexing maps. When specified the number of symbols - in each of the indexing maps has to be either 0 or the rank of the - specified operand. Example: Defining a #matmul_trait attribute in MLIR can be done as follows: @@ -646,50 +635,17 @@ Tensor values must be legalized by a buffer allocation pass before most transformations can be applied. Such legalizations move tensor return values into output buffer operands and updates the region arguments accordingly. - - The `symbol_source` attribute allows selecting a particular operand and - introducing symbols for each operand dimension. Such symbols can then be - used in the indexing maps. - - Example of 1D convolution with symbols: - ```mlir - #conv_1d_accesses = [ - affine_map<(m, n)[dimN] -> (m + n - dimN floordiv 2)>, // in - affine_map<(m, n)[dimN] -> (n)>, // filter - affine_map<(m, n)[dimN] -> (m)> // out - ] - - #conv_1d_trait = { - doc = "O(m) += I(m + n - size(n) floordiv 2) * K(n)", - indexing_maps = #conv_1d_accesses, - library_call = "linalg_conv_1d", - iterator_types = ["parallel", "parallel"], - symbol_source = 1 - } - - linalg.generic #conv_1d_trait - ins(%in, %filter : memref, memref) - outs(%out : memref) { - ^bb0(%a: f32, %b: f32, %c: f32) : - %d = mulf %a, %b : f32 - %e = addf %c, %d : f32 - linalg.yield %e : f32 - } - ``` - where symbol s0 will be substituted with `dim %filter, %c0` i.e. the first - and only dimension of the second operand as specified by the symbol_source - attribute. }]; let builders = [ OpBuilderDAG<(ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, "ValueRange":$outputBuffers, "ValueRange":$initTensors, "ArrayRef":$indexingMaps, "ArrayRef":$iteratorTypes, - "StringRef":$doc, "StringRef":$libraryCall, "IntegerAttr":$symbolSource, + "StringRef":$doc, "StringRef":$libraryCall, CArg<"function_ref", "nullptr">)>, OpBuilderDAG<(ins "ValueRange":$inputs, "ValueRange":$outputBuffers, "ArrayRef":$indexingMaps, "ArrayRef":$iteratorTypes, - "StringRef":$doc, "StringRef":$libraryCall, "IntegerAttr":$symbolSource, + "StringRef":$doc, "StringRef":$libraryCall, CArg<"function_ref", "nullptr">)>, OpBuilderDAG<(ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, "ValueRange":$outputBuffers, "ValueRange":$initTensors, @@ -819,51 +775,18 @@ Tensor values must be legalized by a buffer allocation pass before most transformations can be applied. Such legalizations move tensor return values into output buffer operands and update the region arguments accordingly. - - The `symbol_source` attribute allows selecting a particular operand and - introducing symbols for each operand dimension. Such symbols can then be - used in the indexing maps. - - Example of 1D convolution with symbols: - ```mlir - #conv_1d_accesses = [ - affine_map<(m, n)[dimN] -> (m + n - dimN floordiv 2)>, // in - affine_map<(m, n)[dimN] -> (n)>, // filter - affine_map<(m, n)[dimN] -> (m)> // out - ] - - #conv_1d_trait = { - doc = "O(m) += I(m + n - size(n) floordiv 2) * K(n)", - indexing_maps = #conv_1d_accesses, - library_call = "linalg_conv_1d", - iterator_types = ["parallel", "parallel"], - symbol_source = 1 - } - - linalg.generic #conv_1d_trait - ins(%in, %filter : memref, memref) - outs(%out : memref) { - ^bb0(%a: f32, %b: f32, %c: f32) : - %d = mulf %a, %b : f32 - %e = addf %c, %d : f32 - linalg.yield %e : f32 - } - ``` - where symbol s0 will be substituted with `dim %filter, %c0` i.e. the first - and only dimension of the second operand as specified by the symbol_source - attribute. }]; let builders = [ OpBuilderDAG<(ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, "ValueRange":$outputBuffers, "ValueRange":$initTensors, "ArrayRef":$indexingMaps, "ArrayRef":$iteratorTypes, - "StringRef":$doc, "StringRef":$libraryCall, "IntegerAttr":$symbolSource, + "StringRef":$doc, "StringRef":$libraryCall, CArg<"function_ref", "nullptr">)>, OpBuilderDAG<(ins "ValueRange":$inputs, "ValueRange":$outputBuffers, "ArrayRef":$indexingMaps, "ArrayRef":$iteratorTypes, - "StringRef":$doc, "StringRef":$libraryCall, "IntegerAttr":$symbolSource, + "StringRef":$doc, "StringRef":$libraryCall, CArg<"function_ref", "nullptr">)>, OpBuilderDAG<(ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, diff --git a/mlir/include/mlir/Dialect/Linalg/Passes.td b/mlir/include/mlir/Dialect/Linalg/Passes.td --- a/mlir/include/mlir/Dialect/Linalg/Passes.td +++ b/mlir/include/mlir/Dialect/Linalg/Passes.td @@ -64,7 +64,7 @@ def LinalgBufferize : Pass<"linalg-bufferize", "FuncOp"> { let summary = "Bufferize the linalg dialect"; let constructor = "mlir::createLinalgBufferizePass()"; - let dependentDialects = ["linalg::LinalgDialect"]; + let dependentDialects = ["linalg::LinalgDialect", "AffineDialect"]; } def LinalgLowerToParallelLoops diff --git a/mlir/include/mlir/Dialect/Utils/StructuredOpsUtils.h b/mlir/include/mlir/Dialect/Utils/StructuredOpsUtils.h --- a/mlir/include/mlir/Dialect/Utils/StructuredOpsUtils.h +++ b/mlir/include/mlir/Dialect/Utils/StructuredOpsUtils.h @@ -46,10 +46,6 @@ return indexingMaps == maps; } -/// Attribute name for the IntegerAttr which encodes the index of operand -/// whose dimensions will be propagated as symbols to the indexing maps -constexpr StringRef getSymbolSourceAttrName() { return "symbol_source"; } - /// Attribute name for the AffineArrayAttr which encodes the relationship /// between a structured op iterators' and its operands. constexpr StringRef getIndexingMapsAttrName() { return "indexing_maps"; } diff --git a/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp b/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp --- a/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp +++ b/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp @@ -69,8 +69,7 @@ builder.getStrArrayAttr(iteratorStrTypes), StringAttr() /*doc*/, StringAttr() /*library_call*/, - ArrayAttr() /*sparse*/, - IntegerAttr() /*symbol_source*/ + ArrayAttr() /*sparse*/ /* TODO: other attributes in op */ ) .getOperation(); diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp --- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp @@ -60,42 +60,17 @@ SmallVector LinalgOp::createFlatListOfOperandDims(OpBuilder &b, Location loc) { SmallVector res; - SmallVector ranks; for (Value v : getShapedOperands()) { ShapedType t = v.getType().template cast(); - ranks.push_back(t.getRank()); - for (unsigned i = 0; i < t.getRank(); ++i) + for (unsigned i = 0, e = t.getRank(); i < e; ++i) res.push_back(b.create(loc, v, i)); } - - // TODO: drop the following once symbol_source is deleted. - auto attr = getAttrOfType("symbol_source"); - if (!attr) - return res; - - // Find the correct position for inserting values for symbols. - unsigned numSymb = ranks[attr.getInt()], symbolsPos = 0; - for (unsigned idx = 0, e = attr.getInt(); idx < e; idx++) - symbolsPos += ranks[idx]; - - // Append the end of the value list that corresponds to the - // values mapping to symbols. Since inside concatenated map symbols - // are repeated we have to repeat the sizes as well. - - // Reserve is mandatory to avoid a potential undefined behavior with - // pushing back to smallvector from itself. - res.reserve(res.size() + ranks.size() * numSymb); - for (unsigned idx = 0, s = ranks.size(); idx < s; ++idx) - for (unsigned idx2 = 0; idx2 < numSymb; ++idx2) - res.push_back(res[symbolsPos + idx2]); return res; } SmallVector LinalgOp::createLoopRanges(OpBuilder &b, Location loc) { AffineMap map = getLoopsToShapesMap(); unsigned numDims = map.getNumDims(), numRes = map.getNumResults(); - // TODO: drop numSym once symbol_source is deleted. - unsigned numSym = map.getNumSymbols(); auto viewSizes = createFlatListOfOperandDims(b, loc); SmallVector res(numDims); Value zeroVal = b.create(loc, 0); @@ -107,51 +82,6 @@ continue; res[d.getPosition()] = Range{zeroVal, viewSizes[idx], oneVal}; } - - // TODO: drop the following once symbol_source is deleted. - // If the access pattern is of form (m, n)[s] -> (m + n - s floordiv 2), - // then the bounds are: - // (s floordiv 2) <= m <= (size(m) + s floordiv 2 - s + 1). - // where size(n) is applied to the symbol s. - // This is done statically now. - if (auto binOp = result.dyn_cast()) { - auto lhs = binOp.getLHS().dyn_cast(); - auto rhs = binOp.getRHS().dyn_cast(); - if (!lhs || !rhs || binOp.getKind() != AffineExprKind::Add || - lhs.getKind() != AffineExprKind::Add || - rhs.getKind() != mlir::AffineExprKind::Mul) - continue; - - auto m = lhs.getLHS().dyn_cast(); - auto n = lhs.getRHS().dyn_cast(); - auto fDiv = rhs.getLHS().dyn_cast(); - auto minusOne = rhs.getRHS().dyn_cast(); - if (!m || !n || !fDiv || !minusOne || - fDiv.getKind() != AffineExprKind::FloorDiv || - !fDiv.getLHS().isa() || - !fDiv.getRHS().isa()) - continue; - - auto s = fDiv.getLHS().dyn_cast(); - if (minusOne.getValue() != -1) - continue; - - int mPos = m.getPosition(); - AffineExpr one = getAffineConstantExpr(1, s.getContext()); - AffineExpr sizeOfM = getAffineSymbolExpr(numSym, s.getContext()); - // Construction of upper bound (size(m) + s floordiv 2 - s + 1). - AffineExpr upperOffsetExpr = sizeOfM + fDiv + one - s; - AffineMap fromMap = AffineMap::get(numDims, numSym + 1, fDiv); - AffineMap toMap = AffineMap::get(numDims, numSym + 1, upperOffsetExpr); - SmallVector values(viewSizes.begin(), - viewSizes.begin() + numDims); - values.insert(values.end(), viewSizes.begin() + numRes, viewSizes.end()); - values.push_back(viewSizes[mPos]); - // Construction of the lower bound (s floordiv 2). - Value from = applyMapToValues(b, loc, fromMap, values).front(); - Value to = applyMapToValues(b, loc, toMap, values).front(); - res[mPos] = Range{from, to, oneVal}; - } } return res; } @@ -224,14 +154,14 @@ OpBuilder &builder, OperationState &result, TypeRange resultTensorTypes, ValueRange inputs, ValueRange outputBuffers, ValueRange initTensors, ArrayRef indexingMaps, ArrayRef iteratorTypes, - StringRef doc, StringRef libraryCall, IntegerAttr symbolSource, + StringRef doc, StringRef libraryCall, function_ref bodyBuild) { build(builder, result, resultTensorTypes, inputs, outputBuffers, initTensors, builder.getAffineMapArrayAttr(indexingMaps), builder.getStrArrayAttr(iteratorTypes), doc.empty() ? StringAttr() : builder.getStringAttr(doc), libraryCall.empty() ? StringAttr() : builder.getStringAttr(libraryCall), - ArrayAttr(), symbolSource); + ArrayAttr()); if (!bodyBuild) return; @@ -250,10 +180,9 @@ OpBuilder &builder, OperationState &result, ValueRange inputs, ValueRange outputBuffers, ArrayRef indexingMaps, ArrayRef iteratorTypes, StringRef doc, StringRef libraryCall, - IntegerAttr symbolSource, function_ref bodyBuild) { build(builder, result, TypeRange{}, inputs, outputBuffers, ValueRange{}, - indexingMaps, iteratorTypes, doc, libraryCall, symbolSource, bodyBuild); + indexingMaps, iteratorTypes, doc, libraryCall, bodyBuild); } void GenericOp::build( @@ -263,8 +192,7 @@ function_ref bodyBuild) { build(builder, result, inputs, outputBuffers, indexingMaps, iteratorTypes, /*doc=*/"", - /*libraryCall=*/"", - /*symbolSource=*/IntegerAttr(), bodyBuild); + /*libraryCall=*/"", bodyBuild); } void GenericOp::build( @@ -275,15 +203,13 @@ build(builder, result, resultTensorTypes, inputs, outputBuffers, initTensors, indexingMaps, iteratorTypes, /*doc=*/"", - /*libraryCall=*/"", - /*symbolSource=*/IntegerAttr(), bodyBuild); + /*libraryCall=*/"", bodyBuild); } - void IndexedGenericOp::build( OpBuilder &builder, OperationState &result, TypeRange resultTensorTypes, ValueRange inputs, ValueRange outputBuffers, ValueRange initTensors, ArrayRef indexingMaps, ArrayRef iteratorTypes, - StringRef doc, StringRef libraryCall, IntegerAttr symbolSource, + StringRef doc, StringRef libraryCall, function_ref bodyBuild) { build(builder, result, resultTensorTypes, inputs, outputBuffers, initTensors, @@ -291,7 +217,7 @@ builder.getStrArrayAttr(iteratorTypes), doc.empty() ? StringAttr() : builder.getStringAttr(doc), libraryCall.empty() ? StringAttr() : builder.getStringAttr(libraryCall), - ArrayAttr(), symbolSource); + ArrayAttr()); if (!bodyBuild) return; @@ -313,11 +239,10 @@ OpBuilder &builder, OperationState &result, ValueRange inputs, ValueRange outputBuffers, ArrayRef indexingMaps, ArrayRef iteratorTypes, StringRef doc, StringRef libraryCall, - IntegerAttr symbolSource, function_ref bodyBuild) { build(builder, result, TypeRange{}, inputs, outputBuffers, ValueRange{}, - indexingMaps, iteratorTypes, doc, libraryCall, symbolSource, bodyBuild); + indexingMaps, iteratorTypes, doc, libraryCall, bodyBuild); } void IndexedGenericOp::build( @@ -327,9 +252,7 @@ function_ref bodyBuild) { build(builder, result, inputs, outputBuffers, indexingMaps, iteratorTypes, - /*doc=*/"", - /*libraryCall=*/"", - /*symbolSource=*/IntegerAttr(), bodyBuild); + /*doc=*/"", /*libraryCall=*/"", bodyBuild); } void IndexedGenericOp::build( @@ -341,8 +264,7 @@ build(builder, result, resultTensorTypes, inputs, outputBuffers, initTensors, indexingMaps, iteratorTypes, /*doc=*/"", - /*libraryCall=*/"", - /*symbolSource=*/IntegerAttr(), bodyBuild); + /*libraryCall=*/"", bodyBuild); } template @@ -585,16 +507,6 @@ if (failed(BlockArgsVerifier::verify(op, region.front()))) return failure(); - auto symbolSourceAttr = - op.template getAttrOfType("symbol_source"); - int64_t expectedNumSymbols = 0; - if (symbolSourceAttr) { - unsigned index = symbolSourceAttr.getInt(); - if (index >= op.getNumOperands()) - return op.emitOpError("symbol_source index out of range"); - expectedNumSymbols = op.getShapedType(index).getRank(); - } - if (op.indexing_maps().size() != op.getNumInputsAndOutputs()) return op.emitOpError("expected the number of indexing_map (") << op.indexing_maps().size() @@ -609,9 +521,8 @@ indexingMaps.push_back(m); // Save reference to map for further checks. auto view = op.getShapedType(idx); - if (m.getNumSymbols() != expectedNumSymbols) - return op.emitOpError("expected the number of symbols in indexing_map #") - << idx << " to match rank of operand `symbol_source`"; + if (m.getNumSymbols() != 0) + return op.emitOpError("unexpected symbols in indexing_map #") << idx; if (m.getNumDims() != nLoops) return op.emitOpError("expected indexing_map #") @@ -623,14 +534,7 @@ << idx << " results to match view rank: " << view; } - // TODO: symbol_source prevents us to just write: - // if (!op.getShapeToLoopsMap()) - // return op.emitOpError("expected the shape-to-loops map to be non-null"); - // - // Update when symbol_source is deleted. - auto concatMap = concatAffineMaps(indexingMaps); - // TODO: Bound inference for maps with symbols - if (!concatMap.getNumSymbols() && !inversePermutation(concatMap)) + if (!op.getShapesToLoopsMap()) return op.emitOpError("expected the shape-to-loops map to be non-null"); if (failed(AnnotationsVerifier::verify(op))) diff --git a/mlir/lib/Dialect/Linalg/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Linalg/Transforms/Bufferize.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/Bufferize.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Bufferize.cpp @@ -120,8 +120,7 @@ /*outputBuffers=*/outputs, /*initTensors=*/llvm::None, genericOp.indexing_maps(), genericOp.iterator_types(), genericOp.docAttr(), - genericOp.library_callAttr(), genericOp.sparseAttr(), - genericOp.symbol_sourceAttr()); + genericOp.library_callAttr(), genericOp.sparseAttr()); // Create a new block in the region of the new Generic Op. Block *oldBlock = genericOp.getBody(); @@ -322,7 +321,7 @@ BufferizeTypeConverter typeConverter; // Mark all Standard operations legal. - target.addLegalDialect(); + target.addLegalDialect(); target.addIllegalOp(); // Mark all Linalg operations illegal as long as they work on tensors. diff --git a/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp b/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp @@ -227,8 +227,7 @@ consumer.iterator_types(), /*doc=*/nullptr, /*library_call=*/nullptr, - /*sparse=*/nullptr, - /*symbol_source=*/nullptr) + /*sparse=*/nullptr) .getOperation(); } else { fusedOp = @@ -242,8 +241,7 @@ consumer.iterator_types(), /*doc=*/nullptr, /*library_call=*/nullptr, - /*sparse=*/nullptr, - /*symbol_source=*/nullptr) + /*sparse=*/nullptr) .getOperation(); } @@ -820,8 +818,7 @@ producer.iterator_types(), /*doc=*/nullptr, /*library_call=*/nullptr, - /*sparse=*/nullptr, - /*symbol_source=*/nullptr); + /*sparse=*/nullptr); auto &fusedRegion = fusedOp.getOperation()->getRegion(0); rewriter.cloneRegionBefore(producer.getOperation()->getRegion(0), fusedRegion, fusedRegion.begin()); @@ -904,8 +901,7 @@ linalgOp.iterator_types(), /*doc=*/nullptr, /*library_call=*/nullptr, - /*sparse=*/nullptr, - /*symbol_source=*/nullptr); + /*sparse=*/nullptr); // Map the block argument corresponding to the replaced argument with the // scalar constant. diff --git a/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp b/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp @@ -147,15 +147,7 @@ SmallVector indexedValues; indexedValues.reserve(nInputs + nOutputs); - auto attr = linalgOp.template getAttrOfType("symbol_source"); auto allIvsPlusDims = SmallVector(allIvs.begin(), allIvs.end()); - if (attr) { - auto operand = linalgOp.getOperation()->getOperand(attr.getInt()); - auto shapedType = operand.getType().template cast(); - allIvsPlusDims.reserve(allIvs.size() + shapedType.getRank()); - for (unsigned idx = 0, e = shapedType.getRank(); idx < e; ++idx) - allIvsPlusDims.push_back(b.create(loc, operand, idx)); - } // TODO: Avoid the loads if the corresponding argument of the // region has no uses. diff --git a/mlir/test/Dialect/Linalg/invalid.mlir b/mlir/test/Dialect/Linalg/invalid.mlir --- a/mlir/test/Dialect/Linalg/invalid.mlir +++ b/mlir/test/Dialect/Linalg/invalid.mlir @@ -63,33 +63,6 @@ // ----- -func @generic_symbol_in_map(%arg0: memref) { - // expected-error @+1 {{expected the number of symbols in indexing_map #0 to match rank of operand `symbol_source`}} - linalg.generic { - indexing_maps = [ affine_map<()[N] -> (0)> ], - iterator_types = ["parallel"]} - outs(%arg0 : memref) { - ^bb(%i : i32): - linalg.yield %i : i32 - } -} - -// ----- - -func @generic_symbol_source_out_of_range(%arg0: memref) { - // expected-error @+1 {{symbol_source index out of range}} - linalg.generic { - indexing_maps = [ affine_map<()[N] -> (0)> ], - iterator_types = ["parallel"], - symbol_source = 1} - outs(%arg0 : memref) { - ^bb(%i : i32): - linalg.yield %i : i32 - } -} - -// ----- - func @generic_wrong_dim_in_map(%arg0: memref<1xi32>) { // expected-error @+1 {{op expected indexing_map #0 to have 1 dim(s) to match the number of loops}} linalg.generic { diff --git a/mlir/test/Dialect/Linalg/loops.mlir b/mlir/test/Dialect/Linalg/loops.mlir --- a/mlir/test/Dialect/Linalg/loops.mlir +++ b/mlir/test/Dialect/Linalg/loops.mlir @@ -14,9 +14,6 @@ // CHECKLOOP-DAG: #[[$stride2Dilation1:.*]] = affine_map<(d0, d1) -> (d0 * 2 + d1)> // CHECKLOOP-DAG: #[[$stride2Dilation4:.*]] = affine_map<(d0, d1) -> (d0 * 2 + d1 * 4)> // CHECKLOOP-DAG: #[[$stride3Dilation5:.*]] = affine_map<(d0, d1) -> (d0 * 3 + d1 * 5)> -// CHECKLOOP-DAG: #[[$convLowerBound:.*]] = affine_map<()[s0] -> (s0 floordiv 2)> -// CHECKLOOP-DAG: #[[$convUpperBound:.*]] = affine_map<()[s0, s1] -> (s1 + s0 floordiv 2 - s0 + 1)> -// CHECKLOOP-DAG: #[[$convMap:.*]] = affine_map<(d0, d1)[s0] -> (d0 + d1 - s0 floordiv 2)> // CHECKLOOP-DAG: #[[$stride1Dilation1Padding1:.*]] = affine_map<(d0, d1) -> (d0 + d1 - 1)> // CHECKLOOP-DAG: #[[$stride1Dilation1Padding2:.*]] = affine_map<(d0, d1) -> (d0 + d1 - 2)> @@ -30,9 +27,6 @@ // CHECKPARALLEL-DAG: #[[$stride2Dilation1:.*]] = affine_map<(d0, d1) -> (d0 * 2 + d1)> // CHECKPARALLEL-DAG: #[[$stride2Dilation4:.*]] = affine_map<(d0, d1) -> (d0 * 2 + d1 * 4)> // CHECKPARALLEL-DAG: #[[$stride3Dilation5:.*]] = affine_map<(d0, d1) -> (d0 * 3 + d1 * 5)> -// CHECKPARALLEL-DAG: #[[$convLowerBound:.*]] = affine_map<()[s0] -> (s0 floordiv 2)> -// CHECKPARALLEL-DAG: #[[$convUpperBound:.*]] = affine_map<()[s0, s1] -> (s1 + s0 floordiv 2 - s0 + 1)> -// CHECKPARALLEL-DAG: #[[$convMap:.*]] = affine_map<(d0, d1)[s0] -> (d0 + d1 - s0 floordiv 2)> // CHECKPARALLEL-DAG: #[[$stride1Dilation1Padding1:.*]] = affine_map<(d0, d1) -> (d0 + d1 - 1)> // CHECKPARALLEL-DAG: #[[$stride1Dilation1Padding2:.*]] = affine_map<(d0, d1) -> (d0 + d1 - 2)> @@ -1225,373 +1219,6 @@ // CHECKPARALLEL: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 // CHECKPARALLEL: store %[[res]], %[[mC]][%[[b]], %[[m]], %[[n]]] : memref -#conv_1d_accesses = [ - affine_map<(m, n)[s0] -> (m + n - s0 floordiv 2)>, // in - affine_map<(m, n)[s0] -> (n)>, // filter - affine_map<(m, n)[s0] -> (m)> // out -] - -#conv_1d_trait = { - args_in = 2, - args_out = 1, - doc = "C(m) += A(m) * B(n)", - indexing_maps = #conv_1d_accesses, - library_call = "linalg_conv_1d", - n_views = [2, 1], - iterator_types = ["parallel", "parallel"], - symbol_source = 1 -} - -func @conv1d(%in : memref, %filter : memref, %out : memref) -> () { - linalg.generic #conv_1d_trait - ins(%in, %filter : memref, memref) - outs(%out : memref) { - ^bb0(%a: f32, %b: f32, %c: f32) : - %d = mulf %a, %b : f32 - %e = addf %c, %d : f32 - linalg.yield %e : f32 - } - return -} - -// CHECKLOOP-LABEL: @conv1d -// CHECKLOOP-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKLOOP: %[[c0:.*]] = constant 0 : index -// CHECKLOOP: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKLOOP: %[[dim1:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[lowerBound:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim1]]] -// CHECKLOOP: %[[upperBound:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim1]], %[[dim0]]] -// CHECKLOOP: scf.for %[[b:.*]] = %[[lowerBound]] to %[[upperBound]] step %{{.*}} { -// CHECKLOOP: scf.for %[[m:.*]] = %{{.*}} to %[[dim1]] step %{{.*}} { -// CHECKLOOP: %[[dim2:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[aff:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim2]]] -// CHECKLOOP: %[[va:.*]] = load %[[arg0]][%[[aff]]] : memref -// CHECKLOOP: %[[vb:.*]] = load %[[arg1]][%[[m]]] : memref -// CHECKLOOP: %[[vc:.*]] = load %[[arg2]][%[[b]]] : memref -// CHECKLOOP: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKLOOP: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKLOOP: store %[[res]], %[[arg2]][%[[b]]] : memref - -// CHECKPARALLEL-LABEL: @conv1d -// CHECKPARALLEL-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL: %[[c0:.*]] = constant 0 : index -// CHECKPARALLEL: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim1:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[lowerBound:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim1]]] -// CHECKPARALLEL: %[[upperBound:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim1]], %[[dim0]]] -// CHECKPARALLEL: scf.parallel (%[[b:.*]], %[[m:.*]]) = (%[[lowerBound]], %{{.*}}) to (%[[upperBound]], %[[dim1]]) step ({{.*}}) { -// CHECKPARALLEL: %[[dim2:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[aff:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim2]]] -// CHECKPARALLEL: %[[va:.*]] = load %[[arg0]][%[[aff]]] : memref -// CHECKPARALLEL: %[[vb:.*]] = load %[[arg1]][%[[m]]] : memref -// CHECKPARALLEL: %[[vc:.*]] = load %[[arg2]][%[[b]]] : memref -// CHECKPARALLEL: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKPARALLEL: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKPARALLEL: store %[[res]], %[[arg2]][%[[b]]] : memref - -#conv_2d_accesses = [ - affine_map<(m, n, m1, n1)[s0, s1] -> (m + m1 - s0 floordiv 2, n + n1 - s1 floordiv 2)>, // in - affine_map<(m, n, m1, n1)[s0, s1] -> (m1, n1)>, // filter - affine_map<(m, n, m1, n1)[s0, s1] -> (m, n)> // out -] - -#conv_2d_trait = { - args_in = 2, - args_out = 1, - doc = "C(m,n) += A(m,n) * B(m1,n1)", - indexing_maps = #conv_2d_accesses, - library_call = "linalg_conv_2d", - n_views = [2, 1], - iterator_types = ["parallel", "parallel", "parallel", "parallel"], - symbol_source = 1 -} - -func @conv2d(%in : memref, %filter : memref, %out : memref) -> () { - linalg.generic #conv_2d_trait - ins(%in, %filter : memref, memref) - outs(%out : memref) { - ^bb0(%a: f32, %b: f32, %c: f32) : - %d = mulf %a, %b : f32 - %e = addf %c, %d : f32 - linalg.yield %e : f32 - } - return -} - -// CHECKLOOP-LABEL: @conv2d -// CHECKLOOP-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKLOOP: %[[c0:.*]] = constant 0 : index -// CHECKLOOP: %[[c1:.*]] = constant 1 : index -// CHECKLOOP: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKLOOP: %[[dim1:.*]] = dim %[[arg0]], %[[c1]] : memref -// CHECKLOOP: %[[dim2:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[dim3:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKLOOP: %[[lowerBound1:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim2]]] -// CHECKLOOP: %[[upperBound1:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim2]], %[[dim0]]] -// CHECKLOOP: %[[lowerBound2:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim3]]] -// CHECKLOOP: %[[upperBound2:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim3]], %[[dim1]]] -// CHECKLOOP: scf.for %[[i0:.*]] = %[[lowerBound1]] to %[[upperBound1]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i1:.*]] = %[[lowerBound2]] to %[[upperBound2]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i2:.*]] = %{{.*}} to %[[dim2]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i3:.*]] = %{{.*}} to %[[dim3]] step %{{.*}} { -// CHECKLOOP: %[[dim4:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[dim5:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKLOOP: %[[aff1:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim4]]] -// CHECKLOOP: %[[aff2:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim5]]] -// CHECKLOOP: %[[va:.*]] = load %[[arg0]][%[[aff1]], %[[aff2]]] : memref -// CHECKLOOP: %[[vb:.*]] = load %[[arg1]][%[[i2]], %[[i3]]] : memref -// CHECKLOOP: %[[vc:.*]] = load %[[arg2]][%[[i0]], %[[i1]]] : memref -// CHECKLOOP: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKLOOP: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKLOOP: store %[[res]], %[[arg2]][%[[i0]], %[[i1]]] : memref - -// CHECKPARALLEL-LABEL: @conv2d -// CHECKPARALLEL-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL: %[[c0:.*]] = constant 0 : index -// CHECKPARALLEL: %[[c1:.*]] = constant 1 : index -// CHECKPARALLEL: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim1:.*]] = dim %[[arg0]], %[[c1]] : memref -// CHECKPARALLEL: %[[dim2:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim3:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKPARALLEL: %[[lowerBound1:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim2]]] -// CHECKPARALLEL: %[[upperBound1:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim2]], %[[dim0]]] -// CHECKPARALLEL: %[[lowerBound2:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim3]]] -// CHECKPARALLEL: %[[upperBound2:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim3]], %[[dim1]]] -// CHECKPARALLEL: scf.parallel (%[[i0:.*]], %[[i1:.*]], %[[i2:.*]], %[[i3:.*]]) = (%[[lowerBound1]], %[[lowerBound2]], %{{.*}}, %{{.*}}) to (%[[upperBound1]], %[[upperBound2]], %[[dim2]], %[[dim3]]) step ({{.*}}) { -// CHECKPARALLEL: %[[dim4:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim5:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKPARALLEL: %[[aff1:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim4]]] -// CHECKPARALLEL: %[[aff2:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim5]]] -// CHECKPARALLEL: %[[va:.*]] = load %[[arg0]][%[[aff1]], %[[aff2]]] : memref -// CHECKPARALLEL: %[[vb:.*]] = load %[[arg1]][%[[i2]], %[[i3]]] : memref -// CHECKPARALLEL: %[[vc:.*]] = load %[[arg2]][%[[i0]], %[[i1]]] : memref -// CHECKPARALLEL: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKPARALLEL: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKPARALLEL: store %[[res]], %[[arg2]][%[[i0]], %[[i1]]] : memref - -#conv_3d_accesses = [ - affine_map<(m, n, k, m1, n1, k1)[s0, s1, s2] -> (m + m1 - s0 floordiv 2, n + n1 - s1 floordiv 2, k + k1 - s2 floordiv 2)>, // in - affine_map<(m, n, k, m1, n1, k1)[s0, s1, s2] -> (m1, n1, k1)>, // filter - affine_map<(m, n, k, m1, n1, k1)[s0, s1, s2] -> (m, n, k)> // out -] - -#conv_3d_trait = { - args_in = 2, - args_out = 1, - doc = "C(m,n,k) += A(m,n,k) * B(m1,n1,k1)", - indexing_maps = #conv_3d_accesses, - library_call = "linalg_conv_3d", - n_views = [2, 1], - iterator_types = ["parallel", "parallel", "parallel", "parallel", "parallel", "parallel"], - symbol_source = 1 -} - -func @conv3d(%in : memref, %filter : memref, %out : memref) -> () { - linalg.generic #conv_3d_trait - ins(%in, %filter : memref, memref) - outs(%out : memref) { - ^bb0(%a: f32, %b: f32, %c: f32) : - %d = mulf %a, %b : f32 - %e = addf %c, %d : f32 - linalg.yield %e : f32 - } - return -} - -// CHECKLOOP-LABEL: @conv3d -// CHECKLOOP-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKLOOP: %[[c0:.*]] = constant 0 : index -// CHECKLOOP: %[[c1:.*]] = constant 1 : index -// CHECKLOOP: %[[c2:.*]] = constant 2 : index -// CHECKLOOP: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKLOOP: %[[dim1:.*]] = dim %[[arg0]], %[[c1]] : memref -// CHECKLOOP: %[[dim2:.*]] = dim %[[arg0]], %[[c2]] : memref -// CHECKLOOP: %[[dim3:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[dim4:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKLOOP: %[[dim5:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKLOOP: %[[lowerBound1:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim3]]] -// CHECKLOOP: %[[upperBound1:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim3]], %[[dim0]]] -// CHECKLOOP: %[[lowerBound2:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim4]]] -// CHECKLOOP: %[[upperBound2:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim4]], %[[dim1]]] -// CHECKLOOP: %[[lowerBound3:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim5]]] -// CHECKLOOP: %[[upperBound3:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim5]], %[[dim2]]] -// CHECKLOOP: scf.for %[[i0:.*]] = %[[lowerBound1]] to %[[upperBound1]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i1:.*]] = %[[lowerBound2]] to %[[upperBound2]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i2:.*]] = %[[lowerBound3]] to %[[upperBound3]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i3:.*]] = %{{.*}} to %[[dim3]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i4:.*]] = %{{.*}} to %[[dim4]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i5:.*]] = %{{.*}} to %[[dim5]] step %{{.*}} { -// CHECKLOOP: %[[dim6:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[dim7:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKLOOP: %[[dim8:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKLOOP: %[[aff1:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim6]]] -// CHECKLOOP: %[[aff2:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim7]]] -// CHECKLOOP: %[[aff3:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim8]]] -// CHECKLOOP: %[[va:.*]] = load %[[arg0]][%[[aff1]], %[[aff2]], %[[aff3]]] : memref -// CHECKLOOP: %[[vb:.*]] = load %[[arg1]][%[[i3]], %[[i4]], %[[i5]]] : memref -// CHECKLOOP: %[[vc:.*]] = load %[[arg2]][%[[i0]], %[[i1]], %[[i2]]] : memref -// CHECKLOOP: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKLOOP: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKLOOP: store %[[res]], %[[arg2]][%[[i0]], %[[i1]], %[[i2]]] : memref - -// CHECKPARALLEL-LABEL: @conv3d -// CHECKPARALLEL-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL: %[[c0:.*]] = constant 0 : index -// CHECKPARALLEL: %[[c1:.*]] = constant 1 : index -// CHECKPARALLEL: %[[c2:.*]] = constant 2 : index -// CHECKPARALLEL: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim1:.*]] = dim %[[arg0]], %[[c1]] : memref -// CHECKPARALLEL: %[[dim2:.*]] = dim %[[arg0]], %[[c2]] : memref -// CHECKPARALLEL: %[[dim3:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim4:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKPARALLEL: %[[dim5:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKPARALLEL: %[[lowerBound1:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim3]]] -// CHECKPARALLEL: %[[upperBound1:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim3]], %[[dim0]]] -// CHECKPARALLEL: %[[lowerBound2:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim4]]] -// CHECKPARALLEL: %[[upperBound2:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim4]], %[[dim1]]] -// CHECKPARALLEL: %[[lowerBound3:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim5]]] -// CHECKPARALLEL: %[[upperBound3:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim5]], %[[dim2]]] -// CHECKPARALLEL: scf.parallel (%[[i0:.*]], %[[i1:.*]], %[[i2:.*]], %[[i3:.*]], %[[i4:.*]], %[[i5:.*]]) = (%[[lowerBound1]], %[[lowerBound2]], %[[lowerBound3]], %{{.*}}, %{{.*}}, %{{.*}}) to (%[[upperBound1]], %[[upperBound2]], %[[upperBound3]], %[[dim3]], %[[dim4]], %[[dim5]]) step ({{.*}}) { -// CHECKPARALLEL: %[[dim6:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim7:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKPARALLEL: %[[dim8:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKPARALLEL: %[[aff1:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim6]]] -// CHECKPARALLEL: %[[aff2:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim7]]] -// CHECKPARALLEL: %[[aff3:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim8]]] -// CHECKPARALLEL: %[[va:.*]] = load %[[arg0]][%[[aff1]], %[[aff2]], %[[aff3]]] : memref -// CHECKPARALLEL: %[[vb:.*]] = load %[[arg1]][%[[i3]], %[[i4]], %[[i5]]] : memref -// CHECKPARALLEL: %[[vc:.*]] = load %[[arg2]][%[[i0]], %[[i1]], %[[i2]]] : memref -// CHECKPARALLEL: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKPARALLEL: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKPARALLEL: store %[[res]], %[[arg2]][%[[i0]], %[[i1]], %[[i2]]] : memref - -#conv_4d_accesses = [ - affine_map<(m, n, k, l, m1, n1, k1, l1)[s0, s1, s2, s3] -> (m + m1 - s0 floordiv 2, n + n1 - s1 floordiv 2, k + k1 - s2 floordiv 2, l + l1 - s3 floordiv 2)>, // in - affine_map<(m, n, k, l, m1, n1, k1, l1)[s0, s1, s2, s3] -> (m1, n1, k1, l1)>, // filter - affine_map<(m, n, k, l, m1, n1, k1, l1)[s0, s1, s2, s3] -> (m, n, k, l)> // out -] - -#conv_4d_trait = { - args_in = 2, - args_out = 1, - doc = "C(m,n,k,l) += A(m,n,k,l) * B(m1,n1,k1,l1)", - indexing_maps = #conv_4d_accesses, - library_call = "linalg_conv_4d", - n_views = [2, 1], - iterator_types = ["parallel", "parallel", "parallel", "parallel", "parallel", "parallel", "parallel", "parallel"], - symbol_source = 1 -} - -func @conv4d(%in : memref, %filter : memref, %out : memref) -> () { - linalg.generic #conv_4d_trait - ins(%in, %filter : memref, memref) - outs(%out : memref) { - ^bb0(%a: f32, %b: f32, %c: f32) : - %d = mulf %a, %b : f32 - %e = addf %c, %d : f32 - linalg.yield %e : f32 - } - return -} - -// CHECKLOOP-LABEL: @conv4d -// CHECKLOOP-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKLOOP-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKLOOP: %[[c0:.*]] = constant 0 : index -// CHECKLOOP: %[[c1:.*]] = constant 1 : index -// CHECKLOOP: %[[c2:.*]] = constant 2 : index -// CHECKLOOP: %[[c3:.*]] = constant 3 : index -// CHECKLOOP: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKLOOP: %[[dim1:.*]] = dim %[[arg0]], %[[c1]] : memref -// CHECKLOOP: %[[dim2:.*]] = dim %[[arg0]], %[[c2]] : memref -// CHECKLOOP: %[[dim3:.*]] = dim %[[arg0]], %[[c3]] : memref -// CHECKLOOP: %[[dim4:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[dim5:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKLOOP: %[[dim6:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKLOOP: %[[dim7:.*]] = dim %[[arg1]], %[[c3]] : memref -// CHECKLOOP: %[[lowerBound1:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim4]]] -// CHECKLOOP: %[[upperBound1:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim4]], %[[dim0]]] -// CHECKLOOP: %[[lowerBound2:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim5]]] -// CHECKLOOP: %[[upperBound2:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim5]], %[[dim1]]] -// CHECKLOOP: %[[lowerBound3:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim6]]] -// CHECKLOOP: %[[upperBound3:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim6]], %[[dim2]]] -// CHECKLOOP: %[[lowerBound4:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim7]]] -// CHECKLOOP: %[[upperBound4:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim7]], %[[dim3]]] -// CHECKLOOP: scf.for %[[i0:.*]] = %[[lowerBound1]] to %[[upperBound1]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i1:.*]] = %[[lowerBound2]] to %[[upperBound2]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i2:.*]] = %[[lowerBound3]] to %[[upperBound3]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i3:.*]] = %[[lowerBound4]] to %[[upperBound4]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i4:.*]] = %{{.*}} to %[[dim4]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i5:.*]] = %{{.*}} to %[[dim5]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i6:.*]] = %{{.*}} to %[[dim6]] step %{{.*}} { -// CHECKLOOP: scf.for %[[i7:.*]] = %{{.*}} to %[[dim7]] step %{{.*}} { -// CHECKLOOP: %[[dim8:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKLOOP: %[[dim9:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKLOOP: %[[dim10:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKLOOP: %[[dim11:.*]] = dim %[[arg1]], %[[c3]] : memref -// CHECKLOOP: %[[aff1:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim8]]] -// CHECKLOOP: %[[aff2:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim9]]] -// CHECKLOOP: %[[aff3:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim10]]] -// CHECKLOOP: %[[aff4:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim11]]] -// CHECKLOOP: %[[va:.*]] = load %[[arg0]][%[[aff1]], %[[aff2]], %[[aff3]], %[[aff4]]] : memref -// CHECKLOOP: %[[vb:.*]] = load %[[arg1]][%[[i4]], %[[i5]], %[[i6]], %[[i7]]] : memref -// CHECKLOOP: %[[vc:.*]] = load %[[arg2]][%[[i0]], %[[i1]], %[[i2]], %[[i3]]] : memref -// CHECKLOOP: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKLOOP: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKLOOP: store %[[res]], %[[arg2]][%[[i0]], %[[i1]], %[[i2]], %[[i3]]] : memref - -// CHECKPARALLEL-LABEL: @conv4d -// CHECKPARALLEL-SAME: %[[arg0:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg1:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL-SAME: %[[arg2:[a-zA-Z0-9]+]]: memref -// CHECKPARALLEL: %[[c0:.*]] = constant 0 : index -// CHECKPARALLEL: %[[c1:.*]] = constant 1 : index -// CHECKPARALLEL: %[[c2:.*]] = constant 2 : index -// CHECKPARALLEL: %[[c3:.*]] = constant 3 : index -// CHECKPARALLEL: %[[dim0:.*]] = dim %[[arg0]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim1:.*]] = dim %[[arg0]], %[[c1]] : memref -// CHECKPARALLEL: %[[dim2:.*]] = dim %[[arg0]], %[[c2]] : memref -// CHECKPARALLEL: %[[dim3:.*]] = dim %[[arg0]], %[[c3]] : memref -// CHECKPARALLEL: %[[dim4:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim5:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKPARALLEL: %[[dim6:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKPARALLEL: %[[dim7:.*]] = dim %[[arg1]], %[[c3]] : memref -// CHECKPARALLEL: %[[lowerBound1:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim4]]] -// CHECKPARALLEL: %[[upperBound1:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim4]], %[[dim0]]] -// CHECKPARALLEL: %[[lowerBound2:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim5]]] -// CHECKPARALLEL: %[[upperBound2:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim5]], %[[dim1]]] -// CHECKPARALLEL: %[[lowerBound3:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim6]]] -// CHECKPARALLEL: %[[upperBound3:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim6]], %[[dim2]]] -// CHECKPARALLEL: %[[lowerBound4:.*]] = affine.apply #[[$convLowerBound]]()[%[[dim7]]] -// CHECKPARALLEL: %[[upperBound4:.*]] = affine.apply #[[$convUpperBound]]()[%[[dim7]], %[[dim3]]] -// CHECKPARALLEL: scf.parallel (%[[i0:.*]], %[[i1:.*]], %[[i2:.*]], %[[i3:.*]], %[[i4:.*]], %[[i5:.*]], %[[i6:.*]], %[[i7:.*]]) = (%[[lowerBound1]], %[[lowerBound2]], %[[lowerBound3]], %[[lowerBound4]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) to (%[[upperBound1]], %[[upperBound2]], %[[upperBound3]], %[[upperBound4]], %[[dim4]], %[[dim5]], %[[dim6]], %[[dim7]]) step ({{.*}}) { -// CHECKPARALLEL: %[[dim8:.*]] = dim %[[arg1]], %[[c0]] : memref -// CHECKPARALLEL: %[[dim9:.*]] = dim %[[arg1]], %[[c1]] : memref -// CHECKPARALLEL: %[[dim10:.*]] = dim %[[arg1]], %[[c2]] : memref -// CHECKPARALLEL: %[[dim11:.*]] = dim %[[arg1]], %[[c3]] : memref -// CHECKPARALLEL: %[[aff1:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim8]]] -// CHECKPARALLEL: %[[aff2:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim9]]] -// CHECKPARALLEL: %[[aff3:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim10]]] -// CHECKPARALLEL: %[[aff4:.*]] = affine.apply #[[$convMap]](%{{.*}}, %{{.*}})[%[[dim11]]] -// CHECKPARALLEL: %[[va:.*]] = load %[[arg0]][%[[aff1]], %[[aff2]], %[[aff3]], %[[aff4]]] : memref -// CHECKPARALLEL: %[[vb:.*]] = load %[[arg1]][%[[i4]], %[[i5]], %[[i6]], %[[i7]]] : memref -// CHECKPARALLEL: %[[vc:.*]] = load %[[arg2]][%[[i0]], %[[i1]], %[[i2]], %[[i3]]] : memref -// CHECKPARALLEL: %[[inc:.*]] = mulf %[[va]], %[[vb]] : f32 -// CHECKPARALLEL: %[[res:.*]] = addf %[[vc]], %[[inc]] : f32 -// CHECKPARALLEL: store %[[res]], %[[arg2]][%[[i0]], %[[i1]], %[[i2]], %[[i3]]] : memref func @conv1d_no_symbols(%in : memref, %filter : memref, %out : memref) -> () { linalg.conv_1d ins(%in, %filter : memref, memref)