| # RUN: mlir-linalg-ods-yaml-gen %s --o-ods-decl=- | FileCheck %s --check-prefix=ODS |
| # RUN: mlir-linalg-ods-yaml-gen %s --o-impl=- | FileCheck %s --check-prefix=IMPL |
| |
| # @linalg_structured_op |
| # def test1(O=TensorDef(T, S.M, S.N, output=True), |
| # cast=TypeFnAttrDef(default=TypeFn.cast_signed)): |
| # """Title. |
| |
| # Detailed description. |
| # """ |
| # O[D.m, D.n] = cast(T, const(42)) + cast(T, index(D.n)) |
| |
| --- !LinalgOpConfig |
| metadata: !LinalgOpMetadata |
| name: test1 |
| cpp_class_name: Test1Op |
| doc: |- |
| Title. |
| |
| Detailed description. |
| structured_op: !LinalgStructuredOpConfig |
| args: |
| - !LinalgOperandDefConfig |
| name: O |
| kind: output_tensor |
| type_var: T |
| shape_map: affine_map<()[s0, s1] -> (s0, s1)> |
| - !LinalgOperandDefConfig |
| name: cast |
| kind: type_fn_attr |
| default_fn: cast_signed |
| indexing_maps: !LinalgIndexingMapsConfig |
| static_indexing_maps: |
| - affine_map<(d0, d1)[s0, s1] -> (d0, d1)> |
| iterator_types: |
| - parallel |
| - parallel |
| assignments: |
| - !ScalarAssign |
| arg: O |
| value: !ScalarExpression |
| scalar_fn: |
| kind: binary |
| fn_name: add |
| operands: |
| - !ScalarExpression |
| scalar_fn: |
| kind: type |
| attr_name: cast |
| type_var: T |
| operands: |
| - !ScalarExpression |
| scalar_const: '42 : i64' |
| - !ScalarExpression |
| scalar_fn: |
| kind: type |
| attr_name: cast |
| type_var: T |
| operands: |
| - !ScalarExpression |
| scalar_index: 1 |
| |
| # ODS-LABEL: def Test1Op : LinalgStructuredBase_Op<"test1" |
| |
| # ODS: let summary = [{Title.}]; |
| # ODS-NEXT: let description = [{Detailed description.}]; |
| |
| # ODS: let arguments = |
| # ODS-NEXT: Variadic<AnyType>:$inputs, |
| # ODS-NEXT: Variadic<AnyShaped>:$outputs, |
| # ODS-NEXT: DefaultValuedOptionalAttr<TypeFnAttr, "TypeFn::cast_signed">:$cast |
| |
| # ODS: let builders = |
| # ODS: (ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, |
| # ODS-NEXT: "ValueRange":$outputs, |
| # ODS-NEXT: CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes), |
| |
| # ODS: (ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, |
| # ODS-NEXT: "ValueRange":$outputs, "Attribute":$cast, |
| # ODS-NEXT: CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes), |
| |
| # ODS: buildStructuredOp($_builder, $_state, resultTensorTypes, |
| # ODS-NEXT: attributes, Test1Op::getRegionBuilder()) |
| |
| # ODS: MutableOperandRange getDpsInitsMutable() { |
| # ODS-NEXT: return getOutputsMutable() |
| # ODS-NEXT: } |
| |
| # IMPL-LABEL: void Test1Op::regionBuilder(ImplicitLocOpBuilder &b, |
| # IMPL-NEXT: Block &block, ArrayRef<NamedAttribute> attrs) |
| # IMPL: TypeFn castVal = TypeFn::cast_signed; |
| # IMPL-NEXT: auto castIter = llvm::find_if(attrs, [&](const NamedAttribute &attr) { |
| # IMPL-NEXT: return attr.getName() == "cast"; }); |
| # IMPL-NEXT: if (castIter != attrs.end()) { |
| # IMPL-NEXT: if (auto attr = llvm::dyn_cast<TypeFnAttr>(castIter->getValue())) |
| # IMPL-NEXT: castVal = attr.getValue(); |
| # IMPL-NEXT: } |
| |
| # IMPL: Value [[VAL0:[a-z0-9]+]] = helper.constant("42 : i64"); |
| # IMPL-DAG: Value [[VAL1:[a-z0-9]+]] = helper.buildTypeFn(castVal, block.getArgument(0).getType(), [[VAL0]]); |
| # IMPL-DAG: Value [[VAL2:[a-z0-9]+]] = helper.index(1); |
| # IMPL-DAG: Value [[VAL3:[a-z0-9]+]] = helper.buildTypeFn(castVal, block.getArgument(0).getType(), [[VAL2]]); |
| # IMPL-DAG: Value [[VAL4:[a-z0-9]+]] = helper.buildBinaryFn(BinaryFn::add, [[VAL1]], [[VAL3]]); |
| |
| |
| # @linalg_structured_op |
| # def test2(I=TensorDef(T, S.M, S.N), |
| # O=TensorDef(T, S.M, S.N, output=True), |
| # strides=IndexAttrDef(S.SM, S.SN, default=[1, 2])): |
| # """Title. |
| |
| # Detailed description. |
| # """ |
| # O[D.m, D.n] = I[D.n * S.SM, D.m * S.SN] |
| |
| --- !LinalgOpConfig |
| metadata: !LinalgOpMetadata |
| name: test2 |
| cpp_class_name: Test2Op |
| doc: |- |
| Title. |
| |
| Detailed description. |
| structured_op: !LinalgStructuredOpConfig |
| args: |
| - !LinalgOperandDefConfig |
| name: I |
| kind: input_tensor |
| type_var: T |
| shape_map: affine_map<()[s0, s1, s2, s3] -> (s0, s1)> |
| - !LinalgOperandDefConfig |
| name: O |
| kind: output_tensor |
| type_var: T |
| shape_map: affine_map<()[s0, s1, s2, s3] -> (s0, s1)> |
| - !LinalgOperandDefConfig |
| name: strides |
| kind: index_attr |
| index_attr_map: affine_map<()[s0, s1, s2, s3] -> (s2, s3)> |
| default_indices: |
| - 1 |
| - 2 |
| indexing_maps: !LinalgIndexingMapsConfig |
| static_indexing_maps: |
| - affine_map<(d0, d1)[s0, s1, s2, s3] -> (d1 * s2, d0 * s3)> |
| - affine_map<(d0, d1)[s0, s1, s2, s3] -> (d0, d1)> |
| iterator_types: |
| - parallel |
| - parallel |
| assignments: |
| - !ScalarAssign |
| arg: O |
| value: !ScalarExpression |
| scalar_arg: I |
| |
| # ODS-LABEL: def Test2Op : LinalgStructuredBase_Op<"test2" |
| |
| # ODS: let arguments = |
| # ODS-NEXT: Variadic<AnyType>:$inputs, |
| # ODS-NEXT: Variadic<AnyShaped>:$outputs, |
| # ODS-NEXT: DefaultValuedOptionalAttr<RankedI64ElementsAttr<[2]> |
| # ODS-SAME: "{ static_cast<int64_t>(1), static_cast<int64_t>(2) }">:$strides |
| |
| # ODS: "Attribute":$strides |
| # ODS: $_state.addAttribute("strides", strides); |
| |
| # ODS: bool hasDynamicIndexingMaps(); |
| # ODS-NEXT: LogicalResult verifyIndexingMapRequiredAttributes(); |
| |
| # IMPL: getSymbolBindings(Test2Op self) |
| # IMPL: cst2 = self.getStrides().getValues<int64_t>()[0]; |
| # IMPL-NEXT: getAffineConstantExpr(cst2, context) |
| # IMPL: cst3 = self.getStrides().getValues<int64_t>()[1]; |
| # IMPL-NEXT: getAffineConstantExpr(cst3, context) |
| |
| # IMPL: Test2Op::getIndexingMaps() |
| # IMPL: = getSymbolBindings(*this); |
| # IMPL: "affine_map<(d0, d1)[s0, s1, s2, s3] -> (d1 * s2, d0 * s3)>" |
| # IMPL: "affine_map<(d0, d1)[s0, s1, s2, s3] -> (d0, d1)>" |
| |
| # IMPL: Test2Op::getNumRegionArgs() { return 2; } |
| |
| # IMPL: Test2Op::hasDynamicIndexingMaps() { return true; } |
| # IMPL: Test2Op::verifyIndexingMapRequiredAttributes() |
| # IMPL: auto attr = op->getAttrOfType<DenseElementsAttr>("strides") |
| # IMPL: "incorrect element type for index attribute 'strides'" |
| # IMPL: "incorrect shape for index attribute 'strides'" |
| # IMPL: void Test2Op::regionBuilder(ImplicitLocOpBuilder &b, |
| # IMPL-NEXT: Block &block, ArrayRef<NamedAttribute> attrs) |
| # IMPL-NEXT: assert(2 > 0 && block.getNumArguments() == 2 && |
| |
| # IMPL: yields.push_back(block.getArgument(0)); |
| |
| # @linalg_structured_op |
| # def test3(value=ScalarDef(T1), |
| # O=TensorDef(U, output=True)): |
| # """Title. |
| |
| # Detailed description. |
| # """ |
| # O[None] = TypeFn.cast_signed(U, value) |
| |
| --- !LinalgOpConfig |
| metadata: !LinalgOpMetadata |
| name: test3 |
| cpp_class_name: Test3Op |
| doc: |- |
| Title. |
| |
| Detailed description. |
| structured_op: !LinalgStructuredOpConfig |
| args: |
| - !LinalgOperandDefConfig |
| name: value |
| kind: scalar |
| type_var: T1 |
| - !LinalgOperandDefConfig |
| name: O |
| kind: output_tensor |
| type_var: U |
| shape_map: affine_map<() -> ()> |
| indexing_maps: !LinalgIndexingMapsConfig |
| static_indexing_maps: |
| - affine_map<() -> ()> |
| - affine_map<() -> ()> |
| iterator_types: [] |
| assignments: |
| - !ScalarAssign |
| arg: O |
| value: !ScalarExpression |
| scalar_fn: |
| kind: type |
| fn_name: cast_signed |
| type_var: U |
| operands: |
| - !ScalarExpression |
| scalar_arg: value |
| |
| # IMPL: Test3Op::getIteratorTypesArray() { |
| # IMPL-NEXT: int64_t rank = getRank(getDpsInitOperand(0)); |
| |
| # IMPL: Test3Op::getIndexingMaps() { |
| # IMPL-NEXT: MLIRContext *context = getContext(); |
| # IMPL-NEXT: AffineMap scalarMap = AffineMap::get(getNumParallelLoops(), 0, context); |
| # IMPL-NEXT: AffineMap tensorMap = AffineMap::getMultiDimIdentityMap( |
| |
| # @linalg_structured_op |
| # def test4(O=TensorDef(T, S.M, S.N, output=True), |
| # unary_fun=UnaryFnAttrDef(default=UnaryFn.exp), |
| # binary_fun=BinaryFnAttrDef(default=BinaryFn.add)): |
| # """Title. |
| |
| # Detailed description. |
| # """ |
| # O[D.m, D.n] = binary_fun(unary_fun(O[D.m, D.n]), O[D.m, D.n]) |
| |
| --- !LinalgOpConfig |
| metadata: !LinalgOpMetadata |
| name: test4 |
| cpp_class_name: Test4Op |
| doc: |- |
| Title. |
| |
| Detailed description. |
| structured_op: !LinalgStructuredOpConfig |
| args: |
| - !LinalgOperandDefConfig |
| name: O |
| kind: output_tensor |
| type_var: T |
| shape_map: affine_map<()[s0, s1] -> (s0, s1)> |
| - !LinalgOperandDefConfig |
| name: unary_fun |
| kind: unary_fn_attr |
| default_fn: exp |
| - !LinalgOperandDefConfig |
| name: binary_fun |
| kind: binary_fn_attr |
| default_fn: add |
| indexing_maps: !LinalgIndexingMapsConfig |
| static_indexing_maps: |
| - affine_map<(d0, d1)[s0, s1] -> (d0, d1)> |
| iterator_types: |
| - parallel |
| - parallel |
| assignments: |
| - !ScalarAssign |
| arg: O |
| value: !ScalarExpression |
| scalar_fn: |
| kind: binary |
| attr_name: binary_fun |
| operands: |
| - !ScalarExpression |
| scalar_fn: |
| kind: unary |
| attr_name: unary_fun |
| operands: |
| - !ScalarExpression |
| scalar_arg: O |
| - !ScalarExpression |
| scalar_arg: O |
| |
| # ODS-LABEL: def Test4Op : LinalgStructuredBase_Op<"test4" |
| |
| # ODS: let arguments = |
| # ODS-NEXT: Variadic<AnyType>:$inputs, |
| # ODS-NEXT: Variadic<AnyShaped>:$outputs, |
| # ODS-NEXT: DefaultValuedOptionalAttr<UnaryFnAttr, "UnaryFn::exp">:$unary_fun, |
| # ODS-NEXT: DefaultValuedOptionalAttr<BinaryFnAttr, "BinaryFn::add">:$binary_fun |
| |
| # ODS: "Attribute":$unary_fun, "Attribute":$binary_fun, |
| |
| # ODS: $_state.addAttribute("unary_fun", unary_fun) |
| # ODS-NEXT: $_state.addAttribute("binary_fun", binary_fun) |
| |
| # IMPL-LABEL: void Test4Op::regionBuilder(ImplicitLocOpBuilder &b, |
| # IMPL-NEXT: Block &block, ArrayRef<NamedAttribute> attrs) |
| # IMPL: UnaryFn unary_funVal = UnaryFn::exp |
| # IMPL: BinaryFn binary_funVal = BinaryFn::add |
| |
| # IMPL: Value [[VAL0:[a-z0-9]+]] = helper.buildUnaryFn(unary_funVal, block.getArgument(0)) |
| # IMPL-NEXT: Value [[VAL1:[a-z0-9]+]] = helper.buildBinaryFn(binary_funVal, [[VAL0]], block.getArgument(0)) |
| # IMPL-NEXT: yields.push_back([[VAL1]]) |
| |
| # @linalg_structured_op |
| # def test5(value=ScalarDef(T1), O=TensorDef(U, output=True)): |
| # """Title. |
| |
| # Detailed description. |
| # """ |
| # implements(FillOpInterface) |
| # defines(Canonicalizer) |
| # O[None] = TypeFn.cast(U, value) |
| |
| --- !LinalgOpConfig |
| metadata: !LinalgOpMetadata |
| name: test5 |
| cpp_class_name: Test5Op |
| doc: |- |
| Title. |
| |
| Detailed description. |
| implements: |
| - LinalgFillOpInterface |
| defines: |
| - hasCanonicalizer |
| structured_op: !LinalgStructuredOpConfig |
| args: |
| - !LinalgOperandDefConfig |
| name: value |
| kind: scalar |
| type_var: T1 |
| - !LinalgOperandDefConfig |
| name: O |
| kind: output_tensor |
| type_var: U |
| shape_map: affine_map<() -> ()> |
| indexing_maps: !LinalgIndexingMapsConfig |
| static_indexing_maps: |
| - affine_map<() -> ()> |
| - affine_map<() -> ()> |
| iterator_types: [] |
| assignments: |
| - !ScalarAssign |
| arg: O |
| value: !ScalarExpression |
| scalar_fn: |
| kind: type |
| fn_name: cast |
| type_var: U |
| operands: |
| - !ScalarExpression |
| scalar_arg: value |
| |
| # ODS-LABEL: def Test5Op : LinalgStructuredBase_Op<"test5" |
| # ODS-NEXT: /*extraInterfaces=*/[LinalgFillOpInterface])> |
| |
| # ODS: let hasCanonicalizer = 1; |