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 @@ -32,7 +32,7 @@ // always be 0 for index-free linalg ops. For IndexedGeneric, this must be // equal to numLoops. unsigned getNumPayloadInductionVariables() { - return isa(this->getOperation()) ? getNumLoops() : 0; + return 0; } // Return whether the op accesses the iteration indices. @@ -671,140 +671,6 @@ let hasFolder = 1; } -/// GenericOp with Indexing (i.e. multi-for style in which the region is passed -/// the enclosing loop induction variables) -def IndexedGenericOp : GenericOpBase<"indexed_generic"> { - let description = [{ - Indexed Generic Linalg op form where the key properties of the computation - are specified as attributes. In pretty form, a `linalg.indexed_generic` op - is written as: - - ```mlir - linalg.indexed_generic #trait_attribute - ins(%A, %B : memref, - memref) - outs(%C : memref) - attrs = {other-optional-attributes} - {region} - ``` - - Where #trait_attributes is an alias of a dictionary attribute containing: - - doc [optional]: a documentation string - - indexing_maps: a list of AffineMapAttr, one AffineMapAttr per each input - and output view. Such AffineMapAttr specifies the mapping between the - loops and the indexing within each view. - - library_call [optional]: a StringAttr containing the name of an - external library function that the linalg.indexed_generic operation - maps to. The external library is assumed to be dynamically linked and - no strong compile-time guarantees are provided. In the absence of such - a library call, linalg.indexed_generic will always lower to loops. - - iterator_types: an ArrayAttr they type of the enclosing loops; Each - element of the list represents and iterator of one of the following - types: - parallel, reduction, window - - Example: - Defining a #matmul_trait attribute in MLIR can be done as follows: - - ```mlir - #matmul_accesses = [ - (m, n, k) -> (m, k), - (m, n, k) -> (k, n), - (m, n, k) -> (m, n) - ] - #matmul_trait = { - doc = "C(m, n) += A(m, k) * B(k, n)", - indexing_maps = #matmul_accesses, - library_call = "linalg_matmul", - iterator_types = ["parallel", "parallel", "reduction"] - } - ``` - - And can be reused in multiple places as: - - ```mlir - linalg.indexed_generic #matmul_trait - ins(%A, %B : memref, - memref) - outs(%C : memref) { - (%offset_m: index, %offset_n: index, %offset_k: index, - %a: f32, %b: f32, %c: f32) : - "some_optional_computation"(%offset_m, %offset_n, %offset_k) - %d = mulf %a, %b: f32 - %e = addf %c, %d: f32 - linalg_yield %e : f32 - } - ``` - - This may lower to either: - - ```mlir - call @linalg_matmul(%offset_m, %offset_n, %offset_k, %A, %B, %C) : - (index, index, index, - memref, - memref, - memref) - -> () - ``` - - or IR resembling: - - ```mlir - scf.for %m = %c0 to %M step %c1 { - scf.for %n = %c0 to %N step %c1 { - scf.for %k = %c0 to %K step %c1 { - %a = load %A[%m, %k] : memref - %b = load %B[%k, %n] : memref - %c = load %C[%m, %n] : memref - "some_optional_computation"(%m, %n, %k) - %d = mulf %a, %b: f32 - %e = addf %c, %d: f32 - store %d, %C[%m, %n] : memref - } - } - } - ``` - - To allow progressive lowering from the value world (a.k.a tensor values) to - the buffer world (a.k.a memref values), a `linalg.indexed_generic` op - allows mixing tensors and buffers operands and tensor results. - - ```mlir - %C = linalg.indexed_generic #trait_attribute - ins(%A, %B : tensor, memref) - outs(%C : tensor) - {other-optional-attributes} - {region_with_index_arguments} - -> (tensor) - ``` - }]; - - let builders = [ - OpBuilder<(ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, - "ValueRange":$outputs, "ArrayRef":$indexingMaps, - "ArrayRef":$iteratorTypes, "StringRef":$doc, - "StringRef":$libraryCall, - CArg<"function_ref", - "nullptr">)>, - OpBuilder<(ins "ValueRange":$inputs, "ValueRange":$outputBuffers, - "ArrayRef":$indexingMaps, "ArrayRef":$iteratorTypes, - "StringRef":$doc, "StringRef":$libraryCall, - CArg<"function_ref", - "nullptr">)>, - OpBuilder<(ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, - "ValueRange":$outputs, "ArrayRef":$indexingMaps, - "ArrayRef":$iteratorTypes, - CArg<"function_ref", - "nullptr">)>, - OpBuilder<(ins "ValueRange":$inputs, "ValueRange":$outputBuffers, - "ArrayRef":$indexingMaps, "ArrayRef":$iteratorTypes, - CArg<"function_ref", - "nullptr">)> - ]; - let verifier = [{ return ::verify(*this); }]; - - let hasCanonicalizer = 1; -} //===----------------------------------------------------------------------===// // Named Linalg ops, implemented as a declarative configurations of generic ops. diff --git a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp --- a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp +++ b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp @@ -100,10 +100,6 @@ if (isa(op)) return failure(); - // Canonicalize indexed generic operations before library call conversion. - if (isa(op)) - return failure(); - auto libraryCallName = getLibraryCallSymbolRef(op, rewriter); if (!libraryCallName) return failure(); 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 @@ -525,69 +525,8 @@ /*doc=*/"", /*libraryCall=*/"", bodyBuild); } -void IndexedGenericOp::build( - OpBuilder &builder, OperationState &result, TypeRange resultTensorTypes, - ValueRange inputs, ValueRange outputs, ArrayRef indexingMaps, - ArrayRef iteratorTypes, StringRef doc, StringRef libraryCall, - function_ref - bodyBuild) { - build(builder, result, resultTensorTypes, inputs, outputs, - builder.getAffineMapArrayAttr(indexingMaps), - builder.getStrArrayAttr(iteratorTypes), - doc.empty() ? StringAttr() : builder.getStringAttr(doc), - libraryCall.empty() ? StringAttr() - : builder.getStringAttr(libraryCall)); - if (!bodyBuild) - return; - - unsigned nLoops = iteratorTypes.size(); - SmallVector blockArgTypes(nLoops, builder.getIndexType()); - for (ValueRange container : {inputs, outputs}) - for (Value v : container) - blockArgTypes.push_back(getElementTypeOrSelf(v)); - - OpBuilder::InsertionGuard guard(builder); - auto ®ion = *result.regions.front(); - Block *bodyBlock = builder.createBlock(®ion, region.end(), blockArgTypes); - bodyBuild(builder, result.location, - bodyBlock->getArguments().take_front(nLoops), - bodyBlock->getArguments().drop_front(nLoops)); -} - -void IndexedGenericOp::build( - OpBuilder &builder, OperationState &result, ValueRange inputs, - ValueRange outputs, ArrayRef indexingMaps, - ArrayRef iteratorTypes, StringRef doc, StringRef libraryCall, - function_ref - bodyBuild) { - build(builder, result, TypeRange{}, inputs, outputs, indexingMaps, - iteratorTypes, doc, libraryCall, bodyBuild); -} - -void IndexedGenericOp::build( - OpBuilder &builder, OperationState &result, ValueRange inputs, - ValueRange outputs, ArrayRef indexingMaps, - ArrayRef iteratorTypes, - function_ref - bodyBuild) { - build(builder, result, inputs, outputs, indexingMaps, iteratorTypes, - /*doc=*/"", /*libraryCall=*/"", bodyBuild); -} - -void IndexedGenericOp::build( - OpBuilder &builder, OperationState &result, TypeRange resultTensorTypes, - ValueRange inputs, ValueRange outputs, ArrayRef indexingMaps, - ArrayRef iteratorTypes, - function_ref - bodyBuild) { - build(builder, result, resultTensorTypes, inputs, outputs, indexingMaps, - iteratorTypes, - /*doc=*/"", - /*libraryCall=*/"", bodyBuild); -} -template -static void printGenericOp(OpAsmPrinter &p, GenericOpType op) { +static void print(OpAsmPrinter &p, GenericOp op) { p << op.getOperationName() << " "; // Print extra attributes. @@ -628,12 +567,6 @@ printNamedStructuredOpResults(p, op.result_tensors().getTypes()); } -static void print(OpAsmPrinter &p, GenericOp op) { printGenericOp(p, op); } - -static void print(OpAsmPrinter &p, IndexedGenericOp op) { - printGenericOp(p, op); -} - static ParseResult parseGenericOp(OpAsmParser &parser, OperationState &result) { DictionaryAttr dictAttr; // Parse the core linalg traits that must check into a dictAttr. @@ -704,15 +637,6 @@ outputBuffers); } -void IndexedGenericOp::getEffects( - SmallVectorImpl> - &effects) { - SmallVector inputBuffers = getInputBufferOperands(); - SmallVector outputBuffers = getOutputBufferOperands(); - getGenericEffectsImpl(effects, getOperation()->getResults(), inputBuffers, - outputBuffers); -} - template static LogicalResult verifyGenericOp(GenericOpType op) { return success(); @@ -720,52 +644,6 @@ static LogicalResult verify(GenericOp op) { return verifyGenericOp(op); } -static LogicalResult verify(IndexedGenericOp op) { return verifyGenericOp(op); } - -namespace { - -/// Replace indexed_generic ops by generic ops that access the iteration indices -/// using index operation calls. -struct ConvertIndexedToGenericOp : OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - LogicalResult matchAndRewrite(IndexedGenericOp indexedOp, - PatternRewriter &rewriter) const override { - // Replace all uses of the index block arguments. - BlockAndValueMapping bvm; - if (Block *body = indexedOp.getBody()) { - rewriter.setInsertionPointToStart(body); - for (const auto &en : llvm::enumerate( - body->getArguments().take_front(indexedOp.getNumLoops()))) { - Value index = rewriter.create(indexedOp.getLoc(), en.index()); - bvm.map(en.value(), index); - } - } - - // Create a generic replacement operation and clone the body. - rewriter.setInsertionPointAfter(indexedOp); - SmallVector inputOperands = indexedOp.getInputOperands(); - SmallVector outputOperands = indexedOp.getOutputOperands(); - SmallVector iterators = llvm::to_vector<4>( - indexedOp.iterator_types().getAsValueRange()); - GenericOp genericOp = rewriter.create( - indexedOp.getLoc(), indexedOp->getResultTypes(), inputOperands, - outputOperands, indexedOp.getIndexingMaps(), iterators); - Region &genericRegion = genericOp.region(); - Region &indexedRegion = indexedOp.region(); - rewriter.cloneRegionBefore(indexedRegion, genericRegion, - genericRegion.begin(), bvm); - - rewriter.replaceOp(indexedOp, genericOp->getResults()); - return success(); - } -}; -} // namespace - -void IndexedGenericOp::getCanonicalizationPatterns(RewritePatternSet &results, - MLIRContext *context) { - results.add(context); -} - //===----------------------------------------------------------------------===// // InitTensorOp //===----------------------------------------------------------------------===// @@ -3230,7 +3108,7 @@ PatternRewriter &rewriter) const override { // This pattern reduces the number of arguments of an op, which breaks // the invariants of semantically charged named ops. - if (!isa(op)) + if (!isa(op)) return failure(); // Associate each input to an equivalent "canonical" input that has the same @@ -3290,10 +3168,6 @@ // the value from the original op. newLinalgOp.setNumInputs(canonicalInput.size()); - // linalg.indexed_generic payloads have additional arguments prepended to - // the block arg list. - int bbArgBaseOffset = newLinalgOp.getNumPayloadInductionVariables(); - // Repair the payload entry block by RAUW'ing redundant arguments and // erasing them. Block &payload = newOp->getRegion(0).front(); @@ -3305,10 +3179,10 @@ unsigned operandNumber = opOperand->getOperandNumber(); if (canonicalInputIndices[operandNumber] == operandNumber) continue; - payload.getArgument(bbArgBaseOffset + operandNumber) - .replaceAllUsesWith(payload.getArgument( - bbArgBaseOffset + canonicalInputIndices[operandNumber])); - payload.eraseArgument(bbArgBaseOffset + operandNumber); + payload.getArgument(operandNumber) + .replaceAllUsesWith( + payload.getArgument(canonicalInputIndices[operandNumber])); + payload.eraseArgument(operandNumber); } rewriter.replaceOp(op, newOp->getResults()); @@ -3316,7 +3190,7 @@ } }; -/// Remove generic/indexed_generic operations (on tensors) that are just copying +/// Remove generic operations (on tensors) that are just copying /// the values from inputs to the results. Requirements are /// 1) All iterator types are parallel /// 2) The body contains just a yield operation with the yielded values being @@ -3335,7 +3209,7 @@ } } - if (!isa(op)) + if (!isa(op)) return failure(); if (!op.hasTensorSemantics()) return failure(); 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 @@ -202,10 +202,6 @@ LogicalResult matchAndRewrite(LinalgOp op, ArrayRef operands, ConversionPatternRewriter &rewriter) const final { - // Canonicalize indexed generic operations before bufferization. - if (isa(op)) - return failure(); - // GenericOpAdaptor below expects an `operand_segment_sizes` attribute. if (!op->hasAttr("operand_segment_sizes")) return failure(); diff --git a/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp b/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp @@ -230,7 +230,6 @@ // When the producer has index semantics, we have to transform the indices of // the producer according to the tiling of the consumer, i.e. offset them by // the values computed in `loopRanges`. - assert(!isa(producer) && "unexpected op"); if (producer.hasIndexSemantics()) { assert(clonedOp->getNumRegions() == 1 && clonedOp->getRegion(0).getBlocks().size() == 1 && @@ -426,10 +425,6 @@ if (!fusableDependence) return llvm::None; - // Canonicalize indexed generic ops before fusion. - if (isa(fusableDependence->getDependentOp())) - return llvm::None; - LinalgOp producerOp = dyn_cast(fusableDependence->getDependentOp()); if (!producerOp) return llvm::None; @@ -507,10 +502,6 @@ Optional mlir::linalg::fuseProducerOfTensor(OpBuilder &b, OpResult producerOpResult, OpOperand &consumerOpOperand) { - // Canonicalize indexed generic ops before fusion. - if (isa(producerOpResult.getOwner())) - return llvm::None; - auto producerOp = dyn_cast(producerOpResult.getOwner()); if (!producerOp) return llvm::None; @@ -766,9 +757,6 @@ fusableDependence = findFusableProducer(*opOperand, dependenceGraph); if (!fusableDependence) continue; - // Canonicalize indexed generic ops before fusion. - if (isa(fusableDependence->getDependentOp())) - continue; LinalgOp producerOp = dyn_cast(fusableDependence->getDependentOp()); if (!producerOp) 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 @@ -1402,7 +1402,6 @@ options.controlFoldingReshapesFn); AffineApplyOp::getCanonicalizationPatterns(patterns, context); GenericOp::getCanonicalizationPatterns(patterns, context); - IndexedGenericOp::getCanonicalizationPatterns(patterns, context); TensorExpandShapeOp::getCanonicalizationPatterns(patterns, context); TensorCollapseShapeOp::getCanonicalizationPatterns(patterns, context); context->getLoadedDialect()->getCanonicalizationPatterns( diff --git a/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp @@ -130,8 +130,8 @@ if (failed(marker.checkAndNotify(rewriter, linalgOp))) return failure(); - // No nothing to do for linalg.generic and linalg.indexed_generic. - if (isa(rootOp)) + // No nothing to do for linalg.generic. + if (isa(rootOp)) return failure(); GenericOp genericOp = createGenericOpFromNamedOp(linalgOp, rewriter); 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 @@ -418,10 +418,6 @@ typename std::conditional::value, AffineStoreOp, memref::StoreOp>::type; - // Canonicalize indexed_generic operations before lowering them to loops. - if (isa(linalgOp)) - return llvm::None; - // The flattened loopToOperandRangesMaps is expected to be an invertible // permutation map (which is asserted in the inverse calculation). assert(linalgOp.hasBufferSemantics() && diff --git a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp @@ -163,10 +163,6 @@ if (llvm::all_of(tileSizes, isZero)) return llvm::None; - // Canonicalize indexed generic operations before tiling. - if (isa(op)) - return llvm::None; - if (auto convOp = dyn_cast(op.getOperation())) { // For conv op only support tiling along batch dimension (which is the first // loop). diff --git a/mlir/test/Dialect/Linalg/canonicalize-duplicate-inputs.mlir b/mlir/test/Dialect/Linalg/canonicalize-duplicate-inputs.mlir --- a/mlir/test/Dialect/Linalg/canonicalize-duplicate-inputs.mlir +++ b/mlir/test/Dialect/Linalg/canonicalize-duplicate-inputs.mlir @@ -89,26 +89,3 @@ } -> tensor return %0 : tensor } - -// ----- - -// Test case: linalg.indexed_generic. -// Other than the payload argument handling, everything else is the same. - -#map = affine_map<(d0) -> (d0)> - -// CHECK: #[[$MAP:.*]] = affine_map<(d0) -> (d0)> -// CHECK-LABEL: @indexed_generic -func @indexed_generic(%arg0: tensor) -> tensor { - // CHECK: linalg.generic - // CHECK: ^bb0(%[[BBARG:.*]]: f32, %{{[a-zA-Z0-9]+}}: f32): - // CHECK: addf %[[BBARG]], %[[BBARG]] - %0 = linalg.indexed_generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel"]} - ins(%arg0, %arg0 : tensor, tensor) - outs(%arg0 : tensor) { - ^bb0(%index: index, %arg1: f32, %arg2: f32, %arg3: f32): - %1 = addf %arg1, %arg2 : f32 - linalg.yield %1 : f32 - } -> tensor - return %0 : tensor -} diff --git a/mlir/test/Dialect/Linalg/canonicalize.mlir b/mlir/test/Dialect/Linalg/canonicalize.mlir --- a/mlir/test/Dialect/Linalg/canonicalize.mlir +++ b/mlir/test/Dialect/Linalg/canonicalize.mlir @@ -842,39 +842,6 @@ // ----- -#map = affine_map<(d0, d1) -> (d0, d1)> - -func @indexed_generic(%arg0: memref, %arg1: memref) { - linalg.indexed_generic { - indexing_maps = [#map, #map], - iterator_types = ["parallel", "parallel"]} - ins(%arg0 : memref) - outs(%arg1 : memref) { - ^bb0(%arg4: index, %arg5: index, %arg6: index, %arg7: index): - %0 = addi %arg4, %arg5 : index - %1 = addi %0, %arg6 : index - %2 = addi %1, %arg7 : index - linalg.yield %2 : index - } - return -} - -// CHECK: #[[MAP:.+]] = affine_map<(d0, d1) -> (d0, d1)> -// CHECK: func @indexed_generic -// CHECK-NEXT: linalg.generic { -// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]]], iterator_types = ["parallel", "parallel"]} -// CHECK-SAME: ins(%[[ARG0:[A-Za-z0-9_]+]] : memref) -// CHECK-SAME: outs(%[[ARG1:[A-Za-z0-9_]+]] : memref) -// CHECK: ^bb0(%[[ARG2:[A-Za-z0-9_]+]]: index, %[[ARG3:[A-Za-z0-9_]+]]: index): -// CHECK-NEXT: %[[IDX0:.+]] = linalg.index 0 : index -// CHECK-NEXT: %[[IDX1:.+]] = linalg.index 1 : index -// CHECK-NEXT: %[[SUM0:.+]] = addi %[[IDX0]], %[[IDX1]] : index -// CHECK-NEXT: %[[SUM1:.+]] = addi %[[SUM0]], %[[ARG2]] : index -// CHECK-NEXT: %[[SUM2:.+]] = addi %[[SUM1]], %[[ARG3]] : index -// CHECK-NEXT: linalg.yield %[[SUM2]] : index - -// ----- - func @tensor_pad_cast_fold(%arg0: tensor<4x4xf32>) -> tensor<4x4xf32> { %c0 = constant 0 : index %cst = constant 0.0 : f32 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 @@ -227,72 +227,6 @@ // ----- -func @indexed_generic_block_arg_count(%arg0: memref) { - // expected-error @+1 {{expected as many non-induction variable region arguments as the number of input/output operands}} - linalg.indexed_generic { - indexing_maps = [ affine_map<(i) -> (i)> ], - iterator_types = ["parallel"]} - outs(%arg0 : memref) { - ^bb(%f: f32): - linalg.yield %f : f32 - } -} - -// ----- - -func @indexed_generic_block_induction_var_arg_type(%arg0: memref) { - // expected-error @+1 {{op expected index block argument #0}} - linalg.indexed_generic { - indexing_maps = [ affine_map<(d0) -> (d0)> ], - iterator_types = ["parallel"]} - outs(%arg0 : memref) { - ^bb(%i: f64, %f: f32): - linalg.yield %f: f32 - } -} - -// ----- - -func @indexed_generic_block_arg_type(%arg0: memref) { - // expected-error @+1 {{expected type of bb argument #1 ('i1') to match element or self type of the corresponding operand ('f32')}} - linalg.indexed_generic { - indexing_maps = [ affine_map<(d0) -> (d0)> ], - iterator_types = ["parallel"]} - outs(%arg0 : memref) { - ^bb(%i: index, %f: i1): - linalg.yield %i: index - } -} - -// ----- - -func @indexed_generic_arg_count(%arg0: memref) { - // expected-error @+1 {{expected as many non-induction variable region arguments as the number of input/output operands}} - linalg.indexed_generic { - indexing_maps = [ affine_map<()[] -> ()> ], - iterator_types = []} - outs(%arg0 : memref) { - ^bb(%0: index, %1: f32): - linalg.yield %1: f32 - } - return -} - -// ----- - -func @indexed_generic_result_count(%arg0: memref) { - // expected-error @+6 {{op expected number of yield values (1) to match the number of operands of the enclosing LinalgOp (2)}} - linalg.indexed_generic { - indexing_maps = [ affine_map<(d0) -> (d0)> ], - iterator_types = ["parallel"]} - outs(%arg0 : memref) { - ^bb(%i: index, %val: f32): - linalg.yield %val, %val: f32, f32 - } -} - -// ----- - func @generic_result_0_element_type(%arg0: memref(off + i)>>) { // expected-error @+7 {{type of yield operand 1 ('i1') doesn't match the element type of the enclosing linalg.generic op ('f32')}} linalg.generic { diff --git a/mlir/test/Dialect/Linalg/roundtrip.mlir b/mlir/test/Dialect/Linalg/roundtrip.mlir --- a/mlir/test/Dialect/Linalg/roundtrip.mlir +++ b/mlir/test/Dialect/Linalg/roundtrip.mlir @@ -1,7 +1,7 @@ // RUN: mlir-opt %s | mlir-opt | FileCheck %s // RUN: mlir-opt %s --mlir-print-op-generic | mlir-opt | FileCheck %s -// TODO: Re-enable LLVM lowering test after IndexedGenericOp is lowered. +// TODO: Re-enable LLVM lowering test. // // Test that we can lower all the way to LLVM without crashing, don't check results here. // DISABLED: mlir-opt %s --convert-linalg-to-llvm -o=/dev/null 2>&1 @@ -457,43 +457,6 @@ // ----- -#accesses_2 = [ - affine_map<(i, j, k) -> (j, i)>, - affine_map<(i, j, k) -> (i, k, i + j)>, - affine_map<(i, j, k) -> (i, k, i + j)> -] - -#trait_2 = { - indexing_maps = #accesses_2, - iterator_types = ["parallel", "parallel", "parallel"], - library_call = "some_external_function_name_1" -} - -func @indexed_generic_with_tensor_input_and_output( - %arg0: tensor>, %arg1: tensor) - -> (tensor) { - %0 = linalg.indexed_generic #trait_2 - ins(%arg0, %arg1 : tensor>, tensor) - outs(%arg1 : tensor) - attrs = {foo = 1} { - ^bb(%i: index, %j: index, %k: index, %0: vector<3x4xi4>, %1: f32, %2: f32) : - %f0 = constant 0.0 : f32 - linalg.yield %f0 : f32 - } -> tensor - return %0 : tensor -} -// CHECK-LABEL: func @indexed_generic_with_tensor_input_and_output -// CHECK: linalg.indexed_generic { -// CHECK-SAME: indexing_maps = [#{{.*}}, #{{.*}}], iterator_types = ["parallel", "parallel", "parallel"], -// CHECK-SAME: library_call = "some_external_function_name_1"} -// CHECK-SAME: ins({{.*}} : tensor>, tensor) -// CHECK-SAME: outs({{.*}} : tensor) -// CHECK-SAME: {foo = 1 : i64} -// CHECK: -> tensor -// CHECK: return {{.*}} : tensor - -// ----- - #broadcast_access = [ affine_map<(i, j) -> ()>, affine_map<(i, j) -> (i, j)> @@ -516,17 +479,6 @@ return %0 : tensor<3x4xf32> } -func @indexed_generic_op_zero_rank(%arg0: tensor, %arg1 : tensor<3x4xf32>) -> (tensor<3x4xf32>) -{ - %0 = linalg.indexed_generic #trait_broadcast - ins(%arg0 : tensor) - outs(%arg1 : tensor<3x4xf32>) { - ^bb(%i: index, %j: index, %a: f32, %b: f32) : - linalg.yield %a : f32 - } -> tensor<3x4xf32> - return %0 : tensor<3x4xf32> -} - // ----- @@ -569,29 +521,6 @@ // CHECK: %{{.*}} = linalg.index 2 : index // CHECK: linalg.yield %{{.*}} : f32 -func @indexed_generic(%arg0: memref, offset: ?, strides: [?, 1]>, - %arg1: memref) { - linalg.indexed_generic #trait_3 - ins(%arg0 : memref, offset: ?, strides: [?, 1]>) - outs(%arg1 : memref) - attrs = {foo = 1} { - ^bb(%i: index, %j: index, %k: index, %a: vector<3x4xi4>, %b: f32) : - linalg.yield %b : f32 - } - return -} -// CHECK-LABEL: func @indexed_generic -// CHECK: linalg.indexed_generic { -// CHECK-SAME: indexing_maps = [#{{[0-9a-z]*}}, #{{[0-9a-z]*}}], -// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"], -// CHECK-SAME: library_call = "some_external_function_name_2" -// CHECK-SAME: ins({{.*}} : memref, #[[$strided2D]]>) -// CHECK-SAME: outs({{.*}} : memref) -// CHECK-SAME: {foo = 1 : i64} -// CHECK: ^{{.*}}(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: vector<3x4xi4>, %{{.*}}: f32): -// CHECK: linalg.yield %{{.*}} : f32 -// CHECK: } - // ----- func @reshape_static(%arg0: memref<3x4x5xf32>, %arg1: tensor<3x4x5xf32>,