# 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:$inputs, # ODS-NEXT: Variadic:$outputs, # ODS-NEXT: DefaultValuedOptionalAttr:$cast # ODS: let builders = # ODS: (ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, # ODS-NEXT: "ValueRange":$outputs, # ODS-NEXT: CArg<"ArrayRef", "{}">:$attributes), # ODS: (ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs, # ODS-NEXT: "ValueRange":$outputs, "Attribute":$cast, # ODS-NEXT: CArg<"ArrayRef", "{}">:$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 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(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:$inputs, # ODS-NEXT: Variadic:$outputs, # ODS-NEXT: DefaultValuedOptionalAttr # ODS-SAME: "{ static_cast(1), static_cast(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()[0]; # IMPL-NEXT: getAffineConstantExpr(cst2, context) # IMPL: cst3 = self.getStrides().getValues()[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("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 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:$inputs, # ODS-NEXT: Variadic:$outputs, # ODS-NEXT: DefaultValuedOptionalAttr:$unary_fun, # ODS-NEXT: DefaultValuedOptionalAttr:$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 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;