3919 lines · plain
1//===-- TestOps.td - Test dialect operation definitions ----*- tablegen -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef TEST_OPS10#define TEST_OPS11 12include "TestDialect.td"13include "TestInterfaces.td"14include "mlir/Dialect/DLTI/DLTIBase.td"15include "mlir/Dialect/Linalg/IR/LinalgInterfaces.td"16include "mlir/Dialect/LLVMIR/NVVMRequiresSMTraits.td"17include "mlir/IR/EnumAttr.td"18include "mlir/Interfaces/FunctionInterfaces.td"19include "mlir/IR/OpBase.td"20include "mlir/IR/OpAsmInterface.td"21include "mlir/IR/PatternBase.td"22include "mlir/IR/RegionKindInterface.td"23include "mlir/IR/SymbolInterfaces.td"24include "mlir/Interfaces/CallInterfaces.td"25include "mlir/Interfaces/ControlFlowInterfaces.td"26include "mlir/Interfaces/DataLayoutInterfaces.td"27include "mlir/Interfaces/DestinationStyleOpInterface.td"28include "mlir/Interfaces/InferIntRangeInterface.td"29include "mlir/Interfaces/InferTypeOpInterface.td"30include "mlir/Interfaces/LoopLikeInterface.td"31include "mlir/Interfaces/MemorySlotInterfaces.td"32include "mlir/Interfaces/SideEffectInterfaces.td"33include "mlir/Interfaces/TilingInterface.td"34include "mlir/Interfaces/ValueBoundsOpInterface.td"35include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td"36include "mlir/Dialect/Bufferization/IR/BufferizationTypeInterfaces.td"37 38// Include the attribute definitions.39include "TestAttrDefs.td"40// Include the type definitions.41include "TestTypeDefs.td"42 43 44class TEST_Op<string mnemonic, list<Trait> traits = []> :45 Op<Test_Dialect, mnemonic, traits>;46 47//===----------------------------------------------------------------------===//48// Test Types49//===----------------------------------------------------------------------===//50 51def IntTypesOp : TEST_Op<"int_types"> {52 let results = (outs53 AnyI16:$any_i16,54 SI32:$si32,55 UI64:$ui64,56 AnyInteger:$any_int57 );58}59 60def ComplexF64 : Complex<F64>;61def ComplexOp : TEST_Op<"complex_f64"> {62 let results = (outs ComplexF64);63}64 65def ComplexTensorOp : TEST_Op<"complex_f64_tensor"> {66 let results = (outs TensorOf<[ComplexF64]>);67}68 69def TupleOp : TEST_Op<"tuple_32_bit"> {70 let results = (outs TupleOf<[I32, F32]>);71}72 73def NestedTupleOp : TEST_Op<"nested_tuple_32_bit"> {74 let results = (outs NestedTupleOf<[I32, F32]>);75}76 77def TakesStaticMemRefOp : TEST_Op<"takes_static_memref"> {78 let arguments = (ins AnyStaticShapeMemRef:$x);79}80 81def RankLessThan2I8F32MemRefOp : TEST_Op<"rank_less_than_2_I8_F32_memref"> {82 let results = (outs MemRefRankOf<[I8, F32], [0, 1]>);83}84 85def NDTensorOfOp : TEST_Op<"nd_tensor_of"> {86 let arguments = (ins87 0DTensorOf<[F32]>:$arg0,88 1DTensorOf<[F32]>:$arg1,89 2DTensorOf<[I16]>:$arg2,90 3DTensorOf<[I16]>:$arg3,91 4DTensorOf<[I16]>:$arg492 );93}94 95def RankedTensorOp : TEST_Op<"ranked_tensor_op"> {96 let arguments = (ins AnyRankedTensor:$input);97}98 99def MultiTensorRankOf : TEST_Op<"multi_tensor_rank_of"> {100 let arguments = (ins101 TensorRankOf<[I8, I32, F32], [0, 1]>:$arg0102 );103}104 105def TEST_TestType : DialectType<Test_Dialect,106 CPred<"::llvm::isa<::test::TestType>($_self)">, "test">,107 BuildableType<"$_builder.getType<::test::TestType>()">;108 109def SignlessLikeVariadic : TEST_Op<"signless_like_variadic"> {110 let arguments = (ins Variadic<SignlessIntegerLike>:$x);111}112 113//===----------------------------------------------------------------------===//114// Test Symbols115//===----------------------------------------------------------------------===//116 117def SymbolOp : TEST_Op<"symbol", [NoMemoryEffect, Symbol]> {118 let summary = "operation which defines a new symbol";119 let arguments = (ins StrAttr:$sym_name,120 OptionalAttr<StrAttr>:$sym_visibility);121}122 123def SymbolWithResultOp : TEST_Op<"symbol_with_result", [Symbol]> {124 let summary = "invalid symbol operation that produces an SSA result";125 let arguments = (ins StrAttr:$sym_name,126 OptionalAttr<StrAttr>:$sym_visibility);127 let results = (outs AnyType:$result);128}129 130def OverriddenSymbolVisibilityOp : TEST_Op<"overridden_symbol_visibility", [131 DeclareOpInterfaceMethods<Symbol, ["getVisibility", "setVisibility"]>,132]> {133 let summary = "operation overridden symbol visibility accessors";134 let arguments = (ins StrAttr:$sym_name);135}136 137def SymbolScopeOp : TEST_Op<"symbol_scope",138 [SymbolTable, SingleBlockImplicitTerminator<"TerminatorOp">]> {139 let summary = "operation which defines a new symbol table";140 let regions = (region SizedRegion<1>:$region);141}142 143def SymbolScopeIsolatedOp144 : TEST_Op<"symbol_scope_isolated", [IsolatedFromAbove, SymbolTable,145 SingleBlockImplicitTerminator<146 "TerminatorOp">]> {147 let summary =148 "operation which defines a new symbol table that is IsolatedFromAbove";149 let regions = (region SizedRegion<1>:$region);150}151 152def SymbolTableRegionOp : TEST_Op<"symbol_table_region", [SymbolTable]> {153 let summary = "operation which defines a new symbol table without a "154 "restriction on a terminator";155 let regions = (region SizedRegion<1>:$region);156}157 158//===----------------------------------------------------------------------===//159// Test Operands160//===----------------------------------------------------------------------===//161 162def MixedNormalVariadicOperandOp : TEST_Op<163 "mixed_normal_variadic_operand", [SameVariadicOperandSize]> {164 let arguments = (ins165 Variadic<AnyTensor>:$input1,166 AnyTensor:$input2,167 Variadic<AnyTensor>:$input3168 );169}170def VariadicWithSameOperandsResult :171 TEST_Op<"variadic_with_same_operand_results",172 [SameOperandsAndResultType]> {173 let arguments = (ins Variadic<AnySignlessInteger>);174 let results = (outs AnySignlessInteger:$result);175}176 177def SameOperandsResultType : TEST_Op<178 "same_operand_result_type", [SameOperandsAndResultType]> {179 let arguments = (ins AnyTensor:$operand);180 let results = (outs AnyTensor:$result);181}182 183//===----------------------------------------------------------------------===//184// Test Results185//===----------------------------------------------------------------------===//186 187def MixedNormalVariadicResults : TEST_Op<188 "mixed_normal_variadic_result", [SameVariadicResultSize]> {189 let results = (outs190 Variadic<AnyTensor>:$output1,191 AnyTensor:$output2,192 Variadic<AnyTensor>:$output3193 );194}195 196//===----------------------------------------------------------------------===//197// Test Attributes198//===----------------------------------------------------------------------===//199 200def AnyAttrOfOp : TEST_Op<"any_attr_of_i32_str"> {201 let arguments = (ins AnyAttrOf<[I32Attr, StrAttr]>:$attr);202}203 204def NonNegIntAttrOp : TEST_Op<"non_negative_int_attr"> {205 let arguments = (ins206 ConfinedAttr<I32Attr, [IntNonNegative]>:$i32attr,207 ConfinedAttr<I64Attr, [IntNonNegative]>:$i64attr208 );209}210 211def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> {212 let arguments = (ins213 ConfinedAttr<I32Attr, [IntPositive]>:$i32attr,214 ConfinedAttr<I64Attr, [IntPositive]>:$i64attr215 );216}217 218def TypeArrayAttrOp : TEST_Op<"type_array_attr"> {219 let arguments = (ins TypeArrayAttr:$attr);220}221 222def TypeArrayAttrWithDefaultOp : TEST_Op<"type_array_attr_with_default"> {223 let arguments = (ins DefaultValuedAttr<TypeArrayAttr, "{}">:$attr);224}225 226def TypedStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> {227 let arguments = (ins TypedStrAttr<AnyInteger>:$attr);228 let assemblyFormat = "$attr attr-dict";229}230 231def TypedStringAttrWithMixedTypeOp : TEST_Op<"string_attr_with_mixed_type"> {232 let arguments = (ins233 AnyAttrOf<[TypedStrAttr<AnyInteger>, I64Attr]>:$attr234 );235 let assemblyFormat = "$attr attr-dict";236}237 238def FloatAttrOp : TEST_Op<"float_attrs"> {239 // TODO: Clean up the OpBase float type and attribute selectors so they240 // can express all of the types.241 let arguments = (ins242 AnyAttr:$float_attr243 );244}245 246def I32EnumAttrOp : TEST_Op<"i32_enum_attr"> {247 let arguments = (ins SomeI32Enum:$attr);248 let results = (outs I32:$val);249}250 251def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> {252 let arguments = (ins SomeI64Enum:$attr);253 let results = (outs I32:$val);254}255 256def IntAttrOp : TEST_Op<"int_attrs"> {257 let arguments = (ins258 AnyI32Attr:$any_i32_attr,259 IndexAttr:$index_attr,260 UI32Attr:$ui32_attr,261 SI32Attr:$si32_attr262 );263}264 265def FloatElementsAttrOp : TEST_Op<"float_elements_attr"> {266 let arguments = (ins267 RankedF32ElementsAttr<[2]>:$scalar_f32_attr,268 RankedF64ElementsAttr<[4, 8]>:$tensor_f64_attr269 );270}271 272// A pattern that updates dense<[3.0, 4.0]> to dense<[5.0, 6.0]>.273// This tests both matching and generating float elements attributes.274def UpdateFloatElementsAttr : Pat<275 (FloatElementsAttrOp276 ConstantAttr<RankedF32ElementsAttr<[2]>, "{3.0f, 4.0f}">:$f32attr,277 $f64attr),278 (FloatElementsAttrOp279 ConstantAttr<RankedF32ElementsAttr<[2]>, "{5.0f, 6.0f}">:$f32attr,280 $f64attr)>;281 282def IntElementsAttrOp : TEST_Op<"int_elements_attr"> {283 let arguments = (ins284 AnyI32ElementsAttr:$any_i32_attr,285 I32ElementsAttr:$i32_attr286 );287}288 289def RankedIntElementsAttrOp : TEST_Op<"ranked_int_elements_attr"> {290 let arguments = (ins291 RankedI32ElementsAttr<[2]>:$vector_i32_attr,292 RankedI64ElementsAttr<[4, 8]>:$matrix_i64_attr293 );294}295 296def DerivedTypeAttrOp : TEST_Op<"derived_type_attr", []> {297 let results = (outs AnyTensor:$output);298 DerivedTypeAttr element_dtype =299 DerivedTypeAttr<"return getElementTypeOrSelf(getOutput().getType());">;300 DerivedAttr num_elements = DerivedAttr<"int",301 "return ::llvm::cast<ShapedType>(getOutput().getType()).getNumElements();",302 "$_builder.getI32IntegerAttr($_self)">;303}304 305def TestPropOp : TEST_Op<"prop">,306 Arguments<(ins Variadic<Index>:$upperInits,307 I32ElementsAttr:$transforms)>,308 Results<(outs Variadic<AnyType>:$results)> {309 DerivedAttr upperLen = DerivedAttr<"uint32_t", [{310 return getUpperInits().size() / getTransforms().size();311 }], [{ $_builder.getI32IntegerAttr($_self) }]>;312}313 314 315def StringElementsAttrOp : TEST_Op<"string_elements_attr"> {316 let arguments = (ins317 StringElementsAttr:$scalar_string_attr318 );319}320 321def TypedAttrOp : TEST_Op<"typed_attr"> {322 let arguments = (ins TypeAttr:$type, AnyAttr:$attr);323 let assemblyFormat = [{324 attr-dict $type `=` custom<AttrElideType>(ref($type), $attr)325 }];326}327 328def TypeAttrOfOp : TEST_Op<"type_attr_of"> {329 let arguments = (ins TypeAttrOf<I64>:$type);330 let assemblyFormat = [{331 attr-dict $type332 }];333}334 335def DenseArrayAttrOp : TEST_Op<"dense_array_attr"> {336 let arguments = (ins337 DenseBoolArrayAttr:$i1attr,338 DenseI8ArrayAttr:$i8attr,339 DenseI16ArrayAttr:$i16attr,340 DenseI32ArrayAttr:$i32attr,341 DenseI64ArrayAttr:$i64attr,342 DenseF32ArrayAttr:$f32attr,343 DenseF64ArrayAttr:$f64attr,344 DenseI32ArrayAttr:$emptyattr345 );346 let assemblyFormat = [{347 `i1attr` `=` $i1attr `i8attr` `=` $i8attr `i16attr` `=` $i16attr348 `i32attr` `=` $i32attr `i64attr` `=` $i64attr `f32attr` `=` $f32attr349 `f64attr` `=` $f64attr `emptyattr` `=` $emptyattr attr-dict350 }];351}352 353def SlashAttrOp : TEST_Op<"slash_attr"> {354 let arguments = (ins SlashAttr:$attr);355}356 357//===----------------------------------------------------------------------===//358// Test Attributes Constraints359//===----------------------------------------------------------------------===//360 361def ConfinedDenseArrayAttrOp : TEST_Op<"confined_dense_array_attr"> {362 let arguments = (ins363 ConfinedAttr<DenseI16ArrayAttr,364 [DenseArrayStrictlySorted<DenseI16ArrayAttr>]>:$emptyattr,365 ConfinedAttr<DenseI32ArrayAttr,366 [DenseArraySorted<DenseI32ArrayAttr>]>:$i32attr,367 ConfinedAttr<DenseI64ArrayAttr,368 [DenseArrayStrictlySorted<DenseI64ArrayAttr>]>:$i64attr369 );370}371 372// It does not make sense to have this constraint on a DenseBoolArrayAttr.373def DenseArrayStrictlyPositiveAttrOp : TEST_Op<"confined_strictly_positive_attr"> {374 let arguments = (ins375 ConfinedAttr<DenseI8ArrayAttr,376 [DenseArrayStrictlyPositive<DenseI8ArrayAttr>]>:$i8attr,377 ConfinedAttr<DenseI16ArrayAttr,378 [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>:$i16attr,379 ConfinedAttr<DenseI32ArrayAttr,380 [DenseArrayStrictlyPositive<DenseI32ArrayAttr>]>:$i32attr,381 ConfinedAttr<DenseI64ArrayAttr,382 [DenseArrayStrictlyPositive<DenseI64ArrayAttr>]>:$i64attr,383 ConfinedAttr<DenseF32ArrayAttr,384 [DenseArrayStrictlyPositive<DenseF32ArrayAttr>]>:$f32attr,385 ConfinedAttr<DenseF64ArrayAttr,386 [DenseArrayStrictlyPositive<DenseF64ArrayAttr>]>:$f64attr,387 ConfinedAttr<DenseI16ArrayAttr,388 [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>:$emptyattr389 );390}391 392// It does not make sense to have this constraint on a DenseBoolArrayAttr.393// It is always true.394def DenseArrayNonNegativeOp : TEST_Op<"confined_non_negative_attr"> {395 let arguments = (ins396 ConfinedAttr<DenseI8ArrayAttr,397 [DenseArrayNonNegative<DenseI8ArrayAttr>]>:$i8attr,398 ConfinedAttr<DenseI16ArrayAttr,399 [DenseArrayNonNegative<DenseI16ArrayAttr>]>:$i16attr,400 ConfinedAttr<DenseI32ArrayAttr,401 [DenseArrayNonNegative<DenseI32ArrayAttr>]>:$i32attr,402 ConfinedAttr<DenseI64ArrayAttr,403 [DenseArrayNonNegative<DenseI64ArrayAttr>]>:$i64attr,404 ConfinedAttr<DenseF32ArrayAttr,405 [DenseArrayNonNegative<DenseF32ArrayAttr>]>:$f32attr,406 ConfinedAttr<DenseF64ArrayAttr,407 [DenseArrayNonNegative<DenseF64ArrayAttr>]>:$f64attr,408 ConfinedAttr<DenseI16ArrayAttr,409 [DenseArrayNonNegative<DenseI16ArrayAttr>]>:$emptyattr410 );411}412 413//===----------------------------------------------------------------------===//414// Test Promised Interfaces Constraints415//===----------------------------------------------------------------------===//416 417def PromisedInterfacesOp : TEST_Op<"promised_interfaces"> {418 let arguments = (ins419 ConfinedAttr<AnyAttr,420 [PromisedAttrInterface<TestExternalAttrInterface>]>:$promisedAttr,421 ConfinedType<AnyType,422 [HasPromiseOrImplementsTypeInterface<TestExternalTypeInterface>]423 >:$promisedType424 );425}426 427//===----------------------------------------------------------------------===//428// Test Enum Attributes429//===----------------------------------------------------------------------===//430 431// Define the enum attribute.432def TestEnumAttr : EnumAttr<Test_Dialect, TestEnum, "enum">;433 434// Define an op that contains the enum attribute.435def OpWithEnum : TEST_Op<"op_with_enum"> {436 let arguments = (ins TestEnumAttr:$value, OptionalAttr<AnyAttr>:$tag);437 let assemblyFormat = "$value (`tag` $tag^)? attr-dict";438}439 440// Define a pattern that matches and creates an enum attribute.441def : Pat<(OpWithEnum ConstantEnumCase<TestEnumAttr, "first">:$value,442 ConstantAttr<I32Attr, "0">:$tag),443 (OpWithEnum ConstantEnumCase<TestEnumAttr, "second">,444 ConstantAttr<I32Attr, "1">)>;445 446//===----------------------------------------------------------------------===//447// Test Enum Properties448//===----------------------------------------------------------------------===//449 450// Define the enum property.451def TestEnumProp : EnumProp<TestEnum>;452// Define an op that contains the enum property.453def OpWithEnumProp : TEST_Op<"op_with_enum_prop"> {454 let arguments = (ins TestEnumProp:$value);455 let assemblyFormat = "$value attr-dict";456}457 458def TestEnumPropAttrForm : EnumPropWithAttrForm<TestEnum, TestEnumAttr>;459def OpWithEnumPropAttrForm : TEST_Op<"op_with_enum_prop_attr_form"> {460 let arguments = (ins TestEnumPropAttrForm:$value);461 let assemblyFormat = "prop-dict attr-dict";462}463 464def TestEnumPropAttrFormAlways : EnumPropWithAttrForm<TestEnum, TestEnumAttr> {465 let storeInCustomAttribute = 1;466}467def OpWithEnumPropAttrFormAlways : TEST_Op<"op_with_enum_prop_attr_form_always"> {468 let arguments = (ins TestEnumPropAttrFormAlways:$value);469 let assemblyFormat = "prop-dict attr-dict";470}471 472def TestBitEnumProp : EnumProp<TestBitEnum> {473 let defaultValue = TestBitEnum.cppType # "::Read";474}475def OpWithTestBitEnum : TEST_Op<"op_with_bit_enum_prop"> {476 let arguments = (ins477 TestBitEnumProp:$value1,478 TestBitEnumProp:$value2);479 let assemblyFormat = "$value1 ($value2^)? attr-dict `:` `(``)`";480}481 482def TestBitEnumPropNamed : NamedEnumProp<TestBitEnum, "bit_enum"> {483 let defaultValue = TestBitEnum.cppType # "::Read";484}485def OpWithBitEnumPropNamed : TEST_Op<"op_with_bit_enum_prop_named"> {486 let arguments = (ins487 TestBitEnumPropNamed:$value1,488 TestBitEnumPropNamed:$value2);489 let assemblyFormat = "$value1 ($value2^)? attr-dict";490}491 492//===----------------------------------------------------------------------===//493// Test Bit Enum Attributes494//===----------------------------------------------------------------------===//495 496// Define the enum attribute.497def TestBitEnumAttr : EnumAttr<Test_Dialect, TestBitEnum, "bit_enum"> {498 let assemblyFormat = "`<` $value `>`";499}500 501// Define an op that contains the enum attribute.502def OpWithBitEnum : TEST_Op<"op_with_bit_enum"> {503 let arguments = (ins TestBitEnumAttr:$value, OptionalAttr<AnyAttr>:$tag);504 let assemblyFormat = "$value (`tag` $tag^)? attr-dict";505}506 507def TestBitEnumVerticalBarAttr508 : EnumAttr<Test_Dialect, TestBitEnumVerticalBar, "bit_enum_vbar"> {509 let assemblyFormat = "`<` $value `>`";510}511 512// Define an op that contains the enum attribute.513def OpWithBitEnumVerticalBar : TEST_Op<"op_with_bit_enum_vbar"> {514 let arguments = (ins TestBitEnumVerticalBarAttr:$value,515 OptionalAttr<AnyAttr>:$tag);516 let assemblyFormat = "$value (`tag` $tag^)? attr-dict";517}518 519// Define a pattern that matches and creates a bit enum attribute.520def : Pat<(OpWithBitEnum ConstantEnumCase<TestBitEnumAttr, "write|execute">,521 ConstantAttr<I32Attr, "0">),522 (OpWithBitEnum ConstantEnumCase<TestBitEnumAttr, "execute|read">,523 ConstantAttr<I32Attr, "1">)>;524 525//===----------------------------------------------------------------------===//526// Test Regions527//===----------------------------------------------------------------------===//528 529def OneRegionOp : TEST_Op<"one_region_op", []> {530 let regions = (region AnyRegion);531}532 533def TwoRegionOp : TEST_Op<"two_region_op", []> {534 let regions = (region AnyRegion, AnyRegion);535}536 537def SizedRegionOp : TEST_Op<"sized_region_op", []> {538 let regions = (region SizedRegion<2>:$my_region, SizedRegion<1>);539}540 541def VariadicRegionInferredTypesOp : TEST_Op<"variadic_region_inferred",542 [InferTypeOpInterface]> {543 let regions = (region VariadicRegion<AnyRegion>:$bodies);544 let results = (outs Variadic<AnyType>);545 546 let extraClassDeclaration = [{547 static llvm::LogicalResult inferReturnTypes(mlir::MLIRContext *context,548 std::optional<::mlir::Location> location, mlir::ValueRange operands,549 mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, mlir::RegionRange regions,550 llvm::SmallVectorImpl<mlir::Type> &inferredReturnTypes) {551 inferredReturnTypes.assign({mlir::IntegerType::get(context, 16)});552 return mlir::success();553 }554 }];555}556 557def OneRegionWithOperandsOp : TEST_Op<"one_region_with_operands_op", []> {558 let arguments = (ins Variadic<AnyType>:$operands);559 let regions = (region AnyRegion);560}561 562def IsolatedOneRegionOp : TEST_Op<"isolated_one_region_op", [IsolatedFromAbove]> {563 let arguments = (ins Variadic<AnyType>:$operands);564 let results = (outs Variadic<AnyType>:$results);565 let regions = (region AnyRegion:$my_region);566 let assemblyFormat = [{567 attr-dict-with-keyword $operands $my_region `:` type($operands) `->` type($results)568 }];569}570 571def IsolatedRegionsOp : TEST_Op<"isolated_regions", [IsolatedFromAbove]> {572 let regions = (region VariadicRegion<AnyRegion>:$regions);573 let assemblyFormat = "attr-dict-with-keyword $regions";574}575 576def AllocaScopeRegionOp : TEST_Op<"alloca_scope_region",577 [AutomaticAllocationScope]> {578 let regions = (region AnyRegion:$region);579 let assemblyFormat = "attr-dict-with-keyword $region";580}581 582def OneRegionWithRecursiveMemoryEffectsOp583 : TEST_Op<"one_region_with_recursive_memory_effects", [584 RecursiveMemoryEffects]> {585 let description = [{586 Op that has one region and recursive side effects. The587 RegionBranchOpInterface is not implemented on this op.588 }];589 let results = (outs AnyType:$result);590 let regions = (region SizedRegion<1>:$body);591}592 593//===----------------------------------------------------------------------===//594// NoTerminator Operation595//===----------------------------------------------------------------------===//596 597def SingleNoTerminatorOp : TEST_Op<"single_no_terminator_op",598 GraphRegionNoTerminator.traits> {599 let regions = (region SizedRegion<1>:$my_region);600 601 let assemblyFormat = "attr-dict `:` $my_region";602}603 604def SingleNoTerminatorCustomAsmOp : TEST_Op<"single_no_terminator_custom_asm_op",605 [SingleBlock, NoTerminator]> {606 let regions = (region SizedRegion<1>);607 let hasCustomAssemblyFormat = 1;608}609 610def VariadicNoTerminatorOp : TEST_Op<"variadic_no_terminator_op",611 GraphRegionNoTerminator.traits> {612 let regions = (region VariadicRegion<SizedRegion<1>>:$my_regions);613 614 let assemblyFormat = "attr-dict `:` $my_regions";615}616 617//===----------------------------------------------------------------------===//618// Test Call Interfaces619//===----------------------------------------------------------------------===//620 621def TestCallOp : TEST_Op<"call", [DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {622 let arguments = (ins FlatSymbolRefAttr:$callee, Variadic<AnyType>:$operands);623 let results = (outs Variadic<AnyType>);624 let assemblyFormat = [{625 $callee `(` $operands `)` attr-dict `:` functional-type($operands, results)626 }];627}628 629def ConversionCallOp : TEST_Op<"conversion_call_op",630 [CallOpInterface]> {631 let arguments = (ins632 Variadic<AnyType>:$arg_operands,633 SymbolRefAttr:$callee,634 OptionalAttr<DictArrayAttr>:$arg_attrs,635 OptionalAttr<DictArrayAttr>:$res_attrs636 );637 let results = (outs Variadic<AnyType>);638 639 let extraClassDeclaration = [{640 /// Return the callee of this operation.641 ::mlir::CallInterfaceCallable getCallableForCallee();642 643 /// Set the callee for this operation.644 void setCalleeFromCallable(::mlir::CallInterfaceCallable);645 }];646 let extraClassDefinition = [{647 ::mlir::CallInterfaceCallable $cppClass::getCallableForCallee() {648 return (*this)->getAttrOfType<::mlir::SymbolRefAttr>("callee");649 }650 651 void $cppClass::setCalleeFromCallable(::mlir::CallInterfaceCallable callee) {652 (*this)->setAttr("callee", cast<SymbolRefAttr>(callee));653 }654 }];655}656 657def ConversionFuncOp : TEST_Op<"conversion_func_op", [FunctionOpInterface]> {658 let arguments = (ins SymbolNameAttr:$sym_name,659 TypeAttrOf<FunctionType>:$function_type,660 OptionalAttr<DictArrayAttr>:$arg_attrs,661 OptionalAttr<DictArrayAttr>:$res_attrs,662 OptionalAttr<StrAttr>:$sym_visibility);663 let regions = (region AnyRegion:$body);664 665 let extraClassDeclaration = [{666 //===------------------------------------------------------------------===//667 // FunctionOpInterface Methods668 //===------------------------------------------------------------------===//669 670 /// Returns the region on the current operation that is callable. This may671 /// return null in the case of an external callable object, e.g. an external672 /// function.673 ::mlir::Region *getCallableRegion() {674 return isExternal() ? nullptr : &getBody();675 }676 677 /// Returns the argument types of this async function.678 ::mlir::ArrayRef<::mlir::Type> getArgumentTypes() {679 return getFunctionType().getInputs();680 }681 682 /// Returns the result types of this async function.683 ::mlir::ArrayRef<::mlir::Type> getResultTypes() {684 return getFunctionType().getResults();685 }686 687 /// Returns the number of results of this async function688 unsigned getNumResults() {return getResultTypes().size();}689 }];690 691 let hasCustomAssemblyFormat = 1;692}693 694def FunctionalRegionOp : TEST_Op<"functional_region_op",695 [CallableOpInterface]> {696 let regions = (region AnyRegion:$body);697 let arguments = (ins698 OptionalAttr<DictArrayAttr>:$arg_attrs,699 OptionalAttr<DictArrayAttr>:$res_attrs700 );701 let results = (outs FunctionType);702 703 let extraClassDeclaration = [{704 ::mlir::Region *getCallableRegion() { return &getBody(); }705 ::llvm::ArrayRef<::mlir::Type> getResultTypes() {706 return ::llvm::cast<::mlir::FunctionType>(getType()).getResults();707 }708 ::llvm::ArrayRef<::mlir::Type> getArgumentTypes() {709 return ::llvm::cast<::mlir::FunctionType>(getType()).getInputs();710 }711 }];712}713 714 715def FoldToCallOp : TEST_Op<"fold_to_call_op"> {716 let arguments = (ins FlatSymbolRefAttr:$callee);717 let hasCanonicalizer = 1;718}719 720//===----------------------------------------------------------------------===//721// Test Traits722//===----------------------------------------------------------------------===//723 724def SameOperandElementTypeOp : TEST_Op<"same_operand_element_type",725 [SameOperandsElementType]> {726 let arguments = (ins AnyType, AnyType);727 let results = (outs AnyType);728}729 730def SameOperandAndResultElementTypeOp :731 TEST_Op<"same_operand_and_result_element_type",732 [SameOperandsAndResultElementType]> {733 let arguments = (ins Variadic<AnyType>);734 let results = (outs Variadic<AnyType>);735}736 737def SameOperandShapeOp : TEST_Op<"same_operand_shape", [SameOperandsShape]> {738 let arguments = (ins Variadic<AnyShaped>);739}740 741def SameOperandAndResultShapeOp : TEST_Op<"same_operand_and_result_shape",742 [SameOperandsAndResultShape]> {743 let arguments = (ins Variadic<AnyShaped>);744 let results = (outs Variadic<AnyShaped>);745}746 747def SameOperandAndResultTypeOp : TEST_Op<"same_operand_and_result_type",748 [SameOperandsAndResultType]> {749 let arguments = (ins Variadic<AnyType>);750 let results = (outs Variadic<AnyType>);751}752 753def ElementwiseMappableOp : TEST_Op<"elementwise_mappable",754 ElementwiseMappable.traits> {755 let arguments = (ins Variadic<AnyType>);756 let results = (outs Variadic<AnyType>);757}758 759def ArgAndResHaveFixedElementTypesOp :760 TEST_Op<"arg_and_res_have_fixed_element_types",761 [PredOpTrait<"fixed type combination",762 And<[ElementTypeIsPred<"x", I32>,763 ElementTypeIsPred<"y", F32>]>>,764 ElementTypeIs<"res", I16>]> {765 let arguments = (ins766 AnyShaped:$x, AnyShaped:$y);767 let results = (outs AnyShaped:$res);768}769 770def OperandsHaveSameElementType : TEST_Op<"operands_have_same_element_type", [771 AllElementTypesMatch<["x", "y"]>]> {772 let arguments = (ins AnyType:$x, AnyType:$y);773}774 775def OperandZeroAndResultHaveSameElementType : TEST_Op<776 "operand0_and_result_have_same_element_type",777 [AllElementTypesMatch<["x", "res"]>]> {778 let arguments = (ins AnyType:$x, AnyType:$y);779 let results = (outs AnyType:$res);780}781 782def OperandsHaveSameType :783 TEST_Op<"operands_have_same_type", [AllTypesMatch<["x", "y"]>]> {784 let arguments = (ins AnyType:$x, AnyType:$y);785}786 787def ResultHasSameTypeAsAttr :788 TEST_Op<"result_has_same_type_as_attr",789 [AllTypesMatch<["attr", "result"]>]> {790 let arguments = (ins TypedAttrInterface:$attr);791 let results = (outs AnyType:$result);792 let assemblyFormat = "$attr `->` type($result) attr-dict";793}794 795def OperandZeroAndResultHaveSameType :796 TEST_Op<"operand0_and_result_have_same_type",797 [AllTypesMatch<["x", "res"]>]> {798 let arguments = (ins AnyType:$x, AnyType:$y);799 let results = (outs AnyType:$res);800}801 802def OperandsHaveSameRank :803 TEST_Op<"operands_have_same_rank", [AllRanksMatch<["x", "y"]>]> {804 let arguments = (ins AnyShaped:$x, AnyShaped:$y);805}806 807def OperandZeroAndResultHaveSameRank :808 TEST_Op<"operand0_and_result_have_same_rank",809 [AllRanksMatch<["x", "res"]>]> {810 let arguments = (ins AnyShaped:$x, AnyShaped:$y);811 let results = (outs AnyShaped:$res);812}813 814def OperandsAndResultHaveSameRank :815 TEST_Op<"operands_and_result_have_same_rank", [SameOperandsAndResultRank]> {816 let arguments = (ins AnyShaped:$x, AnyShaped:$y);817 let results = (outs AnyShaped:$res);818}819 820def OperandZeroAndResultHaveSameShape :821 TEST_Op<"operand0_and_result_have_same_shape",822 [AllShapesMatch<["x", "res"]>]> {823 let arguments = (ins AnyShaped:$x, AnyShaped:$y);824 let results = (outs AnyShaped:$res);825}826 827def OperandZeroAndResultHaveSameElementCount :828 TEST_Op<"operand0_and_result_have_same_element_count",829 [AllElementCountsMatch<["x", "res"]>]> {830 let arguments = (ins AnyShaped:$x, AnyShaped:$y);831 let results = (outs AnyShaped:$res);832}833 834def FourEqualsFive :835 TEST_Op<"four_equals_five", [AllMatch<["5", "4"], "4 equals 5">]>;836 837def OperandRankEqualsResultSize :838 TEST_Op<"operand_rank_equals_result_size",839 [AllMatch<[Rank<"operand">.result, ElementCount<"result">.result],840 "operand rank equals result size">]> {841 let arguments = (ins AnyShaped:$operand);842 let results = (outs AnyShaped:$result);843}844 845def IfFirstOperandIsNoneThenSoIsSecond :846 TEST_Op<"if_first_operand_is_none_then_so_is_second", [PredOpTrait<847 "has either both none type operands or first is not none",848 Or<[849 And<[TypeIsPred<"x", NoneType>, TypeIsPred<"y", NoneType>]>,850 Neg<TypeIsPred<"x", NoneType>>]>>]> {851 let arguments = (ins AnyType:$x, AnyType:$y);852}853 854def BroadcastableOp : TEST_Op<"broadcastable", [ResultsBroadcastableShape]> {855 let arguments = (ins Variadic<AnyTensor>);856 let results = (outs AnyTensor);857}858 859// HasParent trait860def ParentOp : TEST_Op<"parent"> {861 let regions = (region AnyRegion);862}863def ChildOp : TEST_Op<"child", [HasParent<"ParentOp">]>;864 865// ParentOneOf trait866def ParentOp1 : TEST_Op<"parent1"> {867 let regions = (region AnyRegion);868}869def ChildWithParentOneOf : TEST_Op<"child_with_parent_one_of",870 [ParentOneOf<["ParentOp", "ParentOp1"]>]>;871 872def TerminatorOp : TEST_Op<"finish", [Terminator]>;873def SingleBlockImplicitTerminatorOp : TEST_Op<"SingleBlockImplicitTerminator",874 [SingleBlockImplicitTerminator<"TerminatorOp">]> {875 let regions = (region SizedRegion<1>:$region);876}877 878def I32ElementsAttrOp : TEST_Op<"i32ElementsAttr"> {879 let arguments = (ins I32ElementsAttr:$attr);880}881 882def IndexElementsAttrOp : TEST_Op<"indexElementsAttr"> {883 let arguments = (ins IndexElementsAttr:$attr);884}885 886def OpWithInferTypeInterfaceOp : TEST_Op<"op_with_infer_type_if", [887 DeclareOpInterfaceMethods<InferTypeOpInterface>]> {888 let arguments = (ins AnyTensor, AnyTensor);889 let results = (outs AnyTensor);890}891 892def OpWithInferTypeAdaptorInterfaceOp : TEST_Op<"op_with_infer_type_adaptor_if", [893 InferTypeOpAdaptor]> {894 let arguments = (ins AnyTensor:$x, AnyTensor:$y);895 let results = (outs AnyTensor);896}897 898def OpWithRefineTypeInterfaceOp : TEST_Op<"op_with_refine_type_if", [899 DeclareOpInterfaceMethods<InferTypeOpInterface,900 ["refineReturnTypes"]>]> {901 let arguments = (ins AnyTensor, AnyTensor);902 let results = (outs AnyTensor);903}904 905def OpWithShapedTypeInferTypeInterfaceOp : TEST_Op<"op_with_shaped_type_infer_type_if",906 [InferTensorTypeWithReify]> {907 let arguments = (ins AnyTensor, AnyTensor);908 let results = (outs AnyTensor);909}910 911def OpWithShapedTypeInferTypeAdaptorInterfaceOp :912 TEST_Op<"op_with_shaped_type_infer_type_adaptor_if",913 [InferTensorTypeAdaptorWithReify]> {914 let arguments = (ins AnyTensor:$operand1, AnyTensor:$operand2);915 let results = (outs AnyTensor:$result);916}917 918def OpWithResultShapeInterfaceOp : TEST_Op<"op_with_result_shape_interface",919 [DeclareOpInterfaceMethods<InferShapedTypeOpInterface,920 ["reifyReturnTypeShapes"]>]> {921 let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2);922 let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2);923}924 925def ReifyShapedTypeUsingReifyResultShapesOp :926 TEST_Op<"reify_shaped_type_using_reify_result_shapes",927 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface, 928 ["reifyResultShapes"]>]> {929 let description = [{930 Test that when resolving a single dimension of a result for an operation931 that doesnt implement `reifyShapeOfResult` nor implements `reifyDimOfResult`932 calls into the implementation of `reifyResultShapes` to get the required value.933 The op semantics is that the first result has the same shape as the second operand934 and the second result has the same shape as the first operand.935 }];936 let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2);937 let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2);938}939 940def ReifyShapedTypeUsingReifyShapeOfResultOp :941 TEST_Op<"reify_shaped_type_using_reify_shape_of_result",942 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface, 943 ["reifyResultShapes", "reifyShapeOfResult"]>]> {944 let description = [{945 Test that when resolving a single dimension of a result for an operation946 that doesnt implement `reifyDimOfResult` but implements `reifyShapeOfResult`, which947 is used to get the required value. `reifyResultShapes` is implemented as a failure948 (which is also the default implementation) to ensure it is not called.949 The op semantics is that the first result has the same shape as the second operand950 and the second result has the same shape as the first operand.951 }];952 let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2);953 let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2);954}955 956def ReifyShapedTypeUsingReifyDimOfResultOp :957 TEST_Op<"reify_shaped_type_using_reify_dim_of_result",958 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface, 959 ["reifyResultShapes", "reifyShapeOfResult", "reifyDimOfResult"]>]> {960 let description = [{961 Test that when resolving a single dimension of a result for an operation962 that implements `reifyDimOfResult`, which is used to get the required value.963 `reifyResultShapes` and `reifyShapeOfResult` are implemented as failures964 to ensure they are not called. The op semantics is that the first result has965 the same shape as the second operand and the second result has the same shape966 as the first operand.967 }];968 let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2);969 let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2);970}971 972def UnreifiableResultShapesOp : TEST_Op<"unreifiable_result_shapes",973 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface,974 ["reifyResultShapes"]>]> {975 let description = [{976 Test handling of case where some dimension of the result cannot be977 reified. This tests the path when `reifyResultShapes` is implemented.978 979 Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but980 dim 1 of `result` is not reifiable.981 }];982 let arguments = (ins 2DTensorOf<[AnyType]>:$operand);983 let results = (outs 2DTensorOf<[AnyType]>:$result);984}985 986def UnreifiableResultShapeOp : TEST_Op<"unreifiable_result_shape",987 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface,988 ["reifyResultShapes", "reifyShapeOfResult"]>]> {989 let description = [{990 Test handling of case where some dimension of the result cannot be991 reified. This tests the path when `reifyShapeOfResult` is implemented,992 but not `reifyDimOfResult` with `reifyResultShapes` implemented as a failure.993 994 Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but995 dim 1 of `result` is not reifiable.996 }];997 let arguments = (ins 2DTensorOf<[AnyType]>:$operand);998 let results = (outs 2DTensorOf<[AnyType]>:$result);999}1000 1001def UnreifiableDimOfResultShapeOp : TEST_Op<"unreifiable_dim_of_result_shape",1002 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface,1003 ["reifyResultShapes", "reifyShapeOfResult", "reifyDimOfResult"]>]> {1004 let description = [{1005 Test handling of case where some dimension of the result cannot be1006 reified. This tests the path when `reifyDimOfResult` is implemented,1007 and `reifyDimOfResult` with `reifyResultShapes` are implemented as a failure.1008 1009 Expected that dim 0 of `result` is reifable as dim 0 of `operand`, but1010 dim 1 of `result` is not reifiable.1011 }];1012 let arguments = (ins 2DTensorOf<[AnyType]>:$operand);1013 let results = (outs 2DTensorOf<[AnyType]>:$result);1014}1015 1016def IsNotScalar : Constraint<CPred<"$0.getType().getRank() != 0">>;1017 1018def UpdateAttr : Pat<(I32ElementsAttrOp $attr),1019 (I32ElementsAttrOp ConstantAttr<I32ElementsAttr, "0">),1020 [(IsNotScalar $attr)]>;1021 1022def TestBranchOp : TEST_Op<"br",1023 [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator]> {1024 let arguments = (ins Variadic<AnyType>:$targetOperands);1025 let successors = (successor AnySuccessor:$target);1026}1027 1028def TestProducingBranchOp : TEST_Op<"producing_br",1029 [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator,1030 AttrSizedOperandSegments]> {1031 let arguments = (ins Variadic<AnyType>:$firstOperands,1032 Variadic<AnyType>:$secondOperands);1033 let results = (outs I32:$dummy);1034 let successors = (successor AnySuccessor:$first,AnySuccessor:$second);1035}1036 1037// Produces an error value on the error path1038def TestInternalBranchOp : TEST_Op<"internal_br",1039 [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator,1040 AttrSizedOperandSegments]> {1041 1042 let arguments = (ins Variadic<AnyType>:$successOperands,1043 Variadic<AnyType>:$errorOperands);1044 1045 let successors = (successor AnySuccessor:$successPath, AnySuccessor:$errorPath);1046}1047 1048def AttrSizedOperandOp : TEST_Op<"attr_sized_operands",1049 [AttrSizedOperandSegments]> {1050 let arguments = (ins1051 Variadic<I32>:$a,1052 Variadic<I32>:$b,1053 I32:$c,1054 Variadic<I32>:$d1055 );1056}1057 1058def AttrSizedResultOp : TEST_Op<"attr_sized_results",1059 [AttrSizedResultSegments]> {1060 let results = (outs1061 Variadic<I32>:$a,1062 Variadic<I32>:$b,1063 I32:$c,1064 Variadic<I32>:$d1065 );1066}1067 1068def AttrSizedResultCompileTestOp : TEST_Op<"attr_sized_results_compile_test",1069 [AttrSizedResultSegments]> {1070 let results = (outs Variadic<I32>:$a, I32:$b, Optional<I32>:$c);1071}1072 1073 1074 1075// This is used to test encoding of a string attribute into an SSA name of a1076// pretty printed value name.1077def StringAttrPrettyNameOp1078 : TEST_Op<"string_attr_pretty_name",1079 [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {1080 let arguments = (ins StrArrayAttr:$names);1081 let results = (outs Variadic<I32>:$r);1082 let hasCustomAssemblyFormat = 1;1083}1084 1085 1086// This is used to test encoding of a string attribute into an SSA name of a1087// pretty printed value name.1088def CustomResultsNameOp1089 : TEST_Op<"custom_result_name",1090 [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {1091 let arguments = (ins1092 Variadic<AnyInteger>:$optional,1093 StrArrayAttr:$names1094 );1095 let results = (outs Variadic<AnyInteger>:$r);1096}1097 1098// This is used to test OpAsmTypeInterface::getAsmName for op result name,1099def ResultNameFromTypeOp1100 : TEST_Op<"result_name_from_type",1101 [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {1102 let results = (outs AnyType:$r);1103}1104 1105// This is used to test OpAsmTypeInterface::getAsmName for block argument,1106def BlockArgumentNameFromTypeOp1107 : TEST_Op<"block_argument_name_from_type",1108 [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmBlockArgumentNames"]>]> {1109 let regions = (region AnyRegion:$body);1110 let assemblyFormat = "regions attr-dict-with-keyword";1111}1112 1113// This is used to test OpAsmTypeInterface::getAsmName's integration with AsmPrinter1114// for op result name when OpAsmOpInterface::getAsmResultNames is the default implementation1115// i.e. does nothing.1116def ResultNameFromTypeInterfaceOp1117 : TEST_Op<"result_name_from_type_interface",1118 [OpAsmOpInterface]> {1119 let results = (outs Variadic<AnyType>:$r);1120}1121 1122// This is used to test OpAsmTypeInterface::getAsmName's integration with AsmPrinter1123// for block argument name when OpAsmOpInterface::getAsmBlockArgumentNames is the default implementation1124// i.e. does nothing.1125def BlockArgumentNameFromTypeInterfaceOp1126 : TEST_Op<"block_argument_name_from_type_interface",1127 [OpAsmOpInterface]> {1128 let regions = (region AnyRegion:$body);1129 let assemblyFormat = "regions attr-dict-with-keyword";1130}1131 1132// This is used to test the OpAsmOpInterface::getDefaultDialect() feature:1133// operations nested in a region under this op will drop the "test." dialect1134// prefix.1135def DefaultDialectOp : TEST_Op<"default_dialect", [OpAsmOpInterface]> {1136 let regions = (region AnyRegion:$body);1137 let extraClassDeclaration = [{1138 static ::llvm::StringRef getDefaultDialect() {1139 return "test";1140 }1141 void getAsmResultNames(::llvm::function_ref<void(::mlir::Value, ::llvm::StringRef)> setNameFn) {}1142 }];1143 let assemblyFormat = "regions attr-dict-with-keyword";1144}1145 1146 1147// This is used to test the OpAsmOpInterface::getAsmBlockName() feature:1148// blocks nested in a region under this op will have a name defined by the1149// interface.1150def AsmBlockNameOp : TEST_Op<"block_names", [OpAsmOpInterface]> {1151 let regions = (region AnyRegion:$body);1152 let extraClassDeclaration = [{1153 void getAsmBlockNames(mlir::OpAsmSetBlockNameFn setNameFn) {1154 std::string name;1155 int count = 0;1156 for (::mlir::Block &block : getRegion().getBlocks()) {1157 name = "foo" + std::to_string(count++);1158 setNameFn(&block, name);1159 }1160 }1161 }];1162 let assemblyFormat = "regions attr-dict-with-keyword";1163}1164 1165// This operation requires its return type to have the trait 'TestTypeTrait'.1166def ResultTypeWithTraitOp : TEST_Op<"result_type_with_trait", []> {1167 let results = (outs AnyType);1168 let hasVerifier = 1;1169}1170 1171// This operation requires its "attr" attribute to have the1172// trait 'TestAttrTrait'.1173def AttrWithTraitOp : TEST_Op<"attr_with_trait", []> {1174 let arguments = (ins AnyAttr:$attr);1175 let hasVerifier = 1;1176}1177 1178//===----------------------------------------------------------------------===//1179// Test Locations1180//===----------------------------------------------------------------------===//1181 1182def TestLocationSrcOp : TEST_Op<"loc_src"> {1183 let arguments = (ins I32:$input);1184 let results = (outs I32:$output);1185}1186 1187def TestLocationDstOp : TEST_Op<"loc_dst", [SameOperandsAndResultType]> {1188 let arguments = (ins I32:$input);1189 let results = (outs I32:$output);1190}1191 1192def TestLocationSrcNoResOp : TEST_Op<"loc_src_no_res"> {1193 let arguments = (ins I32:$input);1194 let results = (outs);1195}1196 1197def TestLocationDstNoResOp : TEST_Op<"loc_dst_no_res"> {1198 let arguments = (ins I32:$input);1199 let results = (outs);1200}1201 1202def TestLocationAttrOp : TEST_Op<"op_with_loc_attr"> {1203 let arguments = (ins LocationAttr:$loc_attr);1204 let results = (outs );1205 let assemblyFormat = "$loc_attr attr-dict";1206}1207 1208//===----------------------------------------------------------------------===//1209// Test Patterns1210//===----------------------------------------------------------------------===//1211 1212def OpA : TEST_Op<"op_a"> {1213 let arguments = (ins I32, I32Attr:$attr);1214 let results = (outs I32);1215}1216 1217def OpB : TEST_Op<"op_b"> {1218 let arguments = (ins I32, I32Attr:$attr);1219 let results = (outs I32);1220}1221 1222// Test named pattern.1223def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>;1224 1225// Test with fused location.1226def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>;1227 1228// Test added benefit.1229def OpD : TEST_Op<"op_d">, Arguments<(ins I32)>, Results<(outs I32)>;1230def OpE : TEST_Op<"op_e">, Arguments<(ins I32)>, Results<(outs I32)>;1231def OpF : TEST_Op<"op_f">, Arguments<(ins I32)>, Results<(outs I32)>;1232def OpG : TEST_Op<"op_g">, Arguments<(ins I32)>, Results<(outs I32)>;1233// Verify that bumping benefit results in selecting different op.1234def : Pat<(OpD $input), (OpE $input)>;1235def : Pat<(OpD $input), (OpF $input), [], [], (addBenefit 10)>;1236// Verify that patterns with more source nodes are selected before those with fewer.1237def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>;1238def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>;1239 1240// Test patterns for zero-result op.1241def OpH : TEST_Op<"op_h">, Arguments<(ins I32)>, Results<(outs)>;1242def OpI : TEST_Op<"op_i">, Arguments<(ins I32)>, Results<(outs)>;1243def : Pat<(OpH $input), (OpI $input)>;1244 1245// Test patterns for zero-input op.1246def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32)>;1247def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32)>;1248def : Pat<(OpJ), (OpK)>;1249 1250// Test that natives calls are only called once during rewrites.1251def OpM : TEST_Op<"op_m"> {1252 let arguments = (ins I32, OptionalAttr<I32Attr>:$optional_attr);1253 let results = (outs I32);1254}1255 1256def OpN : TEST_Op<"op_n"> {1257 let arguments = (ins I32, I32);1258 let results = (outs I32);1259}1260 1261def OpO : TEST_Op<"op_o"> {1262 let arguments = (ins I32);1263 let results = (outs I32);1264}1265 1266def OpP : TEST_Op<"op_p"> {1267 let arguments = (ins I32, I32, I32, I32, I32, I32);1268 let results = (outs I32);1269}1270 1271def OpQ : TEST_Op<"op_q"> {1272 let arguments = (ins AnyType, AnyType);1273 let results = (outs AnyType);1274}1275 1276// Test constant-folding a pattern that maps `(F32) -> SI32`.1277def SignOp : TEST_Op<"sign", [SameOperandsAndResultShape]> {1278 let arguments = (ins RankedTensorOf<[F32]>:$operand);1279 let results = (outs RankedTensorOf<[SI32]>:$result);1280 1281 let assemblyFormat = [{1282 $operand attr-dict `:` functional-type(operands, results)1283 }];1284}1285 1286// Test constant-folding a pattern that maps `(F32, F32) -> I1`.1287def LessThanOp : TEST_Op<"less_than", [SameOperandsAndResultShape]> {1288 let arguments = (ins RankedTensorOf<[F32]>:$lhs, RankedTensorOf<[F32]>:$rhs);1289 let results = (outs RankedTensorOf<[I1]>:$result);1290 1291 let assemblyFormat = [{1292 $lhs `,` $rhs attr-dict `:` functional-type(operands, results)1293 }];1294}1295 1296// Test same operand name enforces equality condition check.1297def TestEqualArgsPattern : Pat<(OpN $a, $a), (OpO $a)>;1298 1299// Test when equality is enforced at different depth.1300def TestNestedOpEqualArgsPattern :1301 Pat<(OpN $b, (OpP $a, $b, $c, $d, $e, $f)), (replaceWithValue $b)>;1302 1303// Test when equality is enforced on same op and same operand but at different1304// depth. We only bound one of the $x to the second operand of outer OpN and1305// left another be the default value (which is the value of first operand of1306// outer OpN). As a result, it ended up comparing wrong values in some cases.1307def TestNestedSameOpAndSameArgEqualityPattern :1308 Pat<(OpN (OpN $_, $x), $x), (replaceWithValue $x)>;1309 1310// Test multiple equal arguments check enforced.1311def TestMultipleEqualArgsPattern :1312 Pat<(OpP $a, $b, $a, $a, $b, $c), (OpN $c, $b)>;1313 1314// Test equal arguments checks are applied before user provided constraints.1315def AssertBinOpEqualArgsAndReturnTrue : Constraint<1316 CPred<"assertBinOpEqualArgsAndReturnTrue($0)">>;1317def TestEqualArgsCheckBeforeUserConstraintsPattern :1318 Pat<(OpQ:$op $x, $x),1319 (replaceWithValue $x),1320 [(AssertBinOpEqualArgsAndReturnTrue $op)]>;1321 1322// Test for memrefs normalization of an op with normalizable memrefs.1323def OpNorm : TEST_Op<"op_norm", [MemRefsNormalizable]> {1324 let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y);1325}1326// Test for memrefs normalization of an op without normalizable memrefs.1327def OpNonNorm : TEST_Op<"op_nonnorm"> {1328 let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y);1329}1330// Test for memrefs normalization of an op that has normalizable memref results.1331def OpNormRet : TEST_Op<"op_norm_ret", [MemRefsNormalizable]> {1332 let arguments = (ins AnyMemRef:$X);1333 let results = (outs AnyMemRef:$Y, AnyMemRef:$Z);1334}1335 1336// Test for memrefs normalization of an op with a reference to a function1337// symbol.1338def OpFuncRef : TEST_Op<"op_funcref"> {1339 let summary = "Test op with a reference to a function symbol";1340 let description = [{1341 The "test.op_funcref" is a test op with a reference to a function symbol.1342 }];1343}1344 1345// Pattern add the argument plus a increasing static number hidden in1346// OpMTest function. That value is set into the optional argument.1347// That way, we will know if operations is called once or twice.1348def OpMGetNullAttr : NativeCodeCall<"Attribute()">;1349def OpMAttributeIsNull : Constraint<CPred<"! ($_self)">, "Attribute is null">;1350def OpMVal : NativeCodeCall<"opMTest($_builder, $0)">;1351def : Pat<(OpM $attr, $optAttr), (OpM $attr, (OpMVal $attr) ),1352 [(OpMAttributeIsNull:$optAttr)]>;1353 1354// Test `$_` for ignoring op argument match.1355def TestIgnoreArgMatchSrcOp : TEST_Op<"ignore_arg_match_src"> {1356 let arguments = (ins1357 AnyType:$a, AnyType:$b, AnyType:$c,1358 AnyAttr:$d, AnyAttr:$e, AnyAttr:$f);1359}1360def TestIgnoreArgMatchDstOp : TEST_Op<"ignore_arg_match_dst"> {1361 let arguments = (ins AnyType:$b, AnyAttr:$f);1362}1363def : Pat<(TestIgnoreArgMatchSrcOp $_, $b, I32, I64Attr:$_, $_, $f),1364 (TestIgnoreArgMatchDstOp $b, $f)>;1365 1366def OpInterleavedOperandAttribute1 : TEST_Op<"interleaved_operand_attr1"> {1367 let arguments = (ins1368 I32:$input1,1369 I64Attr:$attr1,1370 I32:$input2,1371 I64Attr:$attr21372 );1373}1374 1375def OpInterleavedOperandAttribute2 : TEST_Op<"interleaved_operand_attr2"> {1376 let arguments = (ins1377 I32:$input1,1378 I64Attr:$attr1,1379 I32:$input2,1380 I64Attr:$attr21381 );1382}1383 1384def ManyArgsOp : TEST_Op<"many_arguments"> {1385 let arguments = (ins1386 I32:$input1, I32:$input2, I32:$input3, I32:$input4, I32:$input5,1387 I32:$input6, I32:$input7, I32:$input8, I32:$input9,1388 I64Attr:$attr1, I64Attr:$attr2, I64Attr:$attr3, I64Attr:$attr4,1389 I64Attr:$attr5, I64Attr:$attr6, I64Attr:$attr7, I64Attr:$attr8,1390 I64Attr:$attr91391 );1392}1393 1394// Test that DRR does not blow up when seeing lots of arguments.1395def : Pat<(ManyArgsOp1396 $input1, $input2, $input3, $input4, $input5,1397 $input6, $input7, $input8, $input9,1398 ConstantAttr<I64Attr, "42">,1399 $attr2, $attr3, $attr4, $attr5, $attr6,1400 $attr7, $attr8, $attr9),1401 (ManyArgsOp1402 $input1, $input2, $input3, $input4, $input5,1403 $input6, $input7, $input8, $input9,1404 ConstantAttr<I64Attr, "24">,1405 $attr2, $attr3, $attr4, $attr5, $attr6,1406 $attr7, $attr8, $attr9)>;1407 1408// Test that we can capture and reference interleaved operands and attributes.1409def : Pat<(OpInterleavedOperandAttribute1 $input1, $attr1, $input2, $attr2),1410 (OpInterleavedOperandAttribute2 $input1, $attr1, $input2, $attr2)>;1411 1412// Test NativeCodeCall.1413def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> {1414 let arguments = (ins1415 I32:$input1, I32:$input2,1416 BoolAttr:$choice,1417 I64Attr:$attr1, I64Attr:$attr21418 );1419 let results = (outs I32);1420}1421def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> {1422 let arguments = (ins I32:$input, I64ArrayAttr:$attr);1423 let results = (outs I32);1424}1425// Native code call to invoke a C++ function1426def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">;1427// Native code call to invoke a C++ expression1428def CreateArrayAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">;1429// Test that we can use NativeCodeCall to create operand and attribute.1430// This pattern chooses between $input1 and $input2 according to $choice and1431// it combines $attr1 and $attr2 into an array attribute.1432def : Pat<(OpNativeCodeCall1 $input1, $input2,1433 ConstBoolAttrTrue:$choice, $attr1, $attr2),1434 (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice),1435 (CreateArrayAttr $attr1, $attr2))>;1436// Note: the following is just for testing purpose.1437// Should use the replaceWithValue directive instead.1438def UseOpResult: NativeCodeCall<"$0">;1439// Test that we can use NativeCodeCall to create result.1440def : Pat<(OpNativeCodeCall1 $input1, $input2,1441 ConstBoolAttrFalse, $attr1, $attr2),1442 (UseOpResult $input2)>;1443 1444def OpNativeCodeCall3 : TEST_Op<"native_code_call3"> {1445 let arguments = (ins I32:$input);1446 let results = (outs I32);1447}1448// Test that NativeCodeCall is not ignored if it is not used to directly1449// replace the matched root op.1450def : Pattern<(OpNativeCodeCall3 $input),1451 [(NativeCodeCallVoid<"createOpI($_builder, $_loc, $0)"> $input),1452 (OpK)]>;1453 1454def OpNativeCodeCall4 : TEST_Op<"native_code_call4"> {1455 let arguments = (ins AnyType:$input1);1456 let results = (outs I32:$output1, I32:$output2);1457}1458def OpNativeCodeCall5 : TEST_Op<"native_code_call5"> {1459 let arguments = (ins I32:$input1, I32:$input2);1460 let results = (outs I32:$output1, I32:$output2);1461}1462 1463def GetFirstI32Result : NativeCodeCall<"success(getFirstI32Result($_self, $0))">;1464def BindNativeCodeCallResult : NativeCodeCall<"bindNativeCodeCallResult($0)">;1465def : Pat<(OpNativeCodeCall4 (GetFirstI32Result $ret)),1466 (OpNativeCodeCall5 (BindNativeCodeCallResult:$native $ret), $native)>;1467 1468def OpNativeCodeCall6 : TEST_Op<"native_code_call6"> {1469 let arguments = (ins I32:$input1, I32:$input2);1470 let results = (outs I32:$output1, I32:$output2);1471}1472def OpNativeCodeCall7 : TEST_Op<"native_code_call7"> {1473 let arguments = (ins I32:$input);1474 let results = (outs I32);1475}1476def BindMultipleNativeCodeCallResult : NativeCodeCall<"bindMultipleNativeCodeCallResult($0, $1)", 2>;1477def : Pattern<(OpNativeCodeCall6 $arg1, $arg2),1478 [(OpNativeCodeCall7 (BindMultipleNativeCodeCallResult:$native__0 $arg1, $arg2)),1479 (OpNativeCodeCall7 $native__1)]>;1480 1481// Test AllAttrOf.1482def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> {1483 let arguments = (ins I64ArrayAttr:$attr);1484 let results = (outs I32);1485}1486def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> {1487 let arguments = (ins I64ArrayAttr:$attr);1488 let results = (outs I32);1489}1490def Constraint0 : AttrConstraint<1491 CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<ArrayAttr>($_self)[0]).getInt() == 0">,1492 "[0] == 0">;1493def Constraint1 : AttrConstraint<1494 CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<ArrayAttr>($_self)[1]).getInt() == 1">,1495 "[1] == 1">;1496def : Pat<(OpAllAttrConstraint11497 AllAttrOf<[Constraint0, Constraint1]>:$attr),1498 (OpAllAttrConstraint2 $attr)>;1499 1500// Op for testing RewritePattern removing op with inner ops.1501def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> {1502 let regions = (region SizedRegion<1>:$region);1503 let hasCanonicalizer = 1;1504}1505 1506def TestOpConstant : TEST_Op<"constant", [ConstantLike, NoMemoryEffect]> {1507 let arguments = (ins AnyAttr:$value);1508 let results = (outs AnyType);1509 1510 let hasFolder = 1;1511}1512 1513def OpR : TEST_Op<"op_r">, Arguments<(ins AnyInteger, AnyInteger)>, Results<(outs AnyInteger)>;1514def OpS : TEST_Op<"op_s">, Arguments<(ins AnyInteger, AnyAttr:$value)>, Results<(outs AnyInteger)>;1515 1516def : Pat<(OpR $input1, (ConstantLikeMatcher I32Attr:$input2)),1517 (OpS:$unused $input1, $input2)>;1518 1519// Op for testing trivial removal via folding of op with inner ops and no uses.1520def TestOpWithRegionFoldNoMemoryEffect : TEST_Op<1521 "op_with_region_fold_no_side_effect", [NoMemoryEffect]> {1522 let regions = (region SizedRegion<1>:$region);1523}1524 1525// Op for testing folding of outer op with inner ops.1526def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> {1527 let arguments = (ins AnyType:$operand);1528 let results = (outs AnyType);1529 let regions = (region SizedRegion<1>:$region);1530 let hasFolder = 1;1531}1532 1533def TestOpWithVariadicResultsAndFolder: TEST_Op<"op_with_variadic_results_and_folder"> {1534 let arguments = (ins Variadic<I32>);1535 let results = (outs Variadic<I32>);1536 let hasFolder = 1;1537}1538 1539def TestAddIOp : TEST_Op<"addi"> {1540 let arguments = (ins AnyTypeOf<[I32, TestI32]>:$op1,1541 AnyTypeOf<[I32, TestI32]>:$op2);1542 let results = (outs AnyTypeOf<[I32, TestI32]>);1543}1544 1545def TestCommutativeOp : TEST_Op<"op_commutative", [Commutative]> {1546 let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4);1547 let results = (outs I32);1548}1549 1550def TestLargeCommutativeOp : TEST_Op<"op_large_commutative", [Commutative]> {1551 let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4, I32:$op5, I32:$op6, I32:$op7);1552 let results = (outs I32);1553}1554 1555def TestCommutative2Op : TEST_Op<"op_commutative2", [Commutative]> {1556 let arguments = (ins I32:$op1, I32:$op2);1557 let results = (outs I32);1558}1559 1560def TestIdempotentTraitOp1561 : TEST_Op<"op_idempotent_trait",1562 [SameOperandsAndResultType, NoMemoryEffect, Idempotent]> {1563 let arguments = (ins I32:$op1);1564 let results = (outs I32);1565}1566 1567def TestIdempotentTraitBinaryOp1568 : TEST_Op<"op_idempotent_trait_binary",1569 [SameOperandsAndResultType, NoMemoryEffect, Idempotent]> {1570 let arguments = (ins I32:$op1, I32:$op2);1571 let results = (outs I32);1572}1573 1574def TestInvolutionTraitNoOperationFolderOp1575 : TEST_Op<"op_involution_trait_no_operation_fold",1576 [SameOperandsAndResultType, NoMemoryEffect, Involution]> {1577 let arguments = (ins I32:$op1);1578 let results = (outs I32);1579}1580 1581def TestInvolutionTraitFailingOperationFolderOp1582 : TEST_Op<"op_involution_trait_failing_operation_fold",1583 [SameOperandsAndResultType, NoMemoryEffect, Involution]> {1584 let arguments = (ins I32:$op1);1585 let results = (outs I32);1586 let hasFolder = 1;1587}1588 1589def TestInvolutionTraitSuccesfulOperationFolderOp1590 : TEST_Op<"op_involution_trait_succesful_operation_fold",1591 [SameOperandsAndResultType, NoMemoryEffect, Involution]> {1592 let arguments = (ins I32:$op1);1593 let results = (outs I32);1594 let hasFolder = 1;1595}1596 1597def TestOpInPlaceFoldAnchor : TEST_Op<"op_in_place_fold_anchor"> {1598 let arguments = (ins I32);1599 let results = (outs I32);1600}1601 1602def TestOpInPlaceFold : TEST_Op<"op_in_place_fold"> {1603 let arguments = (ins I32:$op, OptionalAttr<I32Attr>:$attr);1604 let results = (outs I32);1605 let hasFolder = 1;1606}1607 1608def TestOpInPlaceSelfFold : TEST_Op<"op_in_place_self_fold"> {1609 let arguments = (ins UnitAttr:$folded);1610 let results = (outs I32);1611 let hasFolder = 1;1612}1613def : Pat<(TestOpInPlaceSelfFold:$op $_),1614 (TestOpConstant ConstantAttr<I32Attr, "97">)>;1615 1616// Test op that simply returns success.1617def TestOpInPlaceFoldSuccess : TEST_Op<"op_in_place_fold_success"> {1618 let results = (outs Variadic<I1>);1619 let hasFolder = 1;1620 let extraClassDefinition = [{1621 ::llvm::LogicalResult $cppClass::fold(FoldAdaptor adaptor,1622 SmallVectorImpl<OpFoldResult> &results) {1623 return success();1624 }1625 }];1626}1627 1628def TestOpFoldWithFoldAdaptor1629 : TEST_Op<"fold_with_fold_adaptor",1630 [AttrSizedOperandSegments, NoTerminator]> {1631 let arguments = (ins1632 I32:$op,1633 DenseI32ArrayAttr:$attr,1634 Variadic<I32>:$variadic,1635 VariadicOfVariadic<I32, "attr">:$var_of_var1636 );1637 1638 let results = (outs I32:$res);1639 1640 let regions = (region AnyRegion:$body);1641 1642 let assemblyFormat = [{1643 $op `,` `[` $variadic `]` `,` `{` $var_of_var `}` $body attr-dict-with-keyword1644 }];1645 1646 let hasFolder = 1;1647}1648 1649def TestDialectCanonicalizerOp : TEST_Op<"dialect_canonicalizable"> {1650 let arguments = (ins);1651 let results = (outs I32);1652}1653 1654//===----------------------------------------------------------------------===//1655// Test Patterns (Symbol Binding)1656//===----------------------------------------------------------------------===//1657 1658// Test symbol binding.1659def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> {1660 let arguments = (ins I32:$operand, I64Attr:$attr);1661 let results = (outs I32);1662}1663def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> {1664 let arguments = (ins I32:$operand);1665 let results = (outs I32);1666}1667def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> {1668 let arguments = (ins I32:$operand);1669 let results = (outs I32);1670 let builders = OpSymbolBindingB.builders;1671}1672def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> {1673 let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr);1674 let results = (outs I32);1675}1676def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">;1677def : Pattern<1678 // Bind to source pattern op operand/attribute/result1679 (OpSymbolBindingA:$res_a $operand, $attr), [1680 // Bind to auxiliary op result1681 (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)),1682 1683 // Use bound symbols in resultant ops1684 (OpSymbolBindingD $res_b, $res_c, $attr)],1685 // Use bound symbols in additional constraints1686 [(HasOneUse $res_a)]>;1687 1688def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> {1689 let arguments = (ins I32:$operand);1690}1691 1692// Test that we can bind to an op without results and reference it later.1693def : Pat<(OpSymbolBindingNoResult:$op $operand),1694 (NativeCodeCallVoid<"handleNoResultOp($_builder, $0)"> $op)>;1695 1696//===----------------------------------------------------------------------===//1697// Test Patterns (Attributes)1698//===----------------------------------------------------------------------===//1699 1700// Test matching against op attributes.1701def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> {1702 let arguments = (ins1703 I32Attr:$required_attr,1704 OptionalAttr<I32Attr>:$optional_attr,1705 DefaultValuedAttr<I32Attr, "42">:$default_valued_attr,1706 I32Attr:$more_attr1707 );1708 let results = (outs I32);1709}1710def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> {1711 let arguments = OpAttrMatch1.arguments;1712 let results = (outs I32);1713}1714def MoreConstraint : AttrConstraint<1715 CPred<"::llvm::cast<IntegerAttr>($_self).getInt() == 4">, "more constraint">;1716def : Pat<(OpAttrMatch1 $required, $optional, $default_valued,1717 MoreConstraint:$more),1718 (OpAttrMatch2 $required, $optional, $default_valued, $more)>;1719 1720// Test unit attrs.1721def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> {1722 let arguments = (ins UnitAttr:$attr);1723 let results = (outs I32);1724}1725def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> {1726 let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2);1727 let results = (outs I32);1728}1729def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>;1730 1731// Test with constant attr.1732def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>;1733def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>;1734 1735// Test integer enum attribute in rewrites.1736def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>;1737def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>;1738 1739def ThreeResultOp : TEST_Op<"three_result"> {1740 let arguments = (ins MultiResultOpEnum:$kind);1741 let results = (outs I32:$result1, F32:$result2, F32:$result3);1742}1743 1744def AnotherThreeResultOp1745 : TEST_Op<"another_three_result",1746 [DeclareOpInterfaceMethods<InferTypeOpInterface>]> {1747 let arguments = (ins MultiResultOpEnum:$kind);1748 let results = (outs I32:$result1, F32:$result2, F32:$result3);1749}1750 1751def TwoResultOp : TEST_Op<"two_result"> {1752 let arguments = (ins MultiResultOpEnum:$kind);1753 let results = (outs I32:$result1, F32:$result2);1754}1755 1756def AnotherTwoResultOp : TEST_Op<"another_two_result"> {1757 let arguments = (ins MultiResultOpEnum:$kind);1758 let results = (outs F32:$result1, F32:$result2);1759}1760 1761def OneResultOp1 : TEST_Op<"one_result1"> {1762 let arguments = (ins MultiResultOpEnum:$kind);1763 let results = (outs F32:$result1);1764}1765 1766def OneResultOp2 : TEST_Op<"one_result2"> {1767 let arguments = (ins MultiResultOpEnum:$kind);1768 let results = (outs I32:$result1);1769}1770 1771def OneResultOp3 : TEST_Op<"one_result3"> {1772 let arguments = (ins F32);1773 let results = (outs I32:$result1);1774}1775 1776// Test using multi-result op as a whole1777def : Pat<(ThreeResultOp MultiResultOpKind1:$kind),1778 (AnotherThreeResultOp $kind)>;1779 1780// Test using multi-result op as a whole for partial replacement1781def : Pattern<(ThreeResultOp MultiResultOpKind2:$kind),1782 [(TwoResultOp $kind),1783 (OneResultOp1 $kind)]>;1784def : Pattern<(ThreeResultOp MultiResultOpKind3:$kind),1785 [(OneResultOp2 $kind),1786 (AnotherTwoResultOp $kind)]>;1787 1788// Test using results separately in a multi-result op1789def : Pattern<(ThreeResultOp MultiResultOpKind4:$kind),1790 [(TwoResultOp:$res1__0 $kind),1791 (OneResultOp1 $kind),1792 (TwoResultOp:$res2__1 $kind)]>;1793 1794// Test referencing a single value in the value pack1795// This rule only matches TwoResultOp if its second result has no use.1796def : Pattern<(TwoResultOp:$res MultiResultOpKind5:$kind),1797 [(OneResultOp2 $kind),1798 (OneResultOp1 $kind)],1799 [(HasNoUseOf:$res__1)]>;1800 1801// Test using auxiliary ops for replacing multi-result op1802def : Pattern<1803 (ThreeResultOp MultiResultOpKind6:$kind), [1804 // Auxiliary op generated to help building the final result but not1805 // directly used to replace the source op's results.1806 (TwoResultOp:$interm $kind),1807 1808 (OneResultOp3 $interm__1),1809 (AnotherTwoResultOp $kind)1810 ]>;1811 1812//===----------------------------------------------------------------------===//1813// Test Patterns (Variadic Ops)1814//===----------------------------------------------------------------------===//1815 1816def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> {1817 let arguments = (ins Variadic<I32>);1818 let results = (outs Variadic<I32>);1819}1820def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> {1821 let arguments = (ins Variadic<I32>);1822 let results = (outs Variadic<I32>);1823}1824 1825// Rewrite an op with one variadic operand and one variadic result to1826// another similar op.1827def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>;1828 1829def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1",1830 [SameVariadicOperandSize]> {1831 let arguments = (ins1832 Variadic<I32>:$input1,1833 F32:$input2,1834 Variadic<I32>:$input31835 );1836}1837 1838def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2",1839 [SameVariadicOperandSize]> {1840 let arguments = (ins1841 Variadic<I32>:$input1,1842 F32:$input2,1843 Variadic<I32>:$input31844 );1845}1846 1847// Rewrite an op with both variadic operands and normal operands.1848def : Pat<(MixedVOperandOp1 $input1, $input2, $input3),1849 (MixedVOperandOp2 $input1, $input2, $input3)>;1850 1851def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> {1852 let results = (outs1853 Variadic<I32>:$output1,1854 F32:$output2,1855 Variadic<I32>:$output31856 );1857}1858 1859def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> {1860 let results = (outs1861 Variadic<I32>:$output1,1862 F32:$output2,1863 Variadic<I32>:$output31864 );1865}1866 1867// Rewrite an op with both variadic results and normal results.1868// Note that because we are generating the op with a top-level result pattern,1869// we are able to deduce the correct result types for the generated op using1870// the information from the matched root op.1871def : Pat<(MixedVResultOp1), (MixedVResultOp2)>;1872 1873def OneI32ResultOp : TEST_Op<"one_i32_out"> {1874 let results = (outs I32);1875}1876 1877def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3",1878 [SameVariadicOperandSize]> {1879 let arguments = (ins1880 I32:$input1,1881 Variadic<I32>:$input2,1882 Variadic<I32>:$input3,1883 I32Attr:$count1884 );1885 1886 let results = (outs I32);1887}1888 1889def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3",1890 [SameVariadicResultSize]> {1891 let arguments = (ins I32Attr:$count);1892 1893 let results = (outs1894 I32:$output1,1895 Variadic<I32>:$output2,1896 Variadic<I32>:$output31897 );1898 1899 // We will use this op in a nested result pattern, where we cannot deduce the1900 // result type. So need to provide a builder not requiring result types.1901 let builders = [1902 OpBuilder<(ins "::mlir::IntegerAttr":$count),1903 [{1904 auto i32Type = $_builder.getIntegerType(32);1905 $_state.addTypes(i32Type); // $output11906 SmallVector<Type, 4> types(count.getInt(), i32Type);1907 $_state.addTypes(types); // $output21908 $_state.addTypes(types); // $output31909 $_state.addAttribute("count", count);1910 }]>1911 ];1912}1913 1914// Generates an op with variadic results using nested pattern.1915def : Pat<(OneI32ResultOp),1916 (MixedVOperandOp31917 (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">),1918 (replaceWithValue $results__1),1919 (replaceWithValue $results__2),1920 ConstantAttr<I32Attr, "2">)>;1921 1922// Variadic structured matching1923def MixedVOperandOp4 : TEST_Op<"mixed_variadic_in4"> {1924 let arguments = (ins1925 Variadic<I32>:$input1,1926 I32:$input2,1927 I32Attr:$attr11928 );1929}1930 1931def MixedVOperandOp5 : TEST_Op<"mixed_variadic_in5"> {1932 let arguments = (ins1933 I32:$input1,1934 I32:$input2,1935 I32:$input3,1936 I32Attr:$attr1,1937 StrAttr:$pattern_name1938 );1939}1940 1941// Helper op to test variadic recursive pattern matching1942def MixedVOperandInOutI32Op : TEST_Op<"mixed_variadic_in_out_i32"> {1943 let arguments = (ins1944 I32:$input1945 );1946 let results = (outs1947 I32:$output1948 );1949}1950 1951def : Pat<1952 (MixedVOperandOp4 (variadic $input1a, $input1b), $input2,1953 ConstantAttr<I32Attr, "0">:$attr1),1954 (MixedVOperandOp5 $input1a, $input1b, $input2, $attr1,1955 ConstantStrAttr<StrAttr, "MatchVariadic">)>;1956 1957def : Pat<1958 (MixedVOperandOp5 $input1a, $input1b, $input2, $attr1,1959 ConstantStrAttr<StrAttr, "MatchInverseVariadic">),1960 (MixedVOperandOp3 $input2, (variadic $input1b), (variadic $input1a),1961 ConstantAttr<I32Attr, "1">:$attr1)>;1962 1963def : Pat<1964 (MixedVOperandOp4 (variadic (MixedVOperandInOutI32Op $input1a),1965 (MixedVOperandInOutI32Op $input1b)),1966 $input2, ConstantAttr<I32Attr, "1">:$attr1),1967 (MixedVOperandOp5 $input1a, $input1b, $input2, $attr1,1968 ConstantStrAttr<StrAttr, "MatchVariadicSubDag">)>;1969 1970def : Pat<1971 (MixedVOperandOp4 (variadic $input1, $input1), $input2,1972 ConstantAttr<I32Attr, "2">:$attr1),1973 (MixedVOperandOp5 $input1, $input1, $input2, $attr1,1974 ConstantStrAttr<StrAttr, "MatchVariadicSameSymbol">)>;1975 1976def MixedVOperandOp6 : TEST_Op<"mixed_variadic_in6",1977 [SameVariadicOperandSize]> {1978 let arguments = (ins1979 Variadic<I32>:$input1,1980 Variadic<I32>:$input2,1981 I32Attr:$attr11982 );1983}1984 1985def : Pat<1986 (MixedVOperandOp6 (variadic:$input1 $input1a, $input1b),1987 (variadic:$input2 $input2a, $input2b),1988 ConstantAttr<I32Attr, "1">:$attr1),1989 (MixedVOperandOp6 $input2, $input1, ConstantAttr<I32Attr, "-1">)>;1990 1991def : Pat<1992 (MixedVOperandOp6 (variadic $input1a, $input1b),1993 (variadic $input2a, $input2b),1994 ConstantAttr<I32Attr, "2">:$attr1),1995 (MixedVOperandOp5 $input2a, $input2b, $input1b, $attr1,1996 ConstantStrAttr<StrAttr, "MatchMultiVariadicSubSymbol">)>;1997 1998def MixedVOperandOp7 : TEST_Op<"mixed_variadic_optional_in7",1999 [AttrSizedOperandSegments]> {2000 let arguments = (ins2001 Variadic<I32>:$input1,2002 Optional<I32>:$input2,2003 I32Attr:$attr12004 );2005}2006 2007def : Pat<2008 (MixedVOperandOp7 $input1, $input2, ConstantAttr<I32Attr, "2">:$attr1),2009 (MixedVOperandOp6 $input1, (variadic $input2), $attr1),2010 [(Constraint<CPred<"$0 != Value()">> $input2)]>;2011 2012//===----------------------------------------------------------------------===//2013// Test Patterns (either)2014//===----------------------------------------------------------------------===//2015 2016def TestEitherOpA : TEST_Op<"either_op_a"> {2017 let arguments = (ins AnyInteger:$arg0, AnyInteger:$arg1, AnyInteger:$arg2);2018 let results = (outs I32:$output);2019}2020 2021def TestEitherOpB : TEST_Op<"either_op_b"> {2022 let arguments = (ins AnyInteger:$arg0, AnyInteger:$arg1);2023 let results = (outs I32:$output);2024}2025 2026def TestEitherOpC : TEST_Op<"either_op_c"> {2027 let arguments = (ins AnyI32Attr:$attr, AnyInteger:$arg0, AnyInteger:$arg1);2028 let results = (outs I32:$output);2029}2030 2031def : Pat<(TestEitherOpA (either I32:$arg1, I16:$arg2), $x),2032 (TestEitherOpB $arg2, $x)>;2033 2034def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1, $_), I16:$arg2), $x),2035 (TestEitherOpB $arg2, $x)>;2036 2037def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1, $_),2038 (TestEitherOpB I16:$arg2, $_)),2039 $x),2040 (TestEitherOpB $arg2, $x)>;2041 2042def : Pat<(TestEitherOpC ConstantAttr<I32Attr, "0">, (either $arg1, I32:$arg2)),2043 (TestEitherOpB $arg1, $arg2)>;2044 2045def TestEitherHelperOpA : TEST_Op<"either_helper_op_a"> {2046 let arguments = (ins I32:$arg0);2047 let results = (outs I32:$output);2048}2049 2050def TestEitherHelperOpB : TEST_Op<"either_helper_op_b"> {2051 let arguments = (ins I32:$arg0);2052 let results = (outs I32:$output);2053}2054 2055// This test case ensures `emitOpMatch` doesn't redefine `castedOp{0}` local2056// variables. To trigger this, we must ensure the matcher for2057// `TestEitherHelperOpA` and `TestEitherHelperOpB` are not lifted as a static2058// matcher.2059def : Pat<(TestEitherOpB (either (TestEitherHelperOpA I32:$either_helper_0),2060 (TestEitherHelperOpB I32:$either_helper_1))),2061 (TestEitherOpB $either_helper_0, $either_helper_1)>;2062 2063//===----------------------------------------------------------------------===//2064// Test Patterns (Location)2065//===----------------------------------------------------------------------===//2066 2067// Test that we can specify locations for generated ops.2068def : Pat<(TestLocationSrcOp:$res12069 (TestLocationSrcOp:$res22070 (TestLocationSrcOp:$res3 $input))),2071 (TestLocationDstOp2072 (TestLocationDstOp2073 (TestLocationDstOp $input, (location $res1)),2074 (location "named")),2075 (location "fused", $res2, $res3))>;2076 2077// Test that we can use the location of an op without results2078def : Pat<(TestLocationSrcNoResOp:$loc2079 (TestLocationSrcOp (TestLocationSrcOp $input))),2080 (TestLocationDstNoResOp $input, (location $loc))>;2081 2082//===----------------------------------------------------------------------===//2083// Test Patterns (Type Builders)2084//===----------------------------------------------------------------------===//2085 2086def SourceOp : TEST_Op<"source_op"> {2087 let arguments = (ins AnyInteger:$arg, AnyI32Attr:$tag);2088 let results = (outs AnyInteger);2089}2090 2091// An op without return type deduction.2092def OpX : TEST_Op<"op_x"> {2093 let arguments = (ins AnyInteger:$input);2094 let results = (outs AnyInteger);2095}2096 2097// Test that ops without built-in type deduction can be created in the2098// replacement DAG with an explicitly specified type.2099def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "11">:$attr),2100 (OpX (OpX $val, (returnType "$_builder.getI32Type()")))>;2101// Test NativeCodeCall type builder can accept arguments.2102def SameTypeAs : NativeCodeCall<"$0.getType()">;2103 2104def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "22">:$attr),2105 (OpX (OpX $val, (returnType (SameTypeAs $val))))>;2106 2107// Test multiple return types.2108def MakeI64Type : NativeCodeCall<"$_builder.getI64Type()">;2109def MakeI32Type : NativeCodeCall<"$_builder.getI32Type()">;2110 2111def OneToTwo : TEST_Op<"one_to_two"> {2112 let arguments = (ins AnyInteger);2113 let results = (outs AnyInteger, AnyInteger);2114}2115 2116def TwoToOne : TEST_Op<"two_to_one"> {2117 let arguments = (ins AnyInteger, AnyInteger);2118 let results = (outs AnyInteger);2119}2120 2121def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "33">:$attr),2122 (TwoToOne (OpX (OneToTwo:$res__0 $val, (returnType (MakeI64Type), (MakeI32Type))), (returnType (MakeI32Type))),2123 (OpX $res__1, (returnType (MakeI64Type))))>;2124 2125// Test copy value return type.2126def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "44">:$attr),2127 (OpX (OpX $val, (returnType $val)))>;2128 2129// Test create multiple return types with different methods.2130def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "55">:$attr),2131 (TwoToOne (OneToTwo:$res__0 $val, (returnType $val, "$_builder.getI64Type()")), $res__1)>;2132 2133//===----------------------------------------------------------------------===//2134// Test Patterns (Trailing Directives)2135//===----------------------------------------------------------------------===//2136 2137// Test that we can specify both `location` and `returnType` directives.2138def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "66">:$attr),2139 (TwoToOne (OpX $val, (returnType $val), (location "loc1")),2140 (OpX $val, (location "loc2"), (returnType $val)))>;2141 2142//===----------------------------------------------------------------------===//2143// Test Legalization2144//===----------------------------------------------------------------------===//2145 2146def Test_LegalizerEnum_Success : ConstantStrAttr<StrAttr, "Success">;2147def Test_LegalizerEnum_Failure : ConstantStrAttr<StrAttr, "Failure">;2148 2149def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>;2150def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>;2151def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>;2152def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>;2153def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>;2154def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>;2155def ILLegalOpG : TEST_Op<"illegal_op_g">, Results<(outs I32)>;2156def LegalOpA : TEST_Op<"legal_op_a">,2157 Arguments<(ins StrAttr:$status)>, Results<(outs I32)>;2158def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>;2159def LegalOpC : TEST_Op<"legal_op_c">,2160 Arguments<(ins I32)>, Results<(outs I32)>;2161def LegalOpD : TEST_Op<"legal_op_d">, Arguments<(ins AnyType)>;2162 2163def ConvertBlockArgsOp : TEST_Op<"convert_block_args", [SingleBlock]> {2164 let arguments = (ins UnitAttr:$is_legal, UnitAttr:$replace_with_operand,2165 UnitAttr:$duplicate, Optional<AnyType>:$val);2166 let regions = (region SizedRegion<1>:$body);2167 let assemblyFormat = [{2168 $val2169 (`is_legal` $is_legal^)?2170 (`duplicate` $duplicate^)?2171 (`replace_with_operand` $replace_with_operand^)?2172 $body attr-dict `:` functional-type(operands, results)2173 }];2174}2175 2176// Check that the conversion infrastructure can properly undo the creation of2177// operations where an operation was created before its parent, in this case,2178// in the parent's builder.2179def IllegalOpTerminator : TEST_Op<"illegal_op_terminator", [Terminator]>;2180def IllegalOpWithRegion : TEST_Op<"illegal_op_with_region"> {2181 let skipDefaultBuilders = 1;2182 let builders = [OpBuilder<(ins),2183 [{2184 Region *bodyRegion = $_state.addRegion();2185 OpBuilder::InsertionGuard g($_builder);2186 Block *body = $_builder.createBlock(bodyRegion);2187 $_builder.setInsertionPointToEnd(body);2188 IllegalOpTerminator::create($_builder,$_state.location);2189 }]>];2190}2191def IllegalOpWithRegionAnchor : TEST_Op<"illegal_op_with_region_anchor">;2192 2193// Check that smaller pattern depths are chosen, i.e. prioritize more direct2194// mappings.2195def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>;2196 2197def : Pat<(ILLegalOpA), (ILLegalOpB)>;2198def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>;2199 2200// Check that the higher benefit pattern is taken for multiple legalizations2201// with the same depth.2202def : Pat<(ILLegalOpC), (ILLegalOpD)>;2203def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>;2204 2205def : Pat<(ILLegalOpC), (ILLegalOpE), [], [], (addBenefit 10)>;2206def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>;2207 2208// Check that patterns use the most up-to-date value when being replaced.2209def TestRewriteOp : TEST_Op<"rewrite">,2210 Arguments<(ins AnyType)>, Results<(outs AnyType)>;2211def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>;2212 2213// Check that patterns can specify bounded recursion when rewriting.2214def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> {2215 let arguments = (ins I64Attr:$depth);2216 let assemblyFormat = "$depth attr-dict";2217}2218 2219// Test legalization pattern: this op will be erase and will also erase the2220// producer of its operand.2221def BlackHoleOp : TEST_Op<"blackhole">,2222 Arguments<(ins AnyType)>;2223 2224//===----------------------------------------------------------------------===//2225// Test Type Legalization2226//===----------------------------------------------------------------------===//2227 2228def TestRegionBuilderOp : TEST_Op<"region_builder">;2229def TestReturnOp : TEST_Op<"return", [Pure, ReturnLike, Terminator]> {2230 let arguments = (ins Variadic<AnyType>);2231 let builders = [OpBuilder<(ins),2232 [{ build($_builder, $_state, {}); }]>2233 ];2234}2235def TestCastOp : TEST_Op<"cast">,2236 Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>;2237def TestInvalidOp : TEST_Op<"invalid", [Terminator]>,2238 Arguments<(ins Variadic<AnyType>)>;2239def TestTypeProducerOp : TEST_Op<"type_producer">,2240 Results<(outs AnyType)>;2241def TestValidProducerOp : TEST_Op<"valid_producer">,2242 Results<(outs AnyType)>;2243def TestValidConsumerOp : TEST_Op<"valid_consumer">,2244 Arguments<(ins AnyType)>;2245def TestAnotherTypeProducerOp : TEST_Op<"another_type_producer">,2246 Results<(outs AnyType)>;2247def TestTypeConsumerOp : TEST_Op<"type_consumer">,2248 Arguments<(ins AnyType)>;2249def TestTypeChangerOp : TEST_Op<"type_changer">,2250 Arguments<(ins AnyType)>, Results<(outs AnyType)>;2251def TestValidOp : TEST_Op<"valid", [Terminator]>,2252 Arguments<(ins Variadic<AnyType>)>;2253 2254def TestMergeBlocksOp : TEST_Op<"merge_blocks"> {2255 let summary = "merge_blocks operation";2256 let description = [{2257 Test op with multiple blocks that are merged with Dialect Conversion2258 }];2259 2260 let regions = (region AnyRegion:$body);2261 let results = (outs Variadic<AnyType>:$result);2262}2263 2264def TestRemappedValueRegionOp : TEST_Op<"remapped_value_region",2265 [SingleBlock]> {2266 let summary = "remapped_value_region operation";2267 let description = [{2268 Test op that remaps values that haven't yet been converted in Dialect2269 Conversion.2270 }];2271 2272 let regions = (region SizedRegion<1>:$body);2273 let results = (outs Variadic<AnyType>:$result);2274}2275 2276def TestSignatureConversionUndoOp : TEST_Op<"signature_conversion_undo"> {2277 let regions = (region AnyRegion);2278}2279 2280def TestSignatureConversionNoConverterOp2281 : TEST_Op<"signature_conversion_no_converter"> {2282 let regions = (region AnyRegion);2283}2284 2285//===----------------------------------------------------------------------===//2286// Test parser.2287//===----------------------------------------------------------------------===//2288 2289def ParseIntegerLiteralOp : TEST_Op<"parse_integer_literal"> {2290 let results = (outs Variadic<Index>:$results);2291 let hasCustomAssemblyFormat = 1;2292}2293 2294def ParseWrappedKeywordOp : TEST_Op<"parse_wrapped_keyword"> {2295 let arguments = (ins StrAttr:$keyword);2296 let hasCustomAssemblyFormat = 1;2297}2298 2299def ParseB64BytesOp : TEST_Op<"parse_b64"> {2300 let arguments = (ins StrAttr:$b64);2301 let hasCustomAssemblyFormat = 1;2302}2303 2304//===----------------------------------------------------------------------===//2305// Test region argument list parsing.2306//===----------------------------------------------------------------------===//2307 2308def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> {2309 let summary = "isolated region operation";2310 let description = [{2311 Test op with an isolated region, to test passthrough region arguments. Each2312 argument is of index type.2313 }];2314 2315 let arguments = (ins Index);2316 let regions = (region SizedRegion<1>:$region);2317 let hasCustomAssemblyFormat = 1;2318}2319 2320def SSACFGRegionOp : TEST_Op<"ssacfg_region", [2321 DeclareOpInterfaceMethods<RegionKindInterface>]> {2322 let summary = "operation with an SSACFG region";2323 let description = [{2324 Test op that defines an SSACFG region.2325 }];2326 2327 let regions = (region VariadicRegion<AnyRegion>:$regions);2328 let arguments = (ins Variadic<AnyType>);2329 let results = (outs Variadic<AnyType>);2330}2331 2332def GraphRegionOp : TEST_Op<"graph_region", [2333 DeclareOpInterfaceMethods<RegionKindInterface>]> {2334 let summary = "operation with a graph region";2335 let description = [{2336 Test op that defines a graph region.2337 }];2338 2339 let regions = (region AnyRegion:$region);2340 let assemblyFormat = "attr-dict-with-keyword $region";2341}2342 2343def IsolatedGraphRegionOp : TEST_Op<"isolated_graph_region", [2344 DeclareOpInterfaceMethods<RegionKindInterface>,2345 IsolatedFromAbove]> {2346 let summary = "isolated from above operation with a graph region";2347 let description = [{2348 Test op that defines a graph region which is isolated from above.2349 }];2350 2351 let regions = (region AnyRegion:$region);2352 let assemblyFormat = "attr-dict-with-keyword $region";2353}2354 2355def AffineScopeOp : TEST_Op<"affine_scope", [AffineScope]> {2356 let summary = "affine scope operation";2357 let description = [{2358 Test op that defines a new affine scope.2359 }];2360 2361 let regions = (region SizedRegion<1>:$region);2362 let hasCustomAssemblyFormat = 1;2363}2364 2365//===----------------------------------------------------------------------===//2366// Custom printer/parser2367//===----------------------------------------------------------------------===//2368 2369def CustomDimensionListAttrOp : TEST_Op<"custom_dimension_list_attr"> {2370 let description = [{2371 Test printing/parsing of dimension list attribute.2372 }];2373 let arguments = (ins DenseI64ArrayAttr:$dimension_list);2374 let assemblyFormat = [{2375 `dimension_list` `=` custom<DimensionList>($dimension_list)2376 attr-dict2377 }];2378}2379 2380def OptionalCustomAttrOp : TEST_Op<"optional_custom_attr"> {2381 let description = [{2382 Test using a custom directive as the optional group anchor and the first2383 element to parse. It is expected to return an `OptionalParseResult`.2384 }];2385 let arguments = (ins OptionalAttr<I1Attr>:$attr);2386 let assemblyFormat = [{2387 attr-dict (custom<OptionalCustomParser>($attr)^) : (`bar`)?2388 }];2389}2390 2391//===----------------------------------------------------------------------===//2392// Test OpAsmInterface.2393//===----------------------------------------------------------------------===//2394 2395def AsmInterfaceOp : TEST_Op<"asm_interface_op"> {2396 let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results,2397 AnyType);2398}2399 2400def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> {2401 let results = (outs AnyType);2402}2403 2404//===----------------------------------------------------------------------===//2405// Test ArrayOfAttr2406//===----------------------------------------------------------------------===//2407 2408// Embed the array attributes directly in the assembly format for a nice syntax.2409def ArrayOfAttrOp : TEST_Op<"array_of_attr_op"> {2410 let arguments = (ins TestArrayOfUglyAttrs:$a, TestArrayOfInts:$b,2411 TestArrayOfEnums:$c);2412 let assemblyFormat = "`a` `=` $a `,` `b` `=` $b `,` `c` `=` $c attr-dict";2413}2414 2415//===----------------------------------------------------------------------===//2416// Test SideEffects2417//===----------------------------------------------------------------------===//2418 2419def SideEffectOp : TEST_Op<"side_effect_op",2420 [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,2421 DeclareOpInterfaceMethods<TestEffectOpInterface>]> {2422 let results = (outs AnyType:$result);2423}2424 2425def SideEffectWithRegionOp : TEST_Op<"side_effect_with_region_op",2426 [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,2427 DeclareOpInterfaceMethods<TestEffectOpInterface>]> {2428 let arguments = (ins AnyType:$operand);2429 let results = (outs AnyType:$result);2430 let regions = (region AnyRegion:$region);2431 let assemblyFormat = [{2432 `(` $operand`)` $region attr-dict `:` type($operand) `->` type($result)2433 }];2434}2435 2436//===----------------------------------------------------------------------===//2437// Copy Operation Test2438//===----------------------------------------------------------------------===//2439 2440def CopyOp : TEST_Op<"copy", []> {2441 let description = [{2442 Represents a copy operation.2443 }];2444 let arguments = (ins Res<AnyRankedOrUnrankedMemRef, "", [MemRead]>:$source,2445 Res<AnyRankedOrUnrankedMemRef, "", [MemWrite]>:$target);2446 let assemblyFormat = [{2447 `(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)`2448 attr-dict2449 }];2450}2451 2452//===----------------------------------------------------------------------===//2453// Test Buffer/Tensor2454//===----------------------------------------------------------------------===//2455 2456def RegionYieldOp : TEST_Op<"region_yield",2457 [Pure, ReturnLike, Terminator]> {2458 let description = [{2459 This operation is used in a region and yields the corresponding type for2460 that operation.2461 }];2462 let arguments = (ins AnyType:$result);2463 let assemblyFormat = [{2464 $result `:` type($result) attr-dict2465 }];2466 let builders = [OpBuilder<(ins),2467 [{ build($_builder, $_state, {}); }]>2468 ];2469}2470 2471class BufferBasedOpBase<string mnemonic, list<Trait> traits>2472 : TEST_Op<mnemonic, traits> {2473 let description = [{2474 A buffer based operation, that uses memRefs as input and output.2475 }];2476 let arguments = (ins Arg<AnyRankedOrUnrankedMemRef, "reading",2477 [MemRead]>:$input,2478 Arg<AnyRankedOrUnrankedMemRef, "writing",2479 [MemWrite]>:$output);2480}2481 2482def BufferBasedOp : BufferBasedOpBase<"buffer_based", []>{2483 let assemblyFormat = [{2484 `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`2485 attr-dict2486 }];2487}2488 2489def RegionBufferBasedOp : BufferBasedOpBase<"region_buffer_based",2490 [SingleBlockImplicitTerminator<"RegionYieldOp">]> {2491 let regions = (region AnyRegion:$region);2492 let assemblyFormat = [{2493 `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`2494 $region attr-dict2495 }];2496}2497 2498def TensorBasedOp : TEST_Op<"tensor_based", []> {2499 let description = [{2500 A tensor based operation, that uses a tensor as an input and results in a2501 tensor again.2502 }];2503 let arguments = (ins AnyRankedTensor:$input);2504 let results = (outs AnyRankedTensor:$result);2505 let assemblyFormat = [{2506 `in` `(` $input`:` type($input) `)` `->` type($result) attr-dict2507 }];2508}2509 2510def ReadBufferOp : TEST_Op<"read_buffer", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {2511 let description = [{2512 An operation that reads the buffer operand and dumps its contents.2513 }];2514 let arguments = (ins AnyRankedOrUnrankedMemRef:$buffer);2515}2516 2517def ForwardBufferOp : TEST_Op<"forward_buffer", [Pure]> {2518 let description = [{2519 A pure operation that takes a buffer and returns a buffer. This op does not2520 have any side effects, so it cannot allocate or read a buffer from memory.2521 It must return the input buffer (or a view thereof). This op purposely does2522 does not implement any interface.2523 }];2524 let arguments = (ins AnyRankedOrUnrankedMemRef:$buffer);2525 let results = (outs AnyRankedOrUnrankedMemRef:$result);2526}2527 2528//===----------------------------------------------------------------------===//2529// Test ValueBoundsOpInterface2530//===----------------------------------------------------------------------===//2531 2532def TestValueWithBoundsOp : TEST_Op<"value_with_bounds", [2533 DeclareOpInterfaceMethods<ValueBoundsOpInterface, ["populateBoundsForIndexValue"]>2534 ]> {2535 let description = [{2536 Creates a value with specified [min, max] range for value bounds analysis.2537 2538 Example:2539 2540 ```mlir2541 %0 = test.value_with_bounds { min = 4 : index, max = 5 : index}2542 ```2543 }];2544 let arguments = (ins IndexAttr:$min, IndexAttr:$max);2545 let results = (outs Index:$result);2546 let assemblyFormat = "attr-dict";2547}2548 2549 2550def ReifyBoundOp : TEST_Op<"reify_bound", [Pure]> {2551 let description = [{2552 Reify a bound for the given index-typed value or dimension size of a shaped2553 value. "LB", "EQ" and "UB" bounds are supported. If `scalable` is set,2554 `vscale_min` and `vscale_max` must be provided, which allows computing2555 a bound in terms of "vector.vscale" for a given range of vscale.2556 }];2557 2558 let arguments = (ins AnyType:$var,2559 OptionalAttr<I64Attr>:$dim,2560 DefaultValuedAttr<StrAttr, "\"EQ\"">:$type,2561 UnitAttr:$constant,2562 UnitAttr:$scalable,2563 OptionalAttr<I64Attr>:$vscale_min,2564 OptionalAttr<I64Attr>:$vscale_max);2565 let results = (outs Index:$result);2566 2567 let extraClassDeclaration = [{2568 ::mlir::presburger::BoundType getBoundType();2569 ::mlir::ValueBoundsConstraintSet::Variable getVariable();2570 }];2571 2572 let hasVerifier = 1;2573}2574 2575def CompareOp : TEST_Op<"compare"> {2576 let description = [{2577 Compare `lhs` and `rhs`. A remark is emitted which indicates whether the2578 specified comparison operator was proven to hold. The remark also indicates2579 whether the opposite comparison operator was proven to hold.2580 2581 `var_operands` must have exactly two operands: one for the LHS operand and2582 one for the RHS operand. If `lhs_map` is specified, as many operands as2583 `lhs_map` has inputs are expected instead of the first operand. If `rhs_map`2584 is specified, as many operands as `rhs_map` has inputs are expected instead2585 of the second operand.2586 }];2587 2588 let arguments = (ins Variadic<Index>:$var_operands,2589 DefaultValuedAttr<StrAttr, "\"EQ\"">:$cmp,2590 OptionalAttr<AffineMapAttr>:$lhs_map,2591 OptionalAttr<AffineMapAttr>:$rhs_map,2592 UnitAttr:$compose);2593 let results = (outs);2594 2595 let extraClassDeclaration = [{2596 ::mlir::ValueBoundsConstraintSet::ComparisonOperator2597 getComparisonOperator();2598 ::mlir::ValueBoundsConstraintSet::Variable getLhs();2599 ::mlir::ValueBoundsConstraintSet::Variable getRhs();2600 }];2601 2602 let hasVerifier = 1;2603}2604 2605//===----------------------------------------------------------------------===//2606// Test RegionBranchOpInterface2607//===----------------------------------------------------------------------===//2608 2609def RegionIfYieldOp : TEST_Op<"region_if_yield",2610 [NoMemoryEffect, ReturnLike, Terminator]> {2611 let arguments = (ins Variadic<AnyType>:$results);2612 let assemblyFormat = [{2613 $results `:` type($results) attr-dict2614 }];2615}2616 2617def RegionIfOp : TEST_Op<"region_if",2618 [DeclareOpInterfaceMethods<RegionBranchOpInterface,2619 ["getRegionInvocationBounds",2620 "getEntrySuccessorOperands"]>,2621 SingleBlockImplicitTerminator<"RegionIfYieldOp">,2622 RecursiveMemoryEffects]> {2623 let description =[{2624 Represents an abstract if-then-else-join pattern. In this context, the then2625 and else regions jump to the join region, which finally returns to its2626 parent op.2627 }];2628 2629 let arguments = (ins Variadic<AnyType>);2630 let results = (outs Variadic<AnyType>:$results);2631 let regions = (region SizedRegion<1>:$thenRegion,2632 AnyRegion:$elseRegion,2633 AnyRegion:$joinRegion);2634 let extraClassDeclaration = [{2635 ::mlir::Block::BlockArgListType getThenArgs() {2636 return getBody(0)->getArguments();2637 }2638 ::mlir::Block::BlockArgListType getElseArgs() {2639 return getBody(1)->getArguments();2640 }2641 ::mlir::Block::BlockArgListType getJoinArgs() {2642 return getBody(2)->getArguments();2643 }2644 }];2645 let hasCustomAssemblyFormat = 1;2646}2647 2648def AnyCondOp : TEST_Op<"any_cond",2649 [DeclareOpInterfaceMethods<RegionBranchOpInterface,2650 ["getRegionInvocationBounds"]>,2651 RecursiveMemoryEffects]> {2652 let results = (outs Variadic<AnyType>:$results);2653 let regions = (region AnyRegion:$region);2654}2655 2656def LoopBlockOp : TEST_Op<"loop_block",2657 [DeclareOpInterfaceMethods<RegionBranchOpInterface,2658 ["getEntrySuccessorOperands"]>, RecursiveMemoryEffects]> {2659 2660 let results = (outs F32:$floatResult);2661 let arguments = (ins I32:$init);2662 let regions = (region SizedRegion<1>:$body);2663 2664 let assemblyFormat = [{2665 $init `:` functional-type($init, $floatResult) $body2666 attr-dict-with-keyword2667 }];2668}2669 2670def LoopBlockTerminatorOp : TEST_Op<"loop_block_term",2671 [DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>, Pure,2672 Terminator]> {2673 let arguments = (ins I32:$nextIterArg, F32:$exitArg);2674 2675 let assemblyFormat = [{2676 `iter` $nextIterArg `exit` $exitArg attr-dict2677 }];2678}2679 2680def TestNoTerminatorOp : TEST_Op<"switch_with_no_break", [2681 NoTerminator,2682 DeclareOpInterfaceMethods<RegionBranchOpInterface>2683 ]> {2684 let arguments = (ins Index:$arg, DenseI64ArrayAttr:$cases);2685 let regions = (region VariadicRegion<SizedRegion<1>>:$caseRegions);2686 2687 let assemblyFormat = [{2688 $arg attr-dict custom<SwitchCases>($cases, $caseRegions)2689 }];2690}2691 2692//===----------------------------------------------------------------------===//2693// Test TableGen generated build() methods2694//===----------------------------------------------------------------------===//2695 2696def TableGenConstant : TEST_Op<"tblgen_constant"> {2697 let results = (outs AnyType);2698}2699 2700// No variadic args or results.2701def TableGenBuildOp0 : TEST_Op<"tblgen_build_0"> {2702 let arguments = (ins AnyType:$value);2703 let results = (outs AnyType:$result);2704}2705 2706// Sigle variadic arg and single variadic results.2707def TableGenBuildOp1 : TEST_Op<"tblgen_build_1"> {2708 let arguments = (ins Variadic<AnyType>:$inputs);2709 let results = (outs Variadic<AnyType>:$results);2710}2711 2712// Single variadic arg and non-variadic results.2713def TableGenBuildOp2 : TEST_Op<"tblgen_build_2"> {2714 let arguments = (ins Variadic<AnyType>:$inputs);2715 let results = (outs AnyType:$result);2716}2717 2718// Single variadic arg and multiple variadic results.2719def TableGenBuildOp3 : TEST_Op<"tblgen_build_3", [SameVariadicResultSize]> {2720 let arguments = (ins Variadic<AnyType>:$inputs);2721 let results = (outs Variadic<AnyType>:$resultA, Variadic<AnyType>:$resultB);2722}2723 2724// Single variadic arg, non variadic results, with SameOperandsAndResultType.2725// Tests suppression of ambiguous build methods for operations with2726// SameOperandsAndResultType trait.2727def TableGenBuildOp4 : TEST_Op<"tblgen_build_4", [SameOperandsAndResultType]> {2728 let arguments = (ins Variadic<AnyType>:$inputs);2729 let results = (outs AnyType:$result);2730}2731 2732// Base class for testing `build` methods for ops with2733// InferReturnTypeOpInterface.2734class TableGenBuildInferReturnTypeBaseOp<string mnemonic,2735 list<Trait> traits = []>2736 : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> {2737 let arguments = (ins Variadic<AnyType>:$inputs);2738 let results = (outs AnyType:$result);2739 2740 let extraClassDeclaration = [{2741 static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *,2742 ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,2743 ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,2744 ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {2745 inferredReturnTypes.assign({operands[0].getType()});2746 return ::mlir::success();2747 }2748 }];2749}2750 2751// Op with InferTypeOpInterface and regions.2752def TableGenBuildOp5 : TableGenBuildInferReturnTypeBaseOp<2753 "tblgen_build_5", [InferTypeOpInterface]> {2754 let regions = (region AnyRegion:$body);2755}2756 2757// Two variadic args, non variadic results, with AttrSizedOperandSegments2758// Test build method generation for property conversion & type inference.2759def TableGenBuildOp6 : TEST_Op<"tblgen_build_6", [AttrSizedOperandSegments]> {2760 let arguments = (ins Variadic<AnyType>:$a, Variadic<AnyType>:$b);2761 let results = (outs F32:$result);2762}2763 2764// An inherent attribute. Test collective builders, both those that take properties as2765// properties structs and those that take an attribute dictionary.2766def TableGenBuildOp7 : TEST_Op<"tblgen_build_7", []> {2767 let arguments = (ins BoolAttr:$attr0);2768 let results = (outs);2769}2770 2771//===----------------------------------------------------------------------===//2772// Test BufferPlacement2773//===----------------------------------------------------------------------===//2774 2775def GetTupleElementOp: TEST_Op<"get_tuple_element"> {2776 let description = [{2777 Test op that returns a specified element of the tuple.2778 }];2779 2780 let arguments = (ins2781 TupleOf<[AnyType]>,2782 I32Attr:$index2783 );2784 let results = (outs AnyType);2785}2786 2787def MakeTupleOp: TEST_Op<"make_tuple"> {2788 let description = [{2789 Test op that creates a tuple value from a list of values.2790 }];2791 2792 let arguments = (ins2793 Variadic<AnyType>:$inputs2794 );2795 let results = (outs TupleOf<[AnyType]>);2796}2797 2798//===----------------------------------------------------------------------===//2799// Test Target DataLayout2800//===----------------------------------------------------------------------===//2801 2802def OpWithDataLayoutOp : TEST_Op<"op_with_data_layout",2803 [IsolatedFromAbove, HasDefaultDLTIDataLayout, DataLayoutOpInterface]> {2804 let summary =2805 "An op that uses DataLayout implementation from the Target dialect";2806 let regions = (region VariadicRegion<AnyRegion>:$regions);2807}2808 2809def DataLayoutQueryOp : TEST_Op<"data_layout_query"> {2810 let summary = "A token op recognized by data layout query test pass";2811 let description = [{2812 The data layout query pass pattern-matches this op and attaches to it an2813 array attribute containing the result of data layout query of the result2814 type of this op.2815 }];2816 2817 let results = (outs AnyType:$res);2818}2819 2820//===----------------------------------------------------------------------===//2821// Test Reducer Patterns2822//===----------------------------------------------------------------------===//2823 2824def OpCrashLong : TEST_Op<"op_crash_long"> {2825 let arguments = (ins I32, I32, I32);2826 let results = (outs I32);2827}2828 2829def OpCrashShort : TEST_Op<"op_crash_short"> {2830 let results = (outs I32);2831}2832 2833def : Pat<(OpCrashLong $_, $_, $_), (OpCrashShort)>;2834 2835//===----------------------------------------------------------------------===//2836// Test DestinationStyleOpInterface.2837//===----------------------------------------------------------------------===//2838 2839def TestDestinationStyleOp :2840 TEST_Op<"destination_style_op", [2841 DestinationStyleOpInterface,2842 AttrSizedOperandSegments]> {2843 let arguments = (ins2844 Variadic<AnyType>:$inputs,2845 Variadic<AnyType>:$outputs,2846 Variadic<AnyType>:$other_operands);2847 let results = (outs Variadic<AnyType>:$results);2848 let assemblyFormat = [{2849 attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?2850 (`outs` `(` $outputs^ `:` type($outputs) `)`)?2851 (`(` $other_operands^ `:` type($other_operands) `)`)?2852 (`->` type($results)^)?2853 }];2854 2855 let extraClassDeclaration = [{2856 mlir::MutableOperandRange getDpsInitsMutable() {2857 return getOutputsMutable();2858 }2859 }];2860}2861 2862//===----------------------------------------------------------------------===//2863// Test LinalgConvolutionOpInterface.2864//===----------------------------------------------------------------------===//2865 2866def TestLinalgConvOpNotLinalgOp : TEST_Op<"conv_op_not_linalg_op", [2867 LinalgConvolutionOpInterface]> {2868 let arguments = (ins2869 AnyType:$image, AnyType:$filter, AnyType:$output);2870 let results = (outs AnyRankedTensor:$result);2871}2872 2873def TestLinalgConvOp :2874 TEST_Op<"linalg_conv_op", [AttrSizedOperandSegments, SingleBlock,2875 DestinationStyleOpInterface, LinalgStructuredInterface,2876 LinalgConvolutionOpInterface]> {2877 2878 let arguments = (ins Variadic<AnyType>:$inputs,2879 Variadic<AnyType>:$outputs);2880 let results = (outs Variadic<AnyType>:$results);2881 let regions = (region AnyRegion:$region);2882 2883 let assemblyFormat = [{2884 attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?2885 `outs` `(` $outputs `:` type($outputs) `)`2886 $region (`->` type($results)^)?2887 }];2888 2889 let extraClassDeclaration = [{2890 bool hasIndexSemantics() { return false; }2891 2892 static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,2893 mlir::ArrayRef<mlir::NamedAttribute> attrs,2894 llvm::function_ref<mlir::InFlightDiagnostic()> emitError) {2895 mlir::linalg::YieldOp::create(b,block.getArguments().back());2896 }2897 2898 static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,2899 mlir::ArrayRef<mlir::NamedAttribute>,2900 llvm::function_ref<mlir::InFlightDiagnostic()>)>2901 getRegionBuilder() {2902 return ®ionBuilder;2903 }2904 2905 llvm::SmallVector<mlir::utils::IteratorType> getIteratorTypesArray() {2906 auto attrs = getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");2907 auto range = attrs.getAsValueRange<IteratorTypeAttr, mlir::utils::IteratorType>();2908 return {range.begin(), range.end()};2909 }2910 2911 mlir::ArrayAttr getIndexingMaps() {2912 return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");2913 }2914 2915 std::string getLibraryCallName() {2916 return "";2917 }2918 2919 mlir::MutableOperandRange getDpsInitsMutable() {2920 return getOutputsMutable();2921 }2922 }];2923}2924 2925//===----------------------------------------------------------------------===//2926// Test LinalgFillOpInterface.2927//===----------------------------------------------------------------------===//2928 2929def TestLinalgFillOpNotLinalgOp : TEST_Op<"fill_op_not_linalg_op", [2930 LinalgFillOpInterface]> {2931 let arguments = (ins2932 AnyType:$value, AnyType:$output);2933 let results = (outs AnyRankedTensor:$result);2934}2935 2936def TestLinalgFillOp :2937 TEST_Op<"linalg_fill_op", [AttrSizedOperandSegments, SingleBlock,2938 DestinationStyleOpInterface, LinalgStructuredInterface,2939 LinalgFillOpInterface]> {2940 2941 let arguments = (ins Variadic<AnyType>:$inputs,2942 Variadic<AnyType>:$outputs);2943 let results = (outs Variadic<AnyType>:$results);2944 let regions = (region AnyRegion:$region);2945 2946 let assemblyFormat = [{2947 attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?2948 `outs` `(` $outputs `:` type($outputs) `)`2949 $region (`->` type($results)^)?2950 }];2951 2952 let extraClassDeclaration = [{2953 bool hasIndexSemantics() { return false; }2954 2955 static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,2956 mlir::ArrayRef<mlir::NamedAttribute> attrs,2957 llvm::function_ref<mlir::InFlightDiagnostic()> emitError) {2958 mlir::linalg::YieldOp::create(b,block.getArguments().back());2959 }2960 2961 static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,2962 mlir::ArrayRef<mlir::NamedAttribute>,2963 llvm::function_ref<mlir::InFlightDiagnostic()>)>2964 getRegionBuilder() {2965 return ®ionBuilder;2966 }2967 2968 llvm::SmallVector<mlir::utils::IteratorType> getIteratorTypesArray() {2969 auto attrs = getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");2970 auto range = attrs.getAsValueRange<IteratorTypeAttr, mlir::utils::IteratorType>();2971 return {range.begin(), range.end()};2972 }2973 2974 mlir::ArrayAttr getIndexingMaps() {2975 return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");2976 }2977 2978 std::string getLibraryCallName() {2979 return "";2980 }2981 2982 mlir::MutableOperandRange getDpsInitsMutable() {2983 return getOutputsMutable();2984 }2985 }];2986}2987 2988//===----------------------------------------------------------------------===//2989// Test TilingInterface.2990//===----------------------------------------------------------------------===//2991 2992def Test_TilingNoDpsOp : TEST_Op<"tiling_no_dps_op",2993 [Pure, DeclareOpInterfaceMethods<TilingInterface,2994 ["getIterationDomain",2995 "getLoopIteratorTypes",2996 "getResultTilePosition",2997 "getTiledImplementation"]>]> {2998 let arguments = (ins AnyRankedTensor:$lhs, AnyRankedTensor:$rhs);2999 let results = (outs AnyRankedTensor:$result);3000}3001 3002//===----------------------------------------------------------------------===//3003// Test NVVM RequiresSM trait.3004//===----------------------------------------------------------------------===//3005 3006def TestNVVMRequiresSMOp :3007 TEST_Op<"nvvm_requires_sm_80", [NVVMRequiresSM<80>]> {3008 let arguments = (ins );3009 let assemblyFormat = "attr-dict";3010}3011 3012def TestNVVMRequiresSMArchCondOp :3013 TEST_Op<"nvvm_requires_sm_90a", [NVVMRequiresSMa<[90]>]> {3014 let arguments = (ins );3015 let assemblyFormat = "attr-dict";3016}3017 3018def TestNVVMRequirestSMArchCondMultiOp :3019 TEST_Op<"nvvm_requires_sm_90a_or_sm_100a", [NVVMRequiresSMa<[90, 100]>]> {3020 let arguments = (ins );3021 let assemblyFormat = "attr-dict";3022}3023 3024//===----------------------------------------------------------------------===//3025// Test Ops with Default-Valued String Attributes3026//===----------------------------------------------------------------------===//3027 3028def TestDefaultStrAttrNoValueOp : TEST_Op<"no_str_value"> {3029 let arguments = (ins DefaultValuedAttr<StrAttr, "">:$value);3030 let assemblyFormat = "attr-dict";3031}3032 3033def TestDefaultStrAttrHasValueOp : TEST_Op<"has_str_value"> {3034 let arguments = (ins DefaultValuedStrAttr<StrAttr, "">:$value);3035 let assemblyFormat = "attr-dict";3036}3037 3038def : Pat<(TestDefaultStrAttrNoValueOp $value),3039 (TestDefaultStrAttrHasValueOp ConstantStrAttr<StrAttr, "foo">)>;3040 3041//===----------------------------------------------------------------------===//3042// Test Ops with variadics3043//===----------------------------------------------------------------------===//3044 3045def TestVariadicRewriteSrcOp : TEST_Op<"variadic_rewrite_src_op", [AttrSizedOperandSegments]> {3046 let arguments = (ins3047 Variadic<AnyType>:$arg,3048 AnyType:$brg,3049 Variadic<AnyType>:$crg3050 );3051}3052 3053def TestVariadicRewriteDstOp : TEST_Op<"variadic_rewrite_dst_op", [AttrSizedOperandSegments]> {3054 let arguments = (ins3055 AnyType:$brg,3056 Variadic<AnyType>:$crg,3057 Variadic<AnyType>:$arg3058 );3059}3060 3061def : Pat<(TestVariadicRewriteSrcOp $arg, $brg, $crg),3062 (TestVariadicRewriteDstOp $brg, $crg, $arg)>;3063 3064//===----------------------------------------------------------------------===//3065// Test Ops with Default-Valued Attributes and Differing Print Settings3066//===----------------------------------------------------------------------===//3067 3068def TestDefaultAttrPrintOp : TEST_Op<"default_value_print"> {3069 let arguments = (ins DefaultValuedAttr<I32Attr, "0">:$value_with_default,3070 I32:$operand);3071 let assemblyFormat = "attr-dict $operand";3072}3073 3074//===----------------------------------------------------------------------===//3075// Test Ops with effects3076//===----------------------------------------------------------------------===//3077 3078def TestResource : Resource<"TestResource">;3079 3080def TestEffectsOpA : TEST_Op<"op_with_effects_a"> {3081 let arguments = (ins3082 Arg<Variadic<AnyMemRef>, "", [MemRead]>,3083 Arg<FlatSymbolRefAttr, "", [MemRead]>:$first,3084 Arg<SymbolRefAttr, "", [MemWrite]>:$second,3085 Arg<OptionalAttr<SymbolRefAttr>, "", [MemRead]>:$optional_symbol3086 );3087 3088 let results = (outs Res<AnyMemRef, "", [MemAlloc<TestResource, 0>]>);3089}3090 3091def TestEffectsOpB : TEST_Op<"op_with_effects_b",3092 [MemoryEffects<[MemWrite<TestResource, 0>]>]>;3093 3094def TestEffectsRead : TEST_Op<"op_with_memread",3095 [MemoryEffects<[MemRead]>]> {3096 let results = (outs AnyInteger);3097}3098 3099def TestEffectsWrite : TEST_Op<"op_with_memwrite",3100 [MemoryEffects<[MemWrite]>]>;3101 3102def TestEffectsResult : TEST_Op<"test_effects_result"> {3103 let results = (outs Res<I32, "", [MemAlloc, MemWrite]>);3104}3105 3106//===----------------------------------------------------------------------===//3107// Test Ops with verifiers3108//===----------------------------------------------------------------------===//3109 3110def TestVerifiersOp : TEST_Op<"verifiers",3111 [SingleBlock, NoTerminator, IsolatedFromAbove]> {3112 let arguments = (ins I32:$input);3113 let regions = (region SizedRegion<1>:$region);3114 let hasVerifier = 1;3115 let hasRegionVerifier = 1;3116}3117 3118//===----------------------------------------------------------------------===//3119// Test Loop Op with a graph region3120//===----------------------------------------------------------------------===//3121 3122// Test loop op with a graph region.3123def TestGraphLoopOp : TEST_Op<"graph_loop",3124 [LoopLikeOpInterface, NoMemoryEffect,3125 RecursivelySpeculatable, SingleBlock,3126 RegionKindInterface, HasOnlyGraphRegion]> {3127 let arguments = (ins Variadic<AnyType>:$args);3128 let results = (outs Variadic<AnyType>:$rets);3129 let regions = (region SizedRegion<1>:$body);3130 3131 let assemblyFormat = [{3132 $args $body attr-dict `:` functional-type(operands, results)3133 }];3134 3135 let extraClassDeclaration = [{3136 llvm::SmallVector<mlir::Region *> getLoopRegions() { return {&getBody()}; }3137 }];3138}3139 3140//===----------------------------------------------------------------------===//3141// Test InferIntRangeInterface3142//===----------------------------------------------------------------------===//3143def InferIntRangeType : AnyTypeOf<[AnyInteger, Index, VectorOfNonZeroRankOf<[AnyInteger, Index]>]>;3144 3145def TestWithBoundsOp : TEST_Op<"with_bounds",3146 [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,3147 NoMemoryEffect]> {3148 let description = [{3149 Creates a value with specified [min, max] range for integer range analysis.3150 3151 Example:3152 3153 ```mlir3154 %0 = test.with_bounds { umin = 4 : index, umax = 5 : index, smin = 4 : index, smax = 5 : index } : index3155 ```3156 }];3157 3158 let arguments = (ins APIntAttr:$umin,3159 APIntAttr:$umax,3160 APIntAttr:$smin,3161 APIntAttr:$smax);3162 let results = (outs InferIntRangeType:$fakeVal);3163 3164 let assemblyFormat = "attr-dict `:` type($fakeVal)";3165}3166 3167def TestWithBoundsRegionOp : TEST_Op<"with_bounds_region",3168 [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,3169 SingleBlock, NoTerminator]> {3170 let arguments = (ins APIntAttr:$umin,3171 APIntAttr:$umax,3172 APIntAttr:$smin,3173 APIntAttr:$smax);3174 // The region has one argument of any integer type3175 let regions = (region SizedRegion<1>:$region);3176 let hasCustomAssemblyFormat = 1;3177}3178 3179def TestIncrementOp : TEST_Op<"increment",3180 [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,3181 NoMemoryEffect, AllTypesMatch<["value", "result"]>]> {3182 let arguments = (ins InferIntRangeType:$value);3183 let results = (outs InferIntRangeType:$result);3184 3185 let assemblyFormat = "attr-dict $value `:` type($result)";3186}3187 3188def TestReflectBoundsOp : TEST_Op<"reflect_bounds",3189 [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,3190 AllTypesMatch<["value", "result"]>]> {3191 let description = [{3192 Integer range analysis will update this op to reflect inferred integer range3193 of the input, so it can be checked with FileCheck3194 3195 Example:3196 3197 ```mlir3198 CHECK: test.reflect_bounds {smax = 7 : index, smin = 0 : index, umax = 7 : index, umin = 0 : index}3199 %1 = test.reflect_bounds %0 : index3200 ```3201 }];3202 3203 let arguments = (ins InferIntRangeType:$value,3204 OptionalAttr<APIntAttr>:$umin,3205 OptionalAttr<APIntAttr>:$umax,3206 OptionalAttr<APIntAttr>:$smin,3207 OptionalAttr<APIntAttr>:$smax);3208 let results = (outs InferIntRangeType:$result);3209 3210 let assemblyFormat = "attr-dict $value `:` type($result)";3211}3212 3213//===----------------------------------------------------------------------===//3214// Test ConditionallySpeculatable3215//===----------------------------------------------------------------------===//3216 3217def ConditionallySpeculatableOp : TEST_Op<"conditionally_speculatable_op",3218 [ConditionallySpeculatable, NoMemoryEffect]> {3219 let description = [{3220 Op used to test conditional speculation. This op can be speculatively3221 executed if the input to it is an `arith.constant`.3222 }];3223 3224 let arguments = (ins I32:$input);3225 let results = (outs I32:$result);3226 3227 let extraClassDeclaration = [{3228 ::mlir::Speculation::Speculatability getSpeculatability();3229 }];3230 3231 let extraClassDefinition = [{3232 ::mlir::Speculation::Speculatability3233 ConditionallySpeculatableOp::getSpeculatability() {3234 Operation* definingOp = getInput().getDefiningOp();3235 return definingOp && isa<::mlir::arith::ConstantOp>(definingOp) ?3236 ::mlir::Speculation::Speculatable : ::mlir::Speculation::NotSpeculatable;3237 }3238 }];3239}3240 3241def PureOp : TEST_Op<"always_speculatable_op", [Pure]> {3242 let description = [{3243 Op used to test conditional speculation. This op can always be3244 speculatively executed.3245 }];3246 let results = (outs I32:$result);3247}3248 3249def NeverSpeculatableOp : TEST_Op<"never_speculatable_op", [ConditionallySpeculatable]> {3250 let description = [{3251 Op used to test conditional speculation. This op can never be3252 speculatively executed.3253 }];3254 let results = (outs I32:$result);3255 3256 let extraClassDeclaration = [{3257 ::mlir::Speculation::Speculatability getSpeculatability() {3258 return ::mlir::Speculation::NotSpeculatable;3259 }3260 }];3261}3262 3263def RecursivelySpeculatableOp : TEST_Op<"recursively_speculatable_op", [3264 RecursivelySpeculatable, RecursiveMemoryEffects]> {3265 let description = [{3266 Op used to test conditional speculation. This op can be speculatively3267 executed only if all the ops in the attached region can be.3268 }];3269 let results = (outs I32:$result);3270 let regions = (region SizedRegion<1>:$body);3271}3272 3273//===---------------------------------------------------------------------===//3274// Test CSE3275//===---------------------------------------------------------------------===//3276 3277def TestCSEOfSingleBlockOp : TEST_Op<"cse_of_single_block_op",3278 [SingleBlockImplicitTerminator<"RegionYieldOp">, Pure]> {3279 let arguments = (ins Variadic<AnyType>:$inputs);3280 let results = (outs Variadic<AnyType>:$outputs);3281 let regions = (region SizedRegion<1>:$region);3282 let assemblyFormat = [{3283 attr-dict `inputs` `(` $inputs `)`3284 $region `:` type($inputs) `->` type($outputs)3285 }];3286}3287 3288//===----------------------------------------------------------------------===//3289// Test Ops to upgrade base on the dialect versions3290//===----------------------------------------------------------------------===//3291 3292def TestVersionedOpA : TEST_Op<"versionedA"> {3293 // A previous version of the dialect (let's say 1.*) supported an attribute3294 // named "dimensions":3295 // let arguments = (ins3296 // AnyI64Attr:$dimensions3297 // );3298 3299 // In the current version (2.0) "dimensions" was renamed to "dims", and a new3300 // boolean attribute "modifier" was added. The previous version of the op3301 // corresponds to "modifier=false". We support loading old IR through3302 // upgrading, see `upgradeFromVersion()` in `TestBytecodeDialectInterface`.3303 let arguments = (ins3304 AnyI64Attr:$dims,3305 BoolAttr:$modifier3306 );3307 3308 // Since we use properties to store attributes, we need a custom encoding3309 // reader/writer to handle versioning.3310 let useCustomPropertiesEncoding = 1;3311}3312 3313def TestVersionedOpB : TEST_Op<"versionedB"> {3314 // A previous version of the dialect (let's say 1.*) we encoded TestAttrParams3315 // with a custom encoding:3316 //3317 // #test.attr_params<X, Y> -> { varInt: Y, varInt: X }3318 //3319 // In the current version (2.0) the encoding changed and the two parameters of3320 // the attribute are swapped:3321 //3322 // #test.attr_params<X, Y> -> { varInt: X, varInt: Y }3323 //3324 // We support loading old IR through a custom readAttribute method, see3325 // `readAttribute()` in `TestBytecodeDialectInterface`3326 let arguments = (ins3327 TestAttrParams:$attribute3328 );3329}3330 3331def TestVersionedOpC : TEST_Op<"versionedC"> {3332 let arguments = (ins AnyAttrOf<[TestAttrParams,3333 I32ElementsAttr]>:$attribute3334 );3335}3336 3337//===----------------------------------------------------------------------===//3338// Test Properties3339//===----------------------------------------------------------------------===//3340 3341 3342// Op with a properties struct defined inline.3343def TestOpWithProperties : TEST_Op<"with_properties"> {3344 let assemblyFormat = [{3345 `a` `=` $a `,`3346 `b` `=` $b `,`3347 `c` `=` $c `,`3348 `flag` `=` $flag `,`3349 `array` `=` $array `,`3350 `array32` `=` $array32 attr-dict}];3351 let arguments = (ins3352 I64Prop:$a,3353 StrAttr:$b, // Attributes can directly be used here.3354 StringProp:$c,3355 BoolProp:$flag,3356 IntArrayProp<I64Prop>:$array, // Example of an array.3357 IntArrayProp<I32Prop>:$array32 // Example of an array.3358 );3359}3360 3361def TestOpWithPropertiesAndAttr3362 : TEST_Op<"with_properties_and_attr"> {3363 let assemblyFormat = "$lhs prop-dict attr-dict";3364 3365 let arguments = (ins I32Attr:$lhs, IntProp<"int64_t">:$rhs);3366}3367 3368def TestOpWithPropertiesAndInferredType3369 : TEST_Op<"with_properties_and_inferred_type", [3370 DeclareOpInterfaceMethods<InferTypeOpInterface>3371 ]> {3372 let assemblyFormat = "$lhs prop-dict attr-dict";3373 3374 let arguments = (ins I32Attr:$lhs, IntProp<"int64_t">:$rhs, OptionalAttr<UnitAttr>: $packed);3375 let results = (outs AnyType:$result);3376}3377 3378// Demonstrate how to wrap an existing C++ class named MyPropStruct.3379def MyStructProperty : Property<"MyPropStruct"> {3380 let convertToAttribute = "return $_storage.asAttribute($_ctxt);";3381 let convertFromAttribute = "return MyPropStruct::setFromAttr($_storage, $_attr, $_diag);";3382 let hashProperty = "$_storage.hash();";3383}3384 3385def TestOpWithWrappedProperties : TEST_Op<"with_wrapped_properties"> {3386 let assemblyFormat = "prop-dict attr-dict";3387 let arguments = (ins3388 MyStructProperty:$prop3389 );3390}3391 3392// Same as above, but without a custom `hashProperty` field, checking3393// that ADL is correctly working.3394def MyStructProperty2 : Property<"MyPropStruct"> {3395 let convertToAttribute = "return $_storage.asAttribute($_ctxt);";3396 let convertFromAttribute = "return MyPropStruct::setFromAttr($_storage, $_attr, $_diag);";3397}3398 3399def TestOpWithWrappedProperties2 : TEST_Op<"with_wrapped_properties2"> {3400 let assemblyFormat = "prop-dict attr-dict";3401 let arguments = (ins3402 MyStructProperty2:$prop3403 );3404}3405 3406def TestOpWithEmptyProperties : TEST_Op<"empty_properties"> {3407 let assemblyFormat = "prop-dict attr-dict";3408 let arguments = (ins);3409}3410 3411def TestOpUsingPropertyInCustom : TEST_Op<"using_property_in_custom"> {3412 let assemblyFormat = "custom<UsingPropertyInCustom>($prop) attr-dict";3413 let arguments = (ins IntArrayProp<I64Prop>:$prop);3414}3415 3416def TestOpUsingPropertyInCustomAndOther3417 : TEST_Op<"using_property_in_custom_and_other"> {3418 let assemblyFormat = "custom<UsingPropertyInCustom>($prop) prop-dict attr-dict";3419 let arguments = (ins3420 IntArrayProp<I64Prop>:$prop,3421 I64Prop:$other3422 );3423}3424 3425def TestOpWithVariadicSegmentProperties : TEST_Op<"variadic_segment_prop",3426 [AttrSizedOperandSegments, AttrSizedResultSegments]> {3427 let arguments = (ins Variadic<I64>:$a1, Variadic<I64>:$a2);3428 let results = (outs Variadic<I64>:$b1, Variadic<I64>:$b2);3429 let assemblyFormat = [{3430 $a1 `:` $a2 `:` type($b1) `:` type($b2) prop-dict attr-dict `end`3431 }];3432}3433 3434def TestOpUsingPropertyRefInCustom : TEST_Op<"using_property_ref_in_custom"> {3435 let assemblyFormat = "custom<IntProperty>($first) `+` custom<SumProperty>($second, ref($first)) attr-dict";3436 let arguments = (ins IntProp<"int64_t">:$first, IntProp<"int64_t">:$second);3437}3438 3439def IntPropertyWithWorseBytecode : Property<"int64_t"> {3440 let writeToMlirBytecode = writeMlirBytecodeWithConvertToAttribute;3441 3442 let readFromMlirBytecode = readMlirBytecodeUsingConvertFromAttribute;3443}3444 3445def TestOpUsingIntPropertyWithWorseBytecode3446 : TEST_Op<"using_int_property_with_worse_bytecode"> {3447 let arguments = (ins IntPropertyWithWorseBytecode:$value);3448}3449 3450// Op with a properties struct defined out-of-line. The struct has custom3451// printer/parser.3452 3453def PropertiesWithCustomPrint : Property<"PropertiesWithCustomPrint"> {3454 let convertToAttribute = [{3455 return getPropertiesAsAttribute($_ctxt, $_storage);3456 }];3457 let convertFromAttribute = [{3458 return setPropertiesFromAttribute($_storage, $_attr, $_diag);3459 }];3460 let hashProperty = [{3461 computeHash($_storage);3462 }];3463}3464 3465def TestOpWithNiceProperties : TEST_Op<"with_nice_properties"> {3466 let assemblyFormat = "prop-dict attr-dict";3467 let arguments = (ins3468 PropertiesWithCustomPrint:$prop3469 );3470 let extraClassDeclaration = [{3471 void printProperties(::mlir::MLIRContext *ctx, ::mlir::OpAsmPrinter &p,3472 const Properties &prop,3473 ::mlir::ArrayRef<::llvm::StringRef> elidedProps);3474 static ::mlir::ParseResult parseProperties(::mlir::OpAsmParser &parser,3475 ::mlir::OperationState &result);3476 static ::llvm::LogicalResult readFromMlirBytecode(3477 ::mlir::DialectBytecodeReader &,3478 test::PropertiesWithCustomPrint &prop);3479 static void writeToMlirBytecode(3480 ::mlir::DialectBytecodeWriter &,3481 const test::PropertiesWithCustomPrint &prop);3482 }];3483 let extraClassDefinition = [{3484 ::llvm::LogicalResult TestOpWithNiceProperties::readFromMlirBytecode(3485 ::mlir::DialectBytecodeReader &reader,3486 test::PropertiesWithCustomPrint &prop) {3487 StringRef label;3488 uint64_t value;3489 if (failed(reader.readString(label)) || failed(reader.readVarInt(value)))3490 return failure();3491 prop.label = std::make_shared<std::string>(label.str());3492 prop.value = value;3493 return success();3494 }3495 void TestOpWithNiceProperties::writeToMlirBytecode(3496 ::mlir::DialectBytecodeWriter &writer,3497 const test::PropertiesWithCustomPrint &prop) {3498 writer.writeOwnedString(*prop.label);3499 writer.writeVarInt(prop.value);3500 }3501 void TestOpWithNiceProperties::printProperties(::mlir::MLIRContext *ctx,3502 ::mlir::OpAsmPrinter &p, const Properties &prop,3503 ::mlir::ArrayRef<::llvm::StringRef> elidedProps) {3504 customPrintProperties(p, prop.prop);3505 }3506 ::mlir::ParseResult TestOpWithNiceProperties::parseProperties(3507 ::mlir::OpAsmParser &parser,3508 ::mlir::OperationState &result) {3509 Properties &prop = result.getOrAddProperties<Properties>();3510 if (customParseProperties(parser, prop.prop))3511 return failure();3512 return success();3513 }3514 }];3515}3516 3517def VersionedProperties : Property<"VersionedProperties"> {3518 let convertToAttribute = [{3519 return getPropertiesAsAttribute($_ctxt, $_storage);3520 }];3521 let convertFromAttribute = [{3522 return setPropertiesFromAttribute($_storage, $_attr, $_diag);3523 }];3524 let hashProperty = [{3525 computeHash($_storage);3526 }];3527}3528 3529def TestOpWithVersionedProperties : TEST_Op<"with_versioned_properties"> {3530 let assemblyFormat = "prop-dict attr-dict";3531 let arguments = (ins3532 VersionedProperties:$prop3533 );3534 let extraClassDeclaration = [{3535 void printProperties(::mlir::MLIRContext *ctx, ::mlir::OpAsmPrinter &p,3536 const Properties &prop,3537 ::mlir::ArrayRef<::llvm::StringRef> elidedProps);3538 static ::mlir::ParseResult parseProperties(::mlir::OpAsmParser &parser,3539 ::mlir::OperationState &result);3540 static ::llvm::LogicalResult readFromMlirBytecode(3541 ::mlir::DialectBytecodeReader &,3542 test::VersionedProperties &prop);3543 static void writeToMlirBytecode(3544 ::mlir::DialectBytecodeWriter &,3545 const test::VersionedProperties &prop);3546 }];3547 let extraClassDefinition = [{3548 void TestOpWithVersionedProperties::printProperties(::mlir::MLIRContext *ctx,3549 ::mlir::OpAsmPrinter &p, const Properties &prop,3550 ::mlir::ArrayRef<::llvm::StringRef> elidedProps) {3551 customPrintProperties(p, prop.prop);3552 }3553 ::mlir::ParseResult TestOpWithVersionedProperties::parseProperties(3554 ::mlir::OpAsmParser &parser,3555 ::mlir::OperationState &result) {3556 Properties &prop = result.getOrAddProperties<Properties>();3557 if (customParseProperties(parser, prop.prop))3558 return failure();3559 return success();3560 }3561 }];3562}3563 3564def TestOpWithDefaultValuedProperties : TEST_Op<"with_default_valued_properties"> {3565 let assemblyFormat = [{3566 ($a^) : (`na`)?3567 ($b^)?3568 ($c^)?3569 ($unit^)?3570 attr-dict3571 }];3572 let arguments = (ins DefaultValuedAttr<I32Attr, "0">:$a,3573 DefaultValuedProp<StringProp, "\"\"">:$b,3574 DefaultValuedProp<IntProp<"int32_t">, "-1">:$c,3575 UnitProp:$unit);3576}3577 3578def TestOpWithOptionalProperties : TEST_Op<"with_optional_properties"> {3579 let assemblyFormat = [{3580 (`anAttr` `=` $anAttr^)?3581 (`simple` `=` $simple^)?3582 (`simplei8` `=` $simplei8^)?3583 (`simpleui8` `=` $simpleui8^)?3584 (`nonTrivialStorage` `=` $nonTrivialStorage^)?3585 (`hasDefault` `=` $hasDefault^)?3586 (`nested` `=` $nested^)?3587 (`longSyntax` `=` $longSyntax^)?3588 (`hasUnit` $hasUnit^)?3589 (`maybeUnit` `=` $maybeUnit^)?3590 attr-dict3591 }];3592 let arguments = (ins3593 OptionalAttr<I32Attr>:$anAttr,3594 OptionalProp<I64Prop>:$simple,3595 OptionalProp<IntProp<"int8_t">>:$simplei8,3596 OptionalProp<IntProp<"uint8_t">>:$simpleui8,3597 OptionalProp<StringProp>:$nonTrivialStorage,3598 // Confirm that properties with default values now default to nullopt and have3599 // the long syntax.3600 OptionalProp<DefaultValuedProp<I64Prop, "0">>:$hasDefault,3601 OptionalProp<OptionalProp<I64Prop>>:$nested,3602 OptionalProp<StringProp, 0>:$longSyntax,3603 UnitProp:$hasUnit,3604 OptionalProp<UnitProp>:$maybeUnit);3605}3606 3607def TestOpWithArrayProperties : TEST_Op<"with_array_properties"> {3608 let assemblyFormat = [{3609 `ints` `=` $ints3610 `strings` `=` $strings3611 `nested` `=` $nested3612 `opt` `=` $opt3613 `explicitOptions` `=` $explicitOptions3614 `explicitUnits` `=` $explicitUnits3615 ($hasDefault^ `thats_has_default`)?3616 attr-dict3617 }];3618 let arguments = (ins3619 ArrayProp<I64Prop>:$ints,3620 ArrayProp<StringProp>:$strings,3621 ArrayProp<ArrayProp<I32Prop>>:$nested,3622 OptionalProp<ArrayProp<I32Prop>>:$opt,3623 ArrayProp<OptionalProp<I64Prop>>:$explicitOptions,3624 ArrayProp<UnitProp>:$explicitUnits,3625 DefaultValuedProp<ArrayProp<I64Prop>,3626 "::llvm::ArrayRef<int64_t>{}", "::llvm::SmallVector<int64_t>{}">:$hasDefault3627 );3628}3629 3630def NonNegativeI64Prop : ConfinedProp<I64Prop,3631 CPred<"$_self >= 0">, "non-negative int64_t">;3632 3633class NonEmptyArray<Property p> : ConfinedProp3634 <ArrayProp<p>, Neg<CPred<"$_self.empty()">>,3635 "non-empty array of " # p.summary>;3636 3637def OpWithPropertyPredicates : TEST_Op<"op_with_property_predicates"> {3638 let arguments = (ins3639 NonNegativeI64Prop:$scalar,3640 OptionalProp<NonNegativeI64Prop>:$optional,3641 DefaultValuedProp<NonNegativeI64Prop, "0">:$defaulted,3642 ConfinedProp<NonNegativeI64Prop,3643 CPred<"$_self <= 5">, "between 0 and 5">:$more_constrained,3644 ArrayProp<NonNegativeI64Prop>:$array,3645 NonEmptyArray<I64Prop>:$non_empty_unconstrained,3646 NonEmptyArray<NonNegativeI64Prop>:$non_empty_constrained,3647 // Test applying predicates when the fromStorage() on the optional<> isn't trivial.3648 OptionalProp<NonEmptyArray<NonNegativeI64Prop>>:$non_empty_optional,3649 I64Prop:$unconstrained3650 );3651 let assemblyFormat = "attr-dict prop-dict";3652}3653 3654def TestPropPatternOp1 : TEST_Op<"prop_pattern_op_1"> {3655 let arguments = (ins3656 StringProp:$tag,3657 I64Prop:$val,3658 BoolProp:$cond3659 );3660 let results = (outs I32:$results);3661 let assemblyFormat = "$tag $val $cond attr-dict";3662}3663 3664def TestPropPatternOp2 : TEST_Op<"prop_pattern_op_2"> {3665 let arguments = (ins3666 I32:$input,3667 StringProp:$tag3668 );3669 let assemblyFormat = "$input $tag attr-dict";3670}3671 3672def : Pat<3673 (TestPropPatternOp1 $tag, NonNegativeI64Prop:$val, ConstantProp<BoolProp, "false">),3674 (TestPropPatternOp1 $tag, (NativeCodeCall<"$0 + 1"> $val), ConstantProp<BoolProp, "true">)>;3675 3676def : Pat<3677 (TestPropPatternOp2 (TestPropPatternOp1 $tag1, $val, ConstantProp<BoolProp, "true">),3678 PropConstraint<CPred<"!$_self.empty()">, "non-empty string">:$tag2),3679 (TestPropPatternOp23680 (TestPropPatternOp1 $tag1,3681 (NativeCodeCall<"-($0)"> $val),3682 ConstantProp<BoolProp, "false">),3683 (NativeCodeCall<"$0.str() + \".\" + $1.str()"> $tag1, $tag2))3684>;3685 3686//===----------------------------------------------------------------------===//3687// Test Dataflow3688//===----------------------------------------------------------------------===//3689 3690def TestCallAndStoreOp : TEST_Op<"call_and_store",3691 [DeclareOpInterfaceMethods<CallOpInterface>]> {3692 let arguments = (ins3693 SymbolRefAttr:$callee,3694 Arg<AnyMemRef, "", [MemWrite]>:$address,3695 Variadic<AnyType>:$callee_operands,3696 BoolAttr:$store_before_call,3697 OptionalAttr<DictArrayAttr>:$arg_attrs,3698 OptionalAttr<DictArrayAttr>:$res_attrs3699 );3700 let results = (outs3701 Variadic<AnyType>:$results3702 );3703 let assemblyFormat =3704 "$callee `(` $callee_operands `)` `,` $address attr-dict "3705 "`:` functional-type(operands, results)";3706}3707 3708def TestCallOnDeviceOp : TEST_Op<"call_on_device",3709 [DeclareOpInterfaceMethods<CallOpInterface>]> {3710 let arguments = (ins3711 SymbolRefAttr:$callee,3712 Variadic<AnyType>:$forwarded_operands,3713 AnyType:$non_forwarded_device_operand,3714 OptionalAttr<DictArrayAttr>:$arg_attrs,3715 OptionalAttr<DictArrayAttr>:$res_attrs3716 );3717 let results = (outs3718 Variadic<AnyType>:$results3719 );3720 let assemblyFormat =3721 "$callee `(` $forwarded_operands `)` `,` $non_forwarded_device_operand "3722 "attr-dict `:` functional-type(operands, results)";3723}3724 3725def TestStoreWithARegion : TEST_Op<"store_with_a_region",3726 [DeclareOpInterfaceMethods<RegionBranchOpInterface>,3727 SingleBlock]> {3728 let arguments = (ins3729 Arg<AnyMemRef, "", [MemWrite]>:$address,3730 BoolAttr:$store_before_region3731 );3732 let regions = (region AnyRegion:$body);3733 let assemblyFormat =3734 "$address attr-dict-with-keyword regions `:` type($address)";3735}3736 3737def TestStoreWithALoopRegion : TEST_Op<"store_with_a_loop_region",3738 [DeclareOpInterfaceMethods<RegionBranchOpInterface>,3739 SingleBlock]> {3740 let arguments = (ins3741 Arg<AnyMemRef, "", [MemWrite]>:$address,3742 BoolAttr:$store_before_region3743 );3744 let regions = (region AnyRegion:$body);3745 let assemblyFormat =3746 "$address attr-dict-with-keyword regions `:` type($address)";3747}3748 3749def TestStoreWithARegionTerminator : TEST_Op<"store_with_a_region_terminator",3750 [ReturnLike, Terminator, NoMemoryEffect]> {3751 let assemblyFormat = "attr-dict";3752}3753 3754def TestOpOptionallyImplementingInterface3755 : TEST_Op<"op_optionally_implementing_interface",3756 [TestOptionallyImplementedOpInterface]> {3757 let arguments = (ins BoolAttr:$implementsInterface);3758}3759 3760//===----------------------------------------------------------------------===//3761// Test Mem2Reg & SROA3762//===----------------------------------------------------------------------===//3763 3764def TestMultiSlotAlloca : TEST_Op<"multi_slot_alloca",3765 [DeclareOpInterfaceMethods<PromotableAllocationOpInterface>,3766 DeclareOpInterfaceMethods<DestructurableAllocationOpInterface>]> {3767 let results = (outs Variadic<MemRefOf<[I32]>>:$results);3768 let assemblyFormat = "attr-dict `:` functional-type(operands, results)";3769}3770 3771//===----------------------------------------------------------------------===//3772// Test allocation Ops3773//===----------------------------------------------------------------------===//3774 3775def TestAllocWithMultipleResults : TEST_Op<"alloc_with_multiple_results"> {3776 let results = (outs Index:$index,3777 Res<AnyMemRef, "", [MemAlloc]>:$memref);3778 let assemblyFormat = [{3779 attr-dict `:` type($index) `,` type($memref)3780 }];3781}3782 3783//===----------------------------------------------------------------------===//3784// Test Ops bufferization3785//===----------------------------------------------------------------------===//3786 3787def TestDummyTensorOp : TEST_Op<"dummy_tensor_op",3788 [DeclareOpInterfaceMethods<BufferizableOpInterface,3789 ["bufferize", "bufferizesToMemoryRead",3790 "bufferizesToMemoryWrite", "getAliasingValues"]>]> {3791 let arguments = (ins3792 Arg<Bufferization_TensorLikeTypeInterface>:$input3793 );3794 let results = (outs3795 Arg<Bufferization_TensorLikeTypeInterface>:$output3796 );3797 3798 let extraClassDefinition = [{3799 bool test::TestDummyTensorOp::bufferizesToMemoryRead(::mlir::OpOperand&,3800 const ::mlir::bufferization::AnalysisState&) {3801 return true;3802 }3803 bool test::TestDummyTensorOp::bufferizesToMemoryWrite(::mlir::OpOperand&,3804 const ::mlir::bufferization::AnalysisState&) {3805 return true;3806 }3807 ::mlir::bufferization::AliasingValueList3808 test::TestDummyTensorOp::getAliasingValues(::mlir::OpOperand&,3809 const ::mlir::bufferization::AnalysisState&) {3810 return {};3811 }3812 }];3813}3814 3815def TestDummyMemrefOp : TEST_Op<"dummy_memref_op", []> {3816 let arguments = (ins3817 Arg<Bufferization_BufferLikeTypeInterface>:$input3818 );3819 let results = (outs3820 Arg<Bufferization_BufferLikeTypeInterface>:$output3821 );3822}3823 3824def TestCreateTensorOp : TEST_Op<"create_tensor_op",3825 [DeclareOpInterfaceMethods<BufferizableOpInterface,3826 ["bufferize", "getBufferType", "bufferizesToMemoryRead",3827 "bufferizesToMemoryWrite", "getAliasingValues",3828 "bufferizesToAllocation"]>]> {3829 let arguments = (ins);3830 let results = (outs Arg<Bufferization_TensorLikeTypeInterface>:$output);3831 let extraClassDefinition = [{3832 bool test::TestCreateTensorOp::bufferizesToMemoryRead(::mlir::OpOperand&,3833 const ::mlir::bufferization::AnalysisState&) {3834 return true;3835 }3836 bool test::TestCreateTensorOp::bufferizesToMemoryWrite(::mlir::OpOperand&,3837 const ::mlir::bufferization::AnalysisState&) {3838 return true;3839 }3840 bool test::TestCreateTensorOp::bufferizesToAllocation(mlir::Value value) {3841 return false;3842 }3843 3844 ::mlir::bufferization::AliasingValueList3845 test::TestCreateTensorOp::getAliasingValues(::mlir::OpOperand&,3846 const ::mlir::bufferization::AnalysisState&) {3847 return {};3848 }3849 }];3850}3851 3852def TestCreateMemrefOp : TEST_Op<"create_memref_op"> {3853 let arguments = (ins);3854 let results = (outs Arg<Bufferization_BufferLikeTypeInterface>:$output);3855}3856 3857//===----------------------------------------------------------------------===//3858// Test assembly format references3859//===----------------------------------------------------------------------===//3860 3861def TestOpWithRegionRef : TEST_Op<"dummy_op_with_region_ref", [NoTerminator]> {3862 let regions = (region AnyRegion:$body);3863 let assemblyFormat = [{3864 $body attr-dict custom<DummyRegionRef>(ref($body))3865 }];3866}3867 3868def TestOpWithSuccessorRef : TEST_Op<"dummy_op_with_successor_ref"> {3869 let successors = (successor AnySuccessor:$successor);3870 let assemblyFormat = [{3871 $successor attr-dict custom<DummySuccessorRef>(ref($successor))3872 }];3873}3874 3875def CallWithSegmentsOp : TEST_Op<"call_with_segments",3876 [AttrSizedOperandSegments,3877 DeclareOpInterfaceMethods<CallOpInterface>]> {3878 let summary = "test call op with segmented args";3879 let arguments = (ins3880 FlatSymbolRefAttr:$callee,3881 Variadic<AnyType>:$prefix, // non-arg segment (e.g., 'in')3882 Variadic<AnyType>:$args, // <-- the call *arguments* segment3883 Variadic<AnyType>:$suffix // non-arg segment (e.g., 'out')3884 );3885 let results = (outs);3886 let assemblyFormat = [{3887 $callee `(` $prefix `:` type($prefix) `)`3888 `(` $args `:` type($args) `)`3889 `(` $suffix `:` type($suffix) `)` attr-dict3890 }];3891 3892 // Provide stub implementations for the ArgAndResultAttrsOpInterface.3893 let extraClassDeclaration = [{3894 ::mlir::ArrayAttr getArgAttrsAttr() { return {}; }3895 ::mlir::ArrayAttr getResAttrsAttr() { return {}; }3896 void setArgAttrsAttr(::mlir::ArrayAttr) {}3897 void setResAttrsAttr(::mlir::ArrayAttr) {}3898 ::mlir::Attribute removeArgAttrsAttr() { return {}; }3899 ::mlir::Attribute removeResAttrsAttr() { return {}; }3900 }];3901 3902 let extraClassDefinition = [{3903 ::mlir::CallInterfaceCallable $cppClass::getCallableForCallee() {3904 if (auto sym = (*this)->getAttrOfType<::mlir::SymbolRefAttr>("callee"))3905 return ::mlir::CallInterfaceCallable(sym);3906 return ::mlir::CallInterfaceCallable();3907 }3908 void $cppClass::setCalleeFromCallable(::mlir::CallInterfaceCallable callee) {3909 if (auto sym = callee.dyn_cast<::mlir::SymbolRefAttr>())3910 (*this)->setAttr("callee", sym);3911 else3912 (*this)->removeAttr("callee");3913 }3914 }];3915}3916 3917 3918#endif // TEST_OPS3919