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-exception 6// 7//===----------------------------------------------------------------------===// 8 9#ifndef TEST_OPS 10#define TEST_OPS 11 12include "mlir/Dialect/DLTI/DLTIBase.td" 13include "mlir/IR/OpBase.td" 14include "mlir/IR/OpAsmInterface.td" 15include "mlir/IR/RegionKindInterface.td" 16include "mlir/IR/SymbolInterfaces.td" 17include "mlir/Interfaces/CallInterfaces.td" 18include "mlir/Interfaces/ControlFlowInterfaces.td" 19include "mlir/Interfaces/CopyOpInterface.td" 20include "mlir/Interfaces/DataLayoutInterfaces.td" 21include "mlir/Interfaces/InferTypeOpInterface.td" 22include "mlir/Interfaces/SideEffectInterfaces.td" 23include "mlir/Dialect/Linalg/IR/LinalgInterfaces.td" 24include "TestInterfaces.td" 25 26def Test_Dialect : Dialect { 27 let name = "test"; 28 let cppNamespace = "::test"; 29 let hasCanonicalizer = 1; 30 let hasConstantMaterializer = 1; 31 let hasOperationAttrVerify = 1; 32 let hasRegionArgAttrVerify = 1; 33 let hasRegionResultAttrVerify = 1; 34 let hasOperationInterfaceFallback = 1; 35 let hasNonDefaultDestructor = 1; 36 let dependentDialects = ["::mlir::DLTIDialect"]; 37 38 let extraClassDeclaration = [{ 39 void registerAttributes(); 40 void registerTypes(); 41 42 ::mlir::Attribute parseAttribute(::mlir::DialectAsmParser &parser, 43 ::mlir::Type type) const override; 44 void printAttribute(::mlir::Attribute attr, 45 ::mlir::DialectAsmPrinter &printer) const override; 46 47 // Provides a custom printing/parsing for some operations. 48 ::llvm::Optional<ParseOpHook> 49 getParseOperationHook(::llvm::StringRef opName) const override; 50 ::llvm::unique_function<void(::mlir::Operation *, 51 ::mlir::OpAsmPrinter &printer)> 52 getOperationPrinter(::mlir::Operation *op) const override; 53 54 private: 55 // Storage for a custom fallback interface. 56 void *fallbackEffectOpInterfaces; 57 58 }]; 59} 60 61class TEST_Op<string mnemonic, list<OpTrait> traits = []> : 62 Op<Test_Dialect, mnemonic, traits>; 63 64//===----------------------------------------------------------------------===// 65// Test Types 66//===----------------------------------------------------------------------===// 67 68def IntTypesOp : TEST_Op<"int_types"> { 69 let results = (outs 70 AnyI16:$any_i16, 71 SI32:$si32, 72 UI64:$ui64, 73 AnyInteger:$any_int 74 ); 75} 76 77def ComplexF64 : Complex<F64>; 78def ComplexOp : TEST_Op<"complex_f64"> { 79 let results = (outs ComplexF64); 80} 81 82def ComplexTensorOp : TEST_Op<"complex_f64_tensor"> { 83 let results = (outs TensorOf<[ComplexF64]>); 84} 85 86def TupleOp : TEST_Op<"tuple_32_bit"> { 87 let results = (outs TupleOf<[I32, F32]>); 88} 89 90def NestedTupleOp : TEST_Op<"nested_tuple_32_bit"> { 91 let results = (outs NestedTupleOf<[I32, F32]>); 92} 93 94def TakesStaticMemRefOp : TEST_Op<"takes_static_memref"> { 95 let arguments = (ins AnyStaticShapeMemRef:$x); 96} 97 98def RankLessThan2I8F32MemRefOp : TEST_Op<"rank_less_than_2_I8_F32_memref"> { 99 let results = (outs MemRefRankOf<[I8, F32], [0, 1]>); 100} 101 102def NDTensorOfOp : TEST_Op<"nd_tensor_of"> { 103 let arguments = (ins 104 0DTensorOf<[F32]>:$arg0, 105 1DTensorOf<[F32]>:$arg1, 106 2DTensorOf<[I16]>:$arg2, 107 3DTensorOf<[I16]>:$arg3, 108 4DTensorOf<[I16]>:$arg4 109 ); 110} 111 112def RankedTensorOp : TEST_Op<"ranked_tensor_op"> { 113 let arguments = (ins AnyRankedTensor:$input); 114} 115 116def MultiTensorRankOf : TEST_Op<"multi_tensor_rank_of"> { 117 let arguments = (ins 118 TensorRankOf<[I8, I32, F32], [0, 1]>:$arg0 119 ); 120} 121 122def TEST_TestType : DialectType<Test_Dialect, 123 CPred<"$_self.isa<::test::TestType>()">, "test">, 124 BuildableType<"$_builder.getType<::test::TestType>()">; 125 126//===----------------------------------------------------------------------===// 127// Test Symbols 128//===----------------------------------------------------------------------===// 129 130def SymbolOp : TEST_Op<"symbol", [Symbol]> { 131 let summary = "operation which defines a new symbol"; 132 let arguments = (ins StrAttr:$sym_name, 133 OptionalAttr<StrAttr>:$sym_visibility); 134} 135 136def SymbolScopeOp : TEST_Op<"symbol_scope", 137 [SymbolTable, SingleBlockImplicitTerminator<"TerminatorOp">]> { 138 let summary = "operation which defines a new symbol table"; 139 let regions = (region SizedRegion<1>:$region); 140} 141 142def SymbolTableRegionOp : TEST_Op<"symbol_table_region", [SymbolTable]> { 143 let summary = "operation which defines a new symbol table without a " 144 "restriction on a terminator"; 145 let regions = (region SizedRegion<1>:$region); 146} 147 148//===----------------------------------------------------------------------===// 149// Test Operands 150//===----------------------------------------------------------------------===// 151 152def MixedNormalVariadicOperandOp : TEST_Op< 153 "mixed_normal_variadic_operand", [SameVariadicOperandSize]> { 154 let arguments = (ins 155 Variadic<AnyTensor>:$input1, 156 AnyTensor:$input2, 157 Variadic<AnyTensor>:$input3 158 ); 159} 160def VariadicWithSameOperandsResult : 161 TEST_Op<"variadic_with_same_operand_results", 162 [SameOperandsAndResultType]> { 163 let arguments = (ins Variadic<AnySignlessInteger>:$operands); 164 let results = (outs AnySignlessInteger:$result); 165} 166 167def SameOperandsResultType : TEST_Op< 168 "same_operand_result_type", [SameOperandsAndResultType]> { 169 let arguments = (ins AnyTensor:$operand); 170 let results = (outs AnyTensor:$result); 171} 172 173//===----------------------------------------------------------------------===// 174// Test Results 175//===----------------------------------------------------------------------===// 176 177def MixedNormalVariadicResults : TEST_Op< 178 "mixed_normal_variadic_result", [SameVariadicResultSize]> { 179 let results = (outs 180 Variadic<AnyTensor>:$output1, 181 AnyTensor:$output2, 182 Variadic<AnyTensor>:$output3 183 ); 184} 185 186//===----------------------------------------------------------------------===// 187// Test Attributes 188//===----------------------------------------------------------------------===// 189 190def NonNegIntAttrOp : TEST_Op<"non_negative_int_attr"> { 191 let arguments = (ins 192 Confined<I32Attr, [IntNonNegative]>:$i32attr, 193 Confined<I64Attr, [IntNonNegative]>:$i64attr 194 ); 195} 196 197def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> { 198 let arguments = (ins 199 Confined<I32Attr, [IntPositive]>:$i32attr, 200 Confined<I64Attr, [IntPositive]>:$i64attr 201 ); 202} 203 204def TypeArrayAttrOp : TEST_Op<"type_array_attr"> { 205 let arguments = (ins TypeArrayAttr:$attr); 206} 207def TypeArrayAttrWithDefaultOp : TEST_Op<"type_array_attr_with_default"> { 208 let arguments = (ins DefaultValuedAttr<TypeArrayAttr, "{}">:$attr); 209} 210def TypeStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> { 211 let arguments = (ins TypedStrAttr<AnyType>:$attr); 212 let assemblyFormat = "$attr attr-dict"; 213} 214 215def StrCaseA: StrEnumAttrCase<"A">; 216def StrCaseB: StrEnumAttrCase<"B">; 217 218def SomeStrEnum: StrEnumAttr< 219 "SomeStrEnum", "", [StrCaseA, StrCaseB]>; 220 221def StrEnumAttrOp : TEST_Op<"str_enum_attr"> { 222 let arguments = (ins SomeStrEnum:$attr); 223 let results = (outs I32:$val); 224} 225 226def I32Case5: I32EnumAttrCase<"case5", 5>; 227def I32Case10: I32EnumAttrCase<"case10", 10>; 228 229def SomeI32Enum: I32EnumAttr< 230 "SomeI32Enum", "", [I32Case5, I32Case10]>; 231 232def I32EnumAttrOp : TEST_Op<"i32_enum_attr"> { 233 let arguments = (ins SomeI32Enum:$attr); 234 let results = (outs I32:$val); 235} 236 237def I64Case5: I64EnumAttrCase<"case5", 5>; 238def I64Case10: I64EnumAttrCase<"case10", 10>; 239 240def SomeI64Enum: I64EnumAttr< 241 "SomeI64Enum", "", [I64Case5, I64Case10]>; 242 243def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> { 244 let arguments = (ins SomeI64Enum:$attr); 245 let results = (outs I32:$val); 246} 247 248def SomeStructAttr : StructAttr<"SomeStructAttr", Test_Dialect, [ 249 StructFieldAttr<"some_field", I64Attr>, 250 StructFieldAttr<"some_other_field", I64Attr> 251]> {} 252 253def StructAttrOp : TEST_Op<"struct_attr"> { 254 let arguments = (ins SomeStructAttr:$the_struct_attr); 255 let results = (outs); 256} 257 258def IntAttrOp : TEST_Op<"int_attrs"> { 259 let arguments = (ins 260 AnyI32Attr:$any_i32_attr, 261 IndexAttr:$index_attr, 262 UI32Attr:$ui32_attr, 263 SI32Attr:$si32_attr 264 ); 265} 266 267def FloatElementsAttrOp : TEST_Op<"float_elements_attr"> { 268 let arguments = (ins 269 RankedF32ElementsAttr<[2]>:$scalar_f32_attr, 270 RankedF64ElementsAttr<[4, 8]>:$tensor_f64_attr 271 ); 272} 273 274// A pattern that updates dense<[3.0, 4.0]> to dense<[5.0, 6.0]>. 275// This tests both matching and generating float elements attributes. 276def UpdateFloatElementsAttr : Pat< 277 (FloatElementsAttrOp 278 ConstantAttr<RankedF32ElementsAttr<[2]>, "{3.0f, 4.0f}">:$f32attr, 279 $f64attr), 280 (FloatElementsAttrOp 281 ConstantAttr<RankedF32ElementsAttr<[2]>, "{5.0f, 6.0f}">:$f32attr, 282 $f64attr)>; 283 284def IntElementsAttrOp : TEST_Op<"int_elements_attr"> { 285 let arguments = (ins 286 AnyI32ElementsAttr:$any_i32_attr, 287 I32ElementsAttr:$i32_attr 288 ); 289} 290 291def RankedIntElementsAttrOp : TEST_Op<"ranked_int_elements_attr"> { 292 let arguments = (ins 293 RankedI32ElementsAttr<[2]>:$vector_i32_attr, 294 RankedI64ElementsAttr<[4, 8]>:$matrix_i64_attr 295 ); 296} 297 298def DerivedTypeAttrOp : TEST_Op<"derived_type_attr", []> { 299 let results = (outs AnyTensor:$output); 300 DerivedTypeAttr element_dtype = 301 DerivedTypeAttr<"return getElementTypeOrSelf(output().getType());">; 302 DerivedAttr size = DerivedAttr<"int", 303 "return output().getType().cast<ShapedType>().getSizeInBits();", 304 "$_builder.getI32IntegerAttr($_self)">; 305} 306 307def StringElementsAttrOp : TEST_Op<"string_elements_attr"> { 308 let arguments = (ins 309 StringElementsAttr:$scalar_string_attr 310 ); 311} 312 313//===----------------------------------------------------------------------===// 314// Test Attribute Constraints 315//===----------------------------------------------------------------------===// 316 317def SymbolRefOp : TEST_Op<"symbol_ref_attr"> { 318 let arguments = (ins 319 Confined<FlatSymbolRefAttr, [ReferToOp<"FuncOp">]>:$symbol 320 ); 321} 322 323//===----------------------------------------------------------------------===// 324// Test Regions 325//===----------------------------------------------------------------------===// 326 327def OneRegionOp : TEST_Op<"one_region_op", []> { 328 let regions = (region AnyRegion); 329} 330 331def TwoRegionOp : TEST_Op<"two_region_op", []> { 332 let regions = (region AnyRegion, AnyRegion); 333} 334 335def SizedRegionOp : TEST_Op<"sized_region_op", []> { 336 let regions = (region SizedRegion<2>:$my_region, SizedRegion<1>); 337} 338 339//===----------------------------------------------------------------------===// 340// NoTerminator Operation 341//===----------------------------------------------------------------------===// 342 343def SingleNoTerminatorOp : TEST_Op<"single_no_terminator_op", 344 GraphRegionNoTerminator.traits> { 345 let regions = (region SizedRegion<1>:$my_region); 346 347 let assemblyFormat = "attr-dict `:` $my_region"; 348} 349 350def SingleNoTerminatorCustomAsmOp : TEST_Op<"single_no_terminator_custom_asm_op", 351 [SingleBlock, NoTerminator]> { 352 let regions = (region SizedRegion<1>); 353 let parser = [{ return ::parseSingleNoTerminatorCustomAsmOp(parser, result); }]; 354 let printer = [{ return ::print(*this, p); }]; 355} 356 357def VariadicNoTerminatorOp : TEST_Op<"variadic_no_terminator_op", 358 GraphRegionNoTerminator.traits> { 359 let regions = (region VariadicRegion<SizedRegion<1>>:$my_regions); 360 361 let assemblyFormat = "attr-dict `:` $my_regions"; 362} 363 364//===----------------------------------------------------------------------===// 365// Test Call Interfaces 366//===----------------------------------------------------------------------===// 367 368def ConversionCallOp : TEST_Op<"conversion_call_op", 369 [CallOpInterface]> { 370 let arguments = (ins Variadic<AnyType>:$inputs, SymbolRefAttr:$callee); 371 let results = (outs Variadic<AnyType>); 372 373 let extraClassDeclaration = [{ 374 /// Get the argument operands to the called function. 375 operand_range getArgOperands() { return inputs(); } 376 377 /// Return the callee of this operation. 378 ::mlir::CallInterfaceCallable getCallableForCallee() { 379 return (*this)->getAttrOfType<::mlir::SymbolRefAttr>("callee"); 380 } 381 }]; 382} 383 384def FunctionalRegionOp : TEST_Op<"functional_region_op", 385 [CallableOpInterface]> { 386 let regions = (region AnyRegion:$body); 387 let results = (outs FunctionType); 388 389 let extraClassDeclaration = [{ 390 ::mlir::Region *getCallableRegion() { return &body(); } 391 ::llvm::ArrayRef<::mlir::Type> getCallableResults() { 392 return getType().cast<::mlir::FunctionType>().getResults(); 393 } 394 }]; 395} 396 397 398def FoldToCallOp : TEST_Op<"fold_to_call_op"> { 399 let arguments = (ins FlatSymbolRefAttr:$callee); 400 let hasCanonicalizer = 1; 401} 402 403//===----------------------------------------------------------------------===// 404// Test Traits 405//===----------------------------------------------------------------------===// 406 407def SameOperandElementTypeOp : TEST_Op<"same_operand_element_type", 408 [SameOperandsElementType]> { 409 let arguments = (ins AnyType, AnyType); 410 let results = (outs AnyType); 411} 412 413def SameOperandAndResultElementTypeOp : 414 TEST_Op<"same_operand_and_result_element_type", 415 [SameOperandsAndResultElementType]> { 416 let arguments = (ins Variadic<AnyType>); 417 let results = (outs Variadic<AnyType>); 418} 419 420def SameOperandShapeOp : TEST_Op<"same_operand_shape", [SameOperandsShape]> { 421 let arguments = (ins Variadic<AnyShaped>); 422} 423 424def SameOperandAndResultShapeOp : TEST_Op<"same_operand_and_result_shape", 425 [SameOperandsAndResultShape]> { 426 let arguments = (ins Variadic<AnyShaped>); 427 let results = (outs Variadic<AnyShaped>); 428} 429 430def SameOperandAndResultTypeOp : TEST_Op<"same_operand_and_result_type", 431 [SameOperandsAndResultType]> { 432 let arguments = (ins Variadic<AnyType>); 433 let results = (outs Variadic<AnyType>); 434} 435 436def ElementwiseMappableOp : TEST_Op<"elementwise_mappable", 437 ElementwiseMappable.traits> { 438 let arguments = (ins Variadic<AnyType>); 439 let results = (outs Variadic<AnyType>); 440} 441 442def ArgAndResHaveFixedElementTypesOp : 443 TEST_Op<"arg_and_res_have_fixed_element_types", 444 [PredOpTrait<"fixed type combination", 445 And<[ElementTypeIsPred<"x", I32>, 446 ElementTypeIsPred<"y", F32>]>>, 447 ElementTypeIs<"res", I16>]> { 448 let arguments = (ins 449 AnyShaped:$x, AnyShaped:$y); 450 let results = (outs AnyShaped:$res); 451} 452 453def OperandsHaveSameElementType : TEST_Op<"operands_have_same_element_type", [ 454 AllElementTypesMatch<["x", "y"]>]> { 455 let arguments = (ins AnyType:$x, AnyType:$y); 456} 457 458def OperandZeroAndResultHaveSameElementType : TEST_Op< 459 "operand0_and_result_have_same_element_type", 460 [AllElementTypesMatch<["x", "res"]>]> { 461 let arguments = (ins AnyType:$x, AnyType:$y); 462 let results = (outs AnyType:$res); 463} 464 465def OperandsHaveSameType : 466 TEST_Op<"operands_have_same_type", [AllTypesMatch<["x", "y"]>]> { 467 let arguments = (ins AnyType:$x, AnyType:$y); 468} 469 470def ResultHasSameTypeAsAttr : 471 TEST_Op<"result_has_same_type_as_attr", 472 [AllTypesMatch<["attr", "result"]>]> { 473 let arguments = (ins AnyAttr:$attr); 474 let results = (outs AnyType:$result); 475 let assemblyFormat = "$attr `->` type($result) attr-dict"; 476} 477 478def OperandZeroAndResultHaveSameType : 479 TEST_Op<"operand0_and_result_have_same_type", 480 [AllTypesMatch<["x", "res"]>]> { 481 let arguments = (ins AnyType:$x, AnyType:$y); 482 let results = (outs AnyType:$res); 483} 484 485def OperandsHaveSameRank : 486 TEST_Op<"operands_have_same_rank", [AllRanksMatch<["x", "y"]>]> { 487 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 488} 489 490def OperandZeroAndResultHaveSameRank : 491 TEST_Op<"operand0_and_result_have_same_rank", 492 [AllRanksMatch<["x", "res"]>]> { 493 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 494 let results = (outs AnyShaped:$res); 495} 496 497def OperandZeroAndResultHaveSameShape : 498 TEST_Op<"operand0_and_result_have_same_shape", 499 [AllShapesMatch<["x", "res"]>]> { 500 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 501 let results = (outs AnyShaped:$res); 502} 503 504def OperandZeroAndResultHaveSameElementCount : 505 TEST_Op<"operand0_and_result_have_same_element_count", 506 [AllElementCountsMatch<["x", "res"]>]> { 507 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 508 let results = (outs AnyShaped:$res); 509} 510 511def FourEqualsFive : 512 TEST_Op<"four_equals_five", [AllMatch<["5", "4"], "4 equals 5">]>; 513 514def OperandRankEqualsResultSize : 515 TEST_Op<"operand_rank_equals_result_size", 516 [AllMatch<[Rank<"operand">.result, ElementCount<"result">.result], 517 "operand rank equals result size">]> { 518 let arguments = (ins AnyShaped:$operand); 519 let results = (outs AnyShaped:$result); 520} 521 522def IfFirstOperandIsNoneThenSoIsSecond : 523 TEST_Op<"if_first_operand_is_none_then_so_is_second", [PredOpTrait< 524 "has either both none type operands or first is not none", 525 Or<[ 526 And<[TypeIsPred<"x", NoneType>, TypeIsPred<"y", NoneType>]>, 527 Neg<TypeIsPred<"x", NoneType>>]>>]> { 528 let arguments = (ins AnyType:$x, AnyType:$y); 529} 530 531def BroadcastableOp : TEST_Op<"broadcastable", [ResultsBroadcastableShape]> { 532 let arguments = (ins Variadic<AnyTensor>); 533 let results = (outs AnyTensor); 534} 535 536// HasParent trait 537def ParentOp : TEST_Op<"parent"> { 538 let regions = (region AnyRegion); 539} 540def ChildOp : TEST_Op<"child", [HasParent<"ParentOp">]>; 541 542// ParentOneOf trait 543def ParentOp1 : TEST_Op<"parent1"> { 544 let regions = (region AnyRegion); 545} 546def ChildWithParentOneOf : TEST_Op<"child_with_parent_one_of", 547 [ParentOneOf<["ParentOp", "ParentOp1"]>]>; 548 549def TerminatorOp : TEST_Op<"finish", [Terminator]>; 550def SingleBlockImplicitTerminatorOp : TEST_Op<"SingleBlockImplicitTerminator", 551 [SingleBlockImplicitTerminator<"TerminatorOp">]> { 552 let regions = (region SizedRegion<1>:$region); 553} 554 555def I32ElementsAttrOp : TEST_Op<"i32ElementsAttr"> { 556 let arguments = (ins I32ElementsAttr:$attr); 557} 558 559def IndexElementsAttrOp : TEST_Op<"indexElementsAttr"> { 560 let arguments = (ins IndexElementsAttr:$attr); 561} 562 563def OpWithInferTypeInterfaceOp : TEST_Op<"op_with_infer_type_if", [ 564 DeclareOpInterfaceMethods<InferTypeOpInterface, 565 ["inferReturnTypeComponents"]>]> { 566 let arguments = (ins AnyTensor, AnyTensor); 567 let results = (outs AnyTensor); 568} 569 570def OpWithShapedTypeInferTypeInterfaceOp : TEST_Op<"op_with_shaped_type_infer_type_if", 571 [InferTensorTypeWithReify]> { 572 let arguments = (ins AnyTensor, AnyTensor); 573 let results = (outs AnyTensor); 574} 575 576def OpWithResultShapeInterfaceOp : TEST_Op<"op_with_result_shape_interface", 577 [DeclareOpInterfaceMethods<InferShapedTypeOpInterface, 578 ["reifyReturnTypeShapes"]>]> { 579 let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2); 580 let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2); 581} 582 583def OpWithResultShapePerDimInterfaceOp : 584 TEST_Op<"op_with_result_shape_per_dim_interface", 585 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface>]> { 586 let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2); 587 let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2); 588} 589 590def IsNotScalar : Constraint<CPred<"$0.getType().getRank() != 0">>; 591 592def UpdateAttr : Pat<(I32ElementsAttrOp $attr), 593 (I32ElementsAttrOp ConstantAttr<I32ElementsAttr, "0">), 594 [(IsNotScalar $attr)]>; 595 596def TestBranchOp : TEST_Op<"br", 597 [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator]> { 598 let arguments = (ins Variadic<AnyType>:$targetOperands); 599 let successors = (successor AnySuccessor:$target); 600} 601 602def AttrSizedOperandOp : TEST_Op<"attr_sized_operands", 603 [AttrSizedOperandSegments]> { 604 let arguments = (ins 605 Variadic<I32>:$a, 606 Variadic<I32>:$b, 607 I32:$c, 608 Variadic<I32>:$d, 609 I32ElementsAttr:$operand_segment_sizes 610 ); 611} 612 613def AttrSizedResultOp : TEST_Op<"attr_sized_results", 614 [AttrSizedResultSegments]> { 615 let arguments = (ins 616 I32ElementsAttr:$result_segment_sizes 617 ); 618 let results = (outs 619 Variadic<I32>:$a, 620 Variadic<I32>:$b, 621 I32:$c, 622 Variadic<I32>:$d 623 ); 624} 625 626// This is used to test encoding of a string attribute into an SSA name of a 627// pretty printed value name. 628def StringAttrPrettyNameOp 629 : TEST_Op<"string_attr_pretty_name", 630 [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> { 631 let arguments = (ins StrArrayAttr:$names); 632 let results = (outs Variadic<I32>:$r); 633 634 let printer = [{ return ::print(p, *this); }]; 635 let parser = [{ return ::parse$cppClass(parser, result); }]; 636} 637 638// This is used to test the OpAsmOpInterface::getDefaultDialect() feature: 639// operations nested in a region under this op will drop the "test." dialect 640// prefix. 641def DefaultDialectOp : TEST_Op<"default_dialect", [OpAsmOpInterface]> { 642 let regions = (region AnyRegion:$body); 643 let extraClassDeclaration = [{ 644 static ::llvm::StringRef getDefaultDialect() { 645 return "test"; 646 } 647 void getAsmResultNames(::llvm::function_ref<void(::mlir::Value, ::llvm::StringRef)> setNameFn) {} 648 }]; 649 let assemblyFormat = "regions attr-dict-with-keyword"; 650} 651 652// This operation requires its return type to have the trait 'TestTypeTrait'. 653def ResultTypeWithTraitOp : TEST_Op<"result_type_with_trait", []> { 654 let results = (outs AnyType); 655 656 let verifier = [{ 657 if((*this)->getResultTypes()[0].hasTrait<TypeTrait::TestTypeTrait>()) 658 return success(); 659 return this->emitError("result type should have trait 'TestTypeTrait'"); 660 }]; 661} 662 663// This operation requires its "attr" attribute to have the 664// trait 'TestAttrTrait'. 665def AttrWithTraitOp : TEST_Op<"attr_with_trait", []> { 666 let arguments = (ins AnyAttr:$attr); 667 668 let verifier = [{ 669 if (this->attr().hasTrait<AttributeTrait::TestAttrTrait>()) 670 return success(); 671 return this->emitError("'attr' attribute should have trait 'TestAttrTrait'"); 672 }]; 673} 674 675 676//===----------------------------------------------------------------------===// 677// Test Locations 678//===----------------------------------------------------------------------===// 679 680def TestLocationSrcOp : TEST_Op<"loc_src"> { 681 let arguments = (ins I32:$input); 682 let results = (outs I32:$output); 683} 684 685def TestLocationDstOp : TEST_Op<"loc_dst", [SameOperandsAndResultType]> { 686 let arguments = (ins I32:$input); 687 let results = (outs I32:$output); 688} 689 690//===----------------------------------------------------------------------===// 691// Test Patterns 692//===----------------------------------------------------------------------===// 693 694def OpA : TEST_Op<"op_a"> { 695 let arguments = (ins I32, I32Attr:$attr); 696 let results = (outs I32); 697} 698 699def OpB : TEST_Op<"op_b"> { 700 let arguments = (ins I32, I32Attr:$attr); 701 let results = (outs I32); 702} 703 704// Test named pattern. 705def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>; 706 707// Test with fused location. 708def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>; 709 710// Test added benefit. 711def OpD : TEST_Op<"op_d">, Arguments<(ins I32)>, Results<(outs I32)>; 712def OpE : TEST_Op<"op_e">, Arguments<(ins I32)>, Results<(outs I32)>; 713def OpF : TEST_Op<"op_f">, Arguments<(ins I32)>, Results<(outs I32)>; 714def OpG : TEST_Op<"op_g">, Arguments<(ins I32)>, Results<(outs I32)>; 715// Verify that bumping benefit results in selecting different op. 716def : Pat<(OpD $input), (OpE $input)>; 717def : Pat<(OpD $input), (OpF $input), [], (addBenefit 10)>; 718// Verify that patterns with more source nodes are selected before those with fewer. 719def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>; 720def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>; 721 722// Test patterns for zero-result op. 723def OpH : TEST_Op<"op_h">, Arguments<(ins I32)>, Results<(outs)>; 724def OpI : TEST_Op<"op_i">, Arguments<(ins I32)>, Results<(outs)>; 725def : Pat<(OpH $input), (OpI $input)>; 726 727// Test patterns for zero-input op. 728def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32)>; 729def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32)>; 730def : Pat<(OpJ), (OpK)>; 731 732// Test that natives calls are only called once during rewrites. 733def OpM : TEST_Op<"op_m"> { 734 let arguments = (ins I32, OptionalAttr<I32Attr>:$optional_attr); 735 let results = (outs I32); 736} 737 738def OpN : TEST_Op<"op_n"> { 739 let arguments = (ins I32, I32); 740 let results = (outs I32); 741} 742 743def OpO : TEST_Op<"op_o"> { 744 let arguments = (ins I32); 745 let results = (outs I32); 746} 747 748def OpP : TEST_Op<"op_p"> { 749 let arguments = (ins I32, I32, I32, I32, I32, I32); 750 let results = (outs I32); 751} 752 753// Test same operand name enforces equality condition check. 754def TestEqualArgsPattern : Pat<(OpN $a, $a), (OpO $a)>; 755 756// Test when equality is enforced at different depth. 757def TestNestedOpEqualArgsPattern : 758 Pat<(OpN $b, (OpP $a, $b, $c, $d, $e, $f)), (replaceWithValue $b)>; 759 760// Test when equality is enforced on same op and same operand but at different 761// depth. We only bound one of the $x to the second operand of outer OpN and 762// left another be the default value (which is the value of first operand of 763// outer OpN). As a result, it ended up comparing wrong values in some cases. 764def TestNestedSameOpAndSameArgEqualityPattern : 765 Pat<(OpN (OpN $_, $x), $x), (replaceWithValue $x)>; 766 767// Test multiple equal arguments check enforced. 768def TestMultipleEqualArgsPattern : 769 Pat<(OpP $a, $b, $a, $a, $b, $c), (OpN $c, $b)>; 770 771// Test for memrefs normalization of an op with normalizable memrefs. 772def OpNorm : TEST_Op<"op_norm", [MemRefsNormalizable]> { 773 let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y); 774} 775// Test for memrefs normalization of an op without normalizable memrefs. 776def OpNonNorm : TEST_Op<"op_nonnorm"> { 777 let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y); 778} 779// Test for memrefs normalization of an op that has normalizable memref results. 780def OpNormRet : TEST_Op<"op_norm_ret", [MemRefsNormalizable]> { 781 let arguments = (ins AnyMemRef:$X); 782 let results = (outs AnyMemRef:$Y, AnyMemRef:$Z); 783} 784 785// Test for memrefs normalization of an op with a reference to a function 786// symbol. 787def OpFuncRef : TEST_Op<"op_funcref"> { 788 let summary = "Test op with a reference to a function symbol"; 789 let description = [{ 790 The "test.op_funcref" is a test op with a reference to a function symbol. 791 }]; 792 let builders = [OpBuilder<(ins "::mlir::FuncOp":$function)>]; 793} 794 795// Pattern add the argument plus a increasing static number hidden in 796// OpMTest function. That value is set into the optional argument. 797// That way, we will know if operations is called once or twice. 798def OpMGetNullAttr : NativeCodeCall<"Attribute()">; 799def OpMAttributeIsNull : Constraint<CPred<"! ($_self)">, "Attribute is null">; 800def OpMVal : NativeCodeCall<"OpMTest($_builder, $0)">; 801def : Pat<(OpM $attr, $optAttr), (OpM $attr, (OpMVal $attr) ), 802 [(OpMAttributeIsNull:$optAttr)]>; 803 804// Test `$_` for ignoring op argument match. 805def TestIgnoreArgMatchSrcOp : TEST_Op<"ignore_arg_match_src"> { 806 let arguments = (ins 807 AnyType:$a, AnyType:$b, AnyType:$c, 808 AnyAttr:$d, AnyAttr:$e, AnyAttr:$f); 809} 810def TestIgnoreArgMatchDstOp : TEST_Op<"ignore_arg_match_dst"> { 811 let arguments = (ins AnyType:$b, AnyAttr:$f); 812} 813def : Pat<(TestIgnoreArgMatchSrcOp $_, $b, I32, I64Attr:$_, $_, $f), 814 (TestIgnoreArgMatchDstOp $b, $f)>; 815 816def OpInterleavedOperandAttribute1 : TEST_Op<"interleaved_operand_attr1"> { 817 let arguments = (ins 818 I32:$input1, 819 I64Attr:$attr1, 820 I32:$input2, 821 I64Attr:$attr2 822 ); 823} 824 825def OpInterleavedOperandAttribute2 : TEST_Op<"interleaved_operand_attr2"> { 826 let arguments = (ins 827 I32:$input1, 828 I64Attr:$attr1, 829 I32:$input2, 830 I64Attr:$attr2 831 ); 832} 833 834def ManyArgsOp : TEST_Op<"many_arguments"> { 835 let arguments = (ins 836 I32:$input1, I32:$input2, I32:$input3, I32:$input4, I32:$input5, 837 I32:$input6, I32:$input7, I32:$input8, I32:$input9, 838 I64Attr:$attr1, I64Attr:$attr2, I64Attr:$attr3, I64Attr:$attr4, 839 I64Attr:$attr5, I64Attr:$attr6, I64Attr:$attr7, I64Attr:$attr8, 840 I64Attr:$attr9 841 ); 842} 843 844// Test that DRR does not blow up when seeing lots of arguments. 845def : Pat<(ManyArgsOp 846 $input1, $input2, $input3, $input4, $input5, 847 $input6, $input7, $input8, $input9, 848 ConstantAttr<I64Attr, "42">, 849 $attr2, $attr3, $attr4, $attr5, $attr6, 850 $attr7, $attr8, $attr9), 851 (ManyArgsOp 852 $input1, $input2, $input3, $input4, $input5, 853 $input6, $input7, $input8, $input9, 854 ConstantAttr<I64Attr, "24">, 855 $attr2, $attr3, $attr4, $attr5, $attr6, 856 $attr7, $attr8, $attr9)>; 857 858// Test that we can capture and reference interleaved operands and attributes. 859def : Pat<(OpInterleavedOperandAttribute1 $input1, $attr1, $input2, $attr2), 860 (OpInterleavedOperandAttribute2 $input1, $attr1, $input2, $attr2)>; 861 862// Test NativeCodeCall. 863def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> { 864 let arguments = (ins 865 I32:$input1, I32:$input2, 866 BoolAttr:$choice, 867 I64Attr:$attr1, I64Attr:$attr2 868 ); 869 let results = (outs I32); 870} 871def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> { 872 let arguments = (ins I32:$input, I64ArrayAttr:$attr); 873 let results = (outs I32); 874} 875// Native code call to invoke a C++ function 876def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">; 877// Native code call to invoke a C++ expression 878def CreateArrayAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">; 879// Test that we can use NativeCodeCall to create operand and attribute. 880// This pattern chooses between $input1 and $input2 according to $choice and 881// it combines $attr1 and $attr2 into an array attribute. 882def : Pat<(OpNativeCodeCall1 $input1, $input2, 883 ConstBoolAttrTrue:$choice, $attr1, $attr2), 884 (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice), 885 (CreateArrayAttr $attr1, $attr2))>; 886// Note: the following is just for testing purpose. 887// Should use the replaceWithValue directive instead. 888def UseOpResult: NativeCodeCall<"$0">; 889// Test that we can use NativeCodeCall to create result. 890def : Pat<(OpNativeCodeCall1 $input1, $input2, 891 ConstBoolAttrFalse, $attr1, $attr2), 892 (UseOpResult $input2)>; 893 894def OpNativeCodeCall3 : TEST_Op<"native_code_call3"> { 895 let arguments = (ins I32:$input); 896 let results = (outs I32); 897} 898// Test that NativeCodeCall is not ignored if it is not used to directly 899// replace the matched root op. 900def : Pattern<(OpNativeCodeCall3 $input), 901 [(NativeCodeCallVoid<"createOpI($_builder, $_loc, $0)"> $input), 902 (OpK)]>; 903 904def OpNativeCodeCall4 : TEST_Op<"native_code_call4"> { 905 let arguments = (ins AnyType:$input1); 906 let results = (outs I32:$output1, I32:$output2); 907} 908def OpNativeCodeCall5 : TEST_Op<"native_code_call5"> { 909 let arguments = (ins I32:$input1, I32:$input2); 910 let results = (outs I32:$output1, I32:$output2); 911} 912 913def GetFirstI32Result : NativeCodeCall<"success(getFirstI32Result($_self, $0))">; 914def BindNativeCodeCallResult : NativeCodeCall<"bindNativeCodeCallResult($0)">; 915def : Pat<(OpNativeCodeCall4 (GetFirstI32Result $ret)), 916 (OpNativeCodeCall5 (BindNativeCodeCallResult:$native $ret), $native)>; 917 918def OpNativeCodeCall6 : TEST_Op<"native_code_call6"> { 919 let arguments = (ins I32:$input1, I32:$input2); 920 let results = (outs I32:$output1, I32:$output2); 921} 922def OpNativeCodeCall7 : TEST_Op<"native_code_call7"> { 923 let arguments = (ins I32:$input); 924 let results = (outs I32); 925} 926def BindMultipleNativeCodeCallResult : NativeCodeCall<"bindMultipleNativeCodeCallResult($0, $1)", 2>; 927def : Pattern<(OpNativeCodeCall6 $arg1, $arg2), 928 [(OpNativeCodeCall7 (BindMultipleNativeCodeCallResult:$native__0 $arg1, $arg2)), 929 (OpNativeCodeCall7 $native__1)]>; 930 931// Test AllAttrConstraintsOf. 932def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> { 933 let arguments = (ins I64ArrayAttr:$attr); 934 let results = (outs I32); 935} 936def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> { 937 let arguments = (ins I64ArrayAttr:$attr); 938 let results = (outs I32); 939} 940def Constraint0 : AttrConstraint< 941 CPred<"$_self.cast<ArrayAttr>()[0]." 942 "cast<::mlir::IntegerAttr>().getInt() == 0">, 943 "[0] == 0">; 944def Constraint1 : AttrConstraint< 945 CPred<"$_self.cast<ArrayAttr>()[1].cast<::mlir::IntegerAttr>().getInt() == 1">, 946 "[1] == 1">; 947def : Pat<(OpAllAttrConstraint1 948 AllAttrConstraintsOf<[Constraint0, Constraint1]>:$attr), 949 (OpAllAttrConstraint2 $attr)>; 950 951// Op for testing RewritePattern removing op with inner ops. 952def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> { 953 let regions = (region SizedRegion<1>:$region); 954 let hasCanonicalizer = 1; 955} 956 957def TestOpConstant : TEST_Op<"constant", [ConstantLike, NoSideEffect]> { 958 let arguments = (ins AnyAttr:$value); 959 let results = (outs AnyType); 960 let extraClassDeclaration = [{ 961 ::mlir::Attribute getValue() { return (*this)->getAttr("value"); } 962 }]; 963 964 let hasFolder = 1; 965} 966 967def OpR : TEST_Op<"op_r">, Arguments<(ins AnyInteger, AnyInteger)>, Results<(outs AnyInteger)>; 968def OpS : TEST_Op<"op_s">, Arguments<(ins AnyInteger, AnyAttr:$value)>, Results<(outs AnyInteger)>; 969 970def : Pat<(OpR $input1, (ConstantLikeMatcher I32Attr:$input2)), 971 (OpS:$unused $input1, $input2)>; 972 973// Op for testing trivial removal via folding of op with inner ops and no uses. 974def TestOpWithRegionFoldNoSideEffect : TEST_Op< 975 "op_with_region_fold_no_side_effect", [NoSideEffect]> { 976 let regions = (region SizedRegion<1>:$region); 977} 978 979// Op for testing folding of outer op with inner ops. 980def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> { 981 let arguments = (ins I32:$operand); 982 let results = (outs I32); 983 let regions = (region SizedRegion<1>:$region); 984 let hasFolder = 1; 985} 986 987def TestOpWithVariadicResultsAndFolder: TEST_Op<"op_with_variadic_results_and_folder"> { 988 let arguments = (ins Variadic<I32>:$operands); 989 let results = (outs Variadic<I32>); 990 let hasFolder = 1; 991} 992 993def TestCommutativeOp : TEST_Op<"op_commutative", [Commutative]> { 994 let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4); 995 let results = (outs I32); 996} 997 998def TestIdempotentTraitOp 999 : TEST_Op<"op_idempotent_trait", 1000 [SameOperandsAndResultType, NoSideEffect, Idempotent]> { 1001 let arguments = (ins I32:$op1); 1002 let results = (outs I32); 1003} 1004 1005def TestInvolutionTraitNoOperationFolderOp 1006 : TEST_Op<"op_involution_trait_no_operation_fold", 1007 [SameOperandsAndResultType, NoSideEffect, Involution]> { 1008 let arguments = (ins I32:$op1); 1009 let results = (outs I32); 1010} 1011 1012def TestInvolutionTraitFailingOperationFolderOp 1013 : TEST_Op<"op_involution_trait_failing_operation_fold", 1014 [SameOperandsAndResultType, NoSideEffect, Involution]> { 1015 let arguments = (ins I32:$op1); 1016 let results = (outs I32); 1017 let hasFolder = 1; 1018} 1019 1020def TestInvolutionTraitSuccesfulOperationFolderOp 1021 : TEST_Op<"op_involution_trait_succesful_operation_fold", 1022 [SameOperandsAndResultType, NoSideEffect, Involution]> { 1023 let arguments = (ins I32:$op1); 1024 let results = (outs I32); 1025 let hasFolder = 1; 1026} 1027 1028def TestOpInPlaceFoldAnchor : TEST_Op<"op_in_place_fold_anchor"> { 1029 let arguments = (ins I32); 1030 let results = (outs I32); 1031} 1032 1033def TestOpInPlaceFold : TEST_Op<"op_in_place_fold"> { 1034 let arguments = (ins I32:$op, I32Attr:$attr); 1035 let results = (outs I32); 1036 let hasFolder = 1; 1037} 1038 1039// An op that always fold itself. 1040def TestPassthroughFold : TEST_Op<"passthrough_fold"> { 1041 let arguments = (ins AnyType:$op); 1042 let results = (outs AnyType); 1043 let hasFolder = 1; 1044} 1045 1046def TestDialectCanonicalizerOp : TEST_Op<"dialect_canonicalizable"> { 1047 let arguments = (ins); 1048 let results = (outs I32); 1049} 1050 1051//===----------------------------------------------------------------------===// 1052// Test Patterns (Symbol Binding) 1053 1054// Test symbol binding. 1055def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> { 1056 let arguments = (ins I32:$operand, I64Attr:$attr); 1057 let results = (outs I32); 1058} 1059def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> { 1060 let arguments = (ins I32:$operand); 1061 let results = (outs I32); 1062} 1063def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> { 1064 let arguments = (ins I32:$operand); 1065 let results = (outs I32); 1066 let builders = OpSymbolBindingB.builders; 1067} 1068def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> { 1069 let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr); 1070 let results = (outs I32); 1071} 1072def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">; 1073def : Pattern< 1074 // Bind to source pattern op operand/attribute/result 1075 (OpSymbolBindingA:$res_a $operand, $attr), [ 1076 // Bind to auxiliary op result 1077 (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)), 1078 1079 // Use bound symbols in resultant ops 1080 (OpSymbolBindingD $res_b, $res_c, $attr)], 1081 // Use bound symbols in additional constraints 1082 [(HasOneUse $res_a)]>; 1083 1084def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> { 1085 let arguments = (ins I32:$operand); 1086} 1087 1088// Test that we can bind to an op without results and reference it later. 1089def : Pat<(OpSymbolBindingNoResult:$op $operand), 1090 (NativeCodeCallVoid<"handleNoResultOp($_builder, $0)"> $op)>; 1091 1092//===----------------------------------------------------------------------===// 1093// Test Patterns (Attributes) 1094 1095// Test matching against op attributes. 1096def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> { 1097 let arguments = (ins 1098 I32Attr:$required_attr, 1099 OptionalAttr<I32Attr>:$optional_attr, 1100 DefaultValuedAttr<I32Attr, "42">:$default_valued_attr, 1101 I32Attr:$more_attr 1102 ); 1103 let results = (outs I32); 1104} 1105def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> { 1106 let arguments = OpAttrMatch1.arguments; 1107 let results = (outs I32); 1108} 1109def MoreConstraint : AttrConstraint< 1110 CPred<"$_self.cast<IntegerAttr>().getInt() == 4">, "more constraint">; 1111def : Pat<(OpAttrMatch1 $required, $optional, $default_valued, 1112 MoreConstraint:$more), 1113 (OpAttrMatch2 $required, $optional, $default_valued, $more)>; 1114 1115// Test unit attrs. 1116def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> { 1117 let arguments = (ins UnitAttr:$attr); 1118 let results = (outs I32); 1119} 1120def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> { 1121 let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2); 1122 let results = (outs I32); 1123} 1124def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>; 1125 1126// Test with constant attr. 1127def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>; 1128def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>; 1129 1130// Test string enum attribute in rewrites. 1131def : Pat<(StrEnumAttrOp StrCaseA), (StrEnumAttrOp StrCaseB)>; 1132// Test integer enum attribute in rewrites. 1133def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>; 1134def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>; 1135 1136//===----------------------------------------------------------------------===// 1137// Test Patterns (Multi-result Ops) 1138 1139def MultiResultOpKind1: I64EnumAttrCase<"kind1", 1>; 1140def MultiResultOpKind2: I64EnumAttrCase<"kind2", 2>; 1141def MultiResultOpKind3: I64EnumAttrCase<"kind3", 3>; 1142def MultiResultOpKind4: I64EnumAttrCase<"kind4", 4>; 1143def MultiResultOpKind5: I64EnumAttrCase<"kind5", 5>; 1144def MultiResultOpKind6: I64EnumAttrCase<"kind6", 6>; 1145 1146def MultiResultOpEnum: I64EnumAttr< 1147 "MultiResultOpEnum", "Multi-result op kinds", [ 1148 MultiResultOpKind1, MultiResultOpKind2, MultiResultOpKind3, 1149 MultiResultOpKind4, MultiResultOpKind5, MultiResultOpKind6 1150 ]>; 1151 1152def ThreeResultOp : TEST_Op<"three_result"> { 1153 let arguments = (ins MultiResultOpEnum:$kind); 1154 let results = (outs I32:$result1, F32:$result2, F32:$result3); 1155} 1156 1157def AnotherThreeResultOp : TEST_Op<"another_three_result", [DeclareOpInterfaceMethods<InferTypeOpInterface>]> { 1158 let arguments = (ins MultiResultOpEnum:$kind); 1159 let results = (outs I32:$result1, F32:$result2, F32:$result3); 1160} 1161 1162def TwoResultOp : TEST_Op<"two_result"> { 1163 let arguments = (ins MultiResultOpEnum:$kind); 1164 let results = (outs I32:$result1, F32:$result2); 1165} 1166 1167def AnotherTwoResultOp : TEST_Op<"another_two_result"> { 1168 let arguments = (ins MultiResultOpEnum:$kind); 1169 let results = (outs F32:$result1, F32:$result2); 1170} 1171 1172def OneResultOp1 : TEST_Op<"one_result1"> { 1173 let arguments = (ins MultiResultOpEnum:$kind); 1174 let results = (outs F32:$result1); 1175} 1176 1177def OneResultOp2 : TEST_Op<"one_result2"> { 1178 let arguments = (ins MultiResultOpEnum:$kind); 1179 let results = (outs I32:$result1); 1180} 1181 1182def OneResultOp3 : TEST_Op<"one_result3"> { 1183 let arguments = (ins F32); 1184 let results = (outs I32:$result1); 1185} 1186 1187// Test using multi-result op as a whole 1188def : Pat<(ThreeResultOp MultiResultOpKind1:$kind), 1189 (AnotherThreeResultOp $kind)>; 1190 1191// Test using multi-result op as a whole for partial replacement 1192def : Pattern<(ThreeResultOp MultiResultOpKind2:$kind), 1193 [(TwoResultOp $kind), 1194 (OneResultOp1 $kind)]>; 1195def : Pattern<(ThreeResultOp MultiResultOpKind3:$kind), 1196 [(OneResultOp2 $kind), 1197 (AnotherTwoResultOp $kind)]>; 1198 1199// Test using results separately in a multi-result op 1200def : Pattern<(ThreeResultOp MultiResultOpKind4:$kind), 1201 [(TwoResultOp:$res1__0 $kind), 1202 (OneResultOp1 $kind), 1203 (TwoResultOp:$res2__1 $kind)]>; 1204 1205// Test referencing a single value in the value pack 1206// This rule only matches TwoResultOp if its second result has no use. 1207def : Pattern<(TwoResultOp:$res MultiResultOpKind5:$kind), 1208 [(OneResultOp2 $kind), 1209 (OneResultOp1 $kind)], 1210 [(HasNoUseOf:$res__1)]>; 1211 1212// Test using auxiliary ops for replacing multi-result op 1213def : Pattern< 1214 (ThreeResultOp MultiResultOpKind6:$kind), [ 1215 // Auxiliary op generated to help building the final result but not 1216 // directly used to replace the source op's results. 1217 (TwoResultOp:$interm $kind), 1218 1219 (OneResultOp3 $interm__1), 1220 (AnotherTwoResultOp $kind) 1221 ]>; 1222 1223//===----------------------------------------------------------------------===// 1224// Test Patterns (Variadic Ops) 1225 1226def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> { 1227 let arguments = (ins Variadic<I32>); 1228 let results = (outs Variadic<I32>); 1229} 1230def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> { 1231 let arguments = (ins Variadic<I32>); 1232 let results = (outs Variadic<I32>); 1233} 1234 1235// Rewrite an op with one variadic operand and one variadic result to 1236// another similar op. 1237def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>; 1238 1239def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1", 1240 [SameVariadicOperandSize]> { 1241 let arguments = (ins 1242 Variadic<I32>:$input1, 1243 F32:$input2, 1244 Variadic<I32>:$input3 1245 ); 1246} 1247 1248def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2", 1249 [SameVariadicOperandSize]> { 1250 let arguments = (ins 1251 Variadic<I32>:$input1, 1252 F32:$input2, 1253 Variadic<I32>:$input3 1254 ); 1255} 1256 1257// Rewrite an op with both variadic operands and normal operands. 1258def : Pat<(MixedVOperandOp1 $input1, $input2, $input3), 1259 (MixedVOperandOp2 $input1, $input2, $input3)>; 1260 1261def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> { 1262 let results = (outs 1263 Variadic<I32>:$output1, 1264 F32:$output2, 1265 Variadic<I32>:$output3 1266 ); 1267} 1268 1269def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> { 1270 let results = (outs 1271 Variadic<I32>:$output1, 1272 F32:$output2, 1273 Variadic<I32>:$output3 1274 ); 1275} 1276 1277// Rewrite an op with both variadic results and normal results. 1278// Note that because we are generating the op with a top-level result pattern, 1279// we are able to deduce the correct result types for the generated op using 1280// the information from the matched root op. 1281def : Pat<(MixedVResultOp1), (MixedVResultOp2)>; 1282 1283def OneI32ResultOp : TEST_Op<"one_i32_out"> { 1284 let results = (outs I32); 1285} 1286 1287def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3", 1288 [SameVariadicOperandSize]> { 1289 let arguments = (ins 1290 I32:$input1, 1291 Variadic<I32>:$input2, 1292 Variadic<I32>:$input3, 1293 I32Attr:$count 1294 ); 1295 1296 let results = (outs I32); 1297} 1298 1299def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3", 1300 [SameVariadicResultSize]> { 1301 let arguments = (ins I32Attr:$count); 1302 1303 let results = (outs 1304 I32:$output1, 1305 Variadic<I32>:$output2, 1306 Variadic<I32>:$output3 1307 ); 1308 1309 // We will use this op in a nested result pattern, where we cannot deduce the 1310 // result type. So need to provide a builder not requiring result types. 1311 let builders = [ 1312 OpBuilder<(ins "::mlir::IntegerAttr":$count), 1313 [{ 1314 auto i32Type = $_builder.getIntegerType(32); 1315 $_state.addTypes(i32Type); // $output1 1316 SmallVector<Type, 4> types(count.getInt(), i32Type); 1317 $_state.addTypes(types); // $output2 1318 $_state.addTypes(types); // $output3 1319 $_state.addAttribute("count", count); 1320 }]> 1321 ]; 1322} 1323 1324// Generates an op with variadic results using nested pattern. 1325def : Pat<(OneI32ResultOp), 1326 (MixedVOperandOp3 1327 (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">), 1328 (replaceWithValue $results__1), 1329 (replaceWithValue $results__2), 1330 ConstantAttr<I32Attr, "2">)>; 1331 1332//===----------------------------------------------------------------------===// 1333// Test Patterns (Location) 1334 1335// Test that we can specify locations for generated ops. 1336def : Pat<(TestLocationSrcOp:$res1 1337 (TestLocationSrcOp:$res2 1338 (TestLocationSrcOp:$res3 $input))), 1339 (TestLocationDstOp 1340 (TestLocationDstOp 1341 (TestLocationDstOp $input, (location $res1)), 1342 (location "named")), 1343 (location "fused", $res2, $res3))>; 1344 1345//===----------------------------------------------------------------------===// 1346// Test Patterns (Type Builders) 1347 1348def SourceOp : TEST_Op<"source_op"> { 1349 let arguments = (ins AnyInteger:$arg, AnyI32Attr:$tag); 1350 let results = (outs AnyInteger); 1351} 1352 1353// An op without return type deduction. 1354def OpX : TEST_Op<"op_x"> { 1355 let arguments = (ins AnyInteger:$input); 1356 let results = (outs AnyInteger); 1357} 1358 1359// Test that ops without built-in type deduction can be created in the 1360// replacement DAG with an explicitly specified type. 1361def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "11">:$attr), 1362 (OpX (OpX $val, (returnType "$_builder.getI32Type()")))>; 1363// Test NativeCodeCall type builder can accept arguments. 1364def SameTypeAs : NativeCodeCall<"$0.getType()">; 1365 1366def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "22">:$attr), 1367 (OpX (OpX $val, (returnType (SameTypeAs $val))))>; 1368 1369// Test multiple return types. 1370def MakeI64Type : NativeCodeCall<"$_builder.getI64Type()">; 1371def MakeI32Type : NativeCodeCall<"$_builder.getI32Type()">; 1372 1373def OneToTwo : TEST_Op<"one_to_two"> { 1374 let arguments = (ins AnyInteger); 1375 let results = (outs AnyInteger, AnyInteger); 1376} 1377 1378def TwoToOne : TEST_Op<"two_to_one"> { 1379 let arguments = (ins AnyInteger, AnyInteger); 1380 let results = (outs AnyInteger); 1381} 1382 1383def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "33">:$attr), 1384 (TwoToOne (OpX (OneToTwo:$res__0 $val, (returnType (MakeI64Type), (MakeI32Type))), (returnType (MakeI32Type))), 1385 (OpX $res__1, (returnType (MakeI64Type))))>; 1386 1387// Test copy value return type. 1388def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "44">:$attr), 1389 (OpX (OpX $val, (returnType $val)))>; 1390 1391// Test create multiple return types with different methods. 1392def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "55">:$attr), 1393 (TwoToOne (OneToTwo:$res__0 $val, (returnType $val, "$_builder.getI64Type()")), $res__1)>; 1394 1395//===----------------------------------------------------------------------===// 1396// Test Patterns (Trailing Directives) 1397 1398// Test that we can specify both `location` and `returnType` directives. 1399def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "66">:$attr), 1400 (TwoToOne (OpX $val, (returnType $val), (location "loc1")), 1401 (OpX $val, (location "loc2"), (returnType $val)))>; 1402 1403//===----------------------------------------------------------------------===// 1404// Test Legalization 1405//===----------------------------------------------------------------------===// 1406 1407def Test_LegalizerEnum_Success : StrEnumAttrCase<"Success">; 1408def Test_LegalizerEnum_Failure : StrEnumAttrCase<"Failure">; 1409 1410def Test_LegalizerEnum : StrEnumAttr<"Success", "Failure", 1411 [Test_LegalizerEnum_Success, Test_LegalizerEnum_Failure]>; 1412 1413def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>; 1414def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>; 1415def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>; 1416def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>; 1417def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>; 1418def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>; 1419def ILLegalOpG : TEST_Op<"illegal_op_g">, Results<(outs I32)>; 1420def LegalOpA : TEST_Op<"legal_op_a">, 1421 Arguments<(ins Test_LegalizerEnum:$status)>, Results<(outs I32)>; 1422def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>; 1423def LegalOpC : TEST_Op<"legal_op_c">, 1424 Arguments<(ins I32)>, Results<(outs I32)>; 1425 1426// Check that the conversion infrastructure can properly undo the creation of 1427// operations where an operation was created before its parent, in this case, 1428// in the parent's builder. 1429def IllegalOpTerminator : TEST_Op<"illegal_op_terminator", [Terminator]>; 1430def IllegalOpWithRegion : TEST_Op<"illegal_op_with_region"> { 1431 let skipDefaultBuilders = 1; 1432 let builders = [OpBuilder<(ins), 1433 [{ 1434 Region *bodyRegion = $_state.addRegion(); 1435 OpBuilder::InsertionGuard g($_builder); 1436 Block *body = $_builder.createBlock(bodyRegion); 1437 $_builder.setInsertionPointToEnd(body); 1438 $_builder.create<IllegalOpTerminator>($_state.location); 1439 }]>]; 1440} 1441def IllegalOpWithRegionAnchor : TEST_Op<"illegal_op_with_region_anchor">; 1442 1443// Check that smaller pattern depths are chosen, i.e. prioritize more direct 1444// mappings. 1445def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>; 1446 1447def : Pat<(ILLegalOpA), (ILLegalOpB)>; 1448def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>; 1449 1450// Check that the higher benefit pattern is taken for multiple legalizations 1451// with the same depth. 1452def : Pat<(ILLegalOpC), (ILLegalOpD)>; 1453def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>; 1454 1455def : Pat<(ILLegalOpC), (ILLegalOpE), [], (addBenefit 10)>; 1456def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>; 1457 1458// Check that patterns use the most up-to-date value when being replaced. 1459def TestRewriteOp : TEST_Op<"rewrite">, 1460 Arguments<(ins AnyType)>, Results<(outs AnyType)>; 1461def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>; 1462 1463// Check that patterns can specify bounded recursion when rewriting. 1464def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> { 1465 let arguments = (ins I64Attr:$depth); 1466 let assemblyFormat = "$depth attr-dict"; 1467} 1468 1469// Test legalization pattern: this op will be erase and will also erase the 1470// producer of its operand. 1471def BlackHoleOp : TEST_Op<"blackhole">, 1472 Arguments<(ins AnyType)>; 1473 1474//===----------------------------------------------------------------------===// 1475// Test Type Legalization 1476//===----------------------------------------------------------------------===// 1477 1478def TestRegionBuilderOp : TEST_Op<"region_builder">; 1479def TestReturnOp : TEST_Op<"return", [ReturnLike, Terminator]> { 1480 let arguments = (ins Variadic<AnyType>); 1481 let builders = [OpBuilder<(ins), 1482 [{ build($_builder, $_state, {}); }]> 1483 ]; 1484} 1485def TestCastOp : TEST_Op<"cast">, 1486 Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>; 1487def TestInvalidOp : TEST_Op<"invalid", [Terminator]>, 1488 Arguments<(ins Variadic<AnyType>)>; 1489def TestTypeProducerOp : TEST_Op<"type_producer">, 1490 Results<(outs AnyType)>; 1491def TestAnotherTypeProducerOp : TEST_Op<"another_type_producer">, 1492 Results<(outs AnyType)>; 1493def TestTypeConsumerOp : TEST_Op<"type_consumer">, 1494 Arguments<(ins AnyType)>; 1495def TestValidOp : TEST_Op<"valid", [Terminator]>, 1496 Arguments<(ins Variadic<AnyType>)>; 1497 1498def TestMergeBlocksOp : TEST_Op<"merge_blocks"> { 1499 let summary = "merge_blocks operation"; 1500 let description = [{ 1501 Test op with multiple blocks that are merged with Dialect Conversion" 1502 }]; 1503 1504 let regions = (region AnyRegion:$body); 1505 let results = (outs Variadic<AnyType>:$result); 1506} 1507 1508def TestSignatureConversionUndoOp : TEST_Op<"signature_conversion_undo"> { 1509 let regions = (region AnyRegion); 1510} 1511 1512//===----------------------------------------------------------------------===// 1513// Test parser. 1514//===----------------------------------------------------------------------===// 1515 1516def ParseIntegerLiteralOp : TEST_Op<"parse_integer_literal"> { 1517 let results = (outs Variadic<Index>:$results); 1518 let parser = [{ return ::parse$cppClass(parser, result); }]; 1519 let printer = [{ return ::print(p, *this); }]; 1520} 1521 1522def ParseWrappedKeywordOp : TEST_Op<"parse_wrapped_keyword"> { 1523 let arguments = (ins StrAttr:$keyword); 1524 let parser = [{ return ::parse$cppClass(parser, result); }]; 1525 let printer = [{ return ::print(p, *this); }]; 1526} 1527 1528//===----------------------------------------------------------------------===// 1529// Test region argument list parsing. 1530 1531def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> { 1532 let summary = "isolated region operation"; 1533 let description = [{ 1534 Test op with an isolated region, to test passthrough region arguments. Each 1535 argument is of index type. 1536 }]; 1537 1538 let arguments = (ins Index); 1539 let regions = (region SizedRegion<1>:$region); 1540 let parser = [{ return ::parse$cppClass(parser, result); }]; 1541 let printer = [{ return ::print(p, *this); }]; 1542} 1543 1544def SSACFGRegionOp : TEST_Op<"ssacfg_region", [ 1545 DeclareOpInterfaceMethods<RegionKindInterface>]> { 1546 let summary = "operation with an SSACFG region"; 1547 let description = [{ 1548 Test op that defines an SSACFG region. 1549 }]; 1550 1551 let regions = (region VariadicRegion<AnyRegion>:$regions); 1552 let arguments = (ins Variadic<AnyType>); 1553 let results = (outs Variadic<AnyType>); 1554} 1555 1556def GraphRegionOp : TEST_Op<"graph_region", [ 1557 DeclareOpInterfaceMethods<RegionKindInterface>]> { 1558 let summary = "operation with a graph region"; 1559 let description = [{ 1560 Test op that defines a graph region. 1561 }]; 1562 1563 let regions = (region AnyRegion:$region); 1564 let parser = [{ return ::parse$cppClass(parser, result); }]; 1565 let printer = [{ return ::print(p, *this); }]; 1566} 1567 1568def AffineScopeOp : TEST_Op<"affine_scope", [AffineScope]> { 1569 let summary = "affine scope operation"; 1570 let description = [{ 1571 Test op that defines a new affine scope. 1572 }]; 1573 1574 let regions = (region SizedRegion<1>:$region); 1575 let parser = [{ return ::parse$cppClass(parser, result); }]; 1576 let printer = [{ return ::print(p, *this); }]; 1577} 1578 1579def WrappingRegionOp : TEST_Op<"wrapping_region", 1580 [SingleBlockImplicitTerminator<"TestReturnOp">]> { 1581 let summary = "wrapping region operation"; 1582 let description = [{ 1583 Test op wrapping another op in a region, to test calling 1584 parseGenericOperation from the custom parser. 1585 }]; 1586 1587 let results = (outs Variadic<AnyType>); 1588 let regions = (region SizedRegion<1>:$region); 1589 let parser = [{ return ::parse$cppClass(parser, result); }]; 1590 let printer = [{ return ::print(p, *this); }]; 1591} 1592 1593def PolyForOp : TEST_Op<"polyfor"> 1594{ 1595 let summary = "polyfor operation"; 1596 let description = [{ 1597 Test op with multiple region arguments, each argument of index type. 1598 }]; 1599 1600 let regions = (region SizedRegion<1>:$region); 1601 let parser = [{ return ::parse$cppClass(parser, result); }]; 1602} 1603 1604//===----------------------------------------------------------------------===// 1605// Test OpAsmInterface. 1606 1607def AsmInterfaceOp : TEST_Op<"asm_interface_op"> { 1608 let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results, 1609 AnyType); 1610} 1611 1612def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> { 1613 let results = (outs AnyType); 1614} 1615 1616//===----------------------------------------------------------------------===// 1617// Test Op Asm Format 1618//===----------------------------------------------------------------------===// 1619 1620def FormatLiteralOp : TEST_Op<"format_literal_op"> { 1621 let assemblyFormat = [{ 1622 `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` `` `(` ` ` `)` 1623 `?` `+` `*` `{` `\n` `}` attr-dict 1624 }]; 1625} 1626 1627// Test that we elide attributes that are within the syntax. 1628def FormatAttrOp : TEST_Op<"format_attr_op"> { 1629 let arguments = (ins I64Attr:$attr); 1630 let assemblyFormat = "$attr attr-dict"; 1631} 1632 1633// Test that we elide optional attributes that are within the syntax. 1634def FormatOptAttrAOp : TEST_Op<"format_opt_attr_op_a"> { 1635 let arguments = (ins OptionalAttr<I64Attr>:$opt_attr); 1636 let assemblyFormat = "(`(` $opt_attr^ `)` )? attr-dict"; 1637} 1638def FormatOptAttrBOp : TEST_Op<"format_opt_attr_op_b"> { 1639 let arguments = (ins OptionalAttr<I64Attr>:$opt_attr); 1640 let assemblyFormat = "($opt_attr^)? attr-dict"; 1641} 1642 1643// Test that we format symbol name attributes properly. 1644def FormatSymbolNameAttrOp : TEST_Op<"format_symbol_name_attr_op"> { 1645 let arguments = (ins SymbolNameAttr:$attr); 1646 let assemblyFormat = "$attr attr-dict"; 1647} 1648 1649// Test that we format optional symbol name attributes properly. 1650def FormatOptSymbolNameAttrOp : TEST_Op<"format_opt_symbol_name_attr_op"> { 1651 let arguments = (ins OptionalAttr<SymbolNameAttr>:$opt_attr); 1652 let assemblyFormat = "($opt_attr^)? attr-dict"; 1653} 1654 1655// Test that we elide attributes that are within the syntax. 1656def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> { 1657 let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$opt_attr); 1658 let assemblyFormat = "attr-dict-with-keyword"; 1659} 1660 1661// Test that we don't need to provide types in the format if they are buildable. 1662def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> { 1663 let arguments = (ins I64:$buildable); 1664 let results = (outs I64:$buildable_res); 1665 let assemblyFormat = "$buildable attr-dict"; 1666} 1667 1668// Test various mixings of region formatting. 1669class FormatRegionBase<string suffix, string fmt> 1670 : TEST_Op<"format_region_" # suffix # "_op"> { 1671 let regions = (region AnyRegion:$region); 1672 let assemblyFormat = fmt; 1673} 1674def FormatRegionAOp : FormatRegionBase<"a", [{ 1675 regions attr-dict 1676}]>; 1677def FormatRegionBOp : FormatRegionBase<"b", [{ 1678 $region attr-dict 1679}]>; 1680def FormatRegionCOp : FormatRegionBase<"c", [{ 1681 (`region` $region^)? attr-dict 1682}]>; 1683class FormatVariadicRegionBase<string suffix, string fmt> 1684 : TEST_Op<"format_variadic_region_" # suffix # "_op"> { 1685 let regions = (region VariadicRegion<AnyRegion>:$regions); 1686 let assemblyFormat = fmt; 1687} 1688def FormatVariadicRegionAOp : FormatVariadicRegionBase<"a", [{ 1689 $regions attr-dict 1690}]>; 1691def FormatVariadicRegionBOp : FormatVariadicRegionBase<"b", [{ 1692 ($regions^ `found_regions`)? attr-dict 1693}]>; 1694class FormatRegionImplicitTerminatorBase<string suffix, string fmt> 1695 : TEST_Op<"format_implicit_terminator_region_" # suffix # "_op", 1696 [SingleBlockImplicitTerminator<"TestReturnOp">]> { 1697 let regions = (region AnyRegion:$region); 1698 let assemblyFormat = fmt; 1699} 1700def FormatFormatRegionImplicitTerminatorAOp 1701 : FormatRegionImplicitTerminatorBase<"a", [{ 1702 $region attr-dict 1703}]>; 1704 1705// Test various mixings of result type formatting. 1706class FormatResultBase<string suffix, string fmt> 1707 : TEST_Op<"format_result_" # suffix # "_op"> { 1708 let results = (outs I64:$buildable_res, AnyMemRef:$result); 1709 let assemblyFormat = fmt; 1710} 1711def FormatResultAOp : FormatResultBase<"a", [{ 1712 type($result) attr-dict 1713}]>; 1714def FormatResultBOp : FormatResultBase<"b", [{ 1715 type(results) attr-dict 1716}]>; 1717def FormatResultCOp : FormatResultBase<"c", [{ 1718 functional-type($buildable_res, $result) attr-dict 1719}]>; 1720 1721def FormatVariadicResult : TEST_Op<"format_variadic_result"> { 1722 let results = (outs Variadic<I64>:$result); 1723 let assemblyFormat = [{ `:` type($result) attr-dict}]; 1724} 1725 1726def FormatMultipleVariadicResults : TEST_Op<"format_multiple_variadic_results", 1727 [AttrSizedResultSegments]> { 1728 let results = (outs Variadic<I64>:$result0, Variadic<AnyType>:$result1); 1729 let assemblyFormat = [{ 1730 `:` `(` type($result0) `)` `,` `(` type($result1) `)` attr-dict 1731 }]; 1732} 1733 1734// Test various mixings of operand type formatting. 1735class FormatOperandBase<string suffix, string fmt> 1736 : TEST_Op<"format_operand_" # suffix # "_op"> { 1737 let arguments = (ins I64:$buildable, AnyMemRef:$operand); 1738 let assemblyFormat = fmt; 1739} 1740 1741def FormatOperandAOp : FormatOperandBase<"a", [{ 1742 operands `:` type(operands) attr-dict 1743}]>; 1744def FormatOperandBOp : FormatOperandBase<"b", [{ 1745 operands `:` type($operand) attr-dict 1746}]>; 1747def FormatOperandCOp : FormatOperandBase<"c", [{ 1748 $buildable `,` $operand `:` type(operands) attr-dict 1749}]>; 1750def FormatOperandDOp : FormatOperandBase<"d", [{ 1751 $buildable `,` $operand `:` type($operand) attr-dict 1752}]>; 1753def FormatOperandEOp : FormatOperandBase<"e", [{ 1754 $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict 1755}]>; 1756 1757def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> { 1758 let successors = (successor VariadicSuccessor<AnySuccessor>:$targets); 1759 let assemblyFormat = "$targets attr-dict"; 1760} 1761 1762def FormatVariadicOperand : TEST_Op<"format_variadic_operand"> { 1763 let arguments = (ins Variadic<I64>:$operand); 1764 let assemblyFormat = [{ $operand `:` type($operand) attr-dict}]; 1765} 1766def FormatVariadicOfVariadicOperand 1767 : TEST_Op<"format_variadic_of_variadic_operand"> { 1768 let arguments = (ins 1769 VariadicOfVariadic<I64, "operand_segments">:$operand, 1770 I32ElementsAttr:$operand_segments 1771 ); 1772 let assemblyFormat = [{ $operand `:` type($operand) attr-dict}]; 1773} 1774 1775def FormatMultipleVariadicOperands : 1776 TEST_Op<"format_multiple_variadic_operands", [AttrSizedOperandSegments]> { 1777 let arguments = (ins Variadic<I64>:$operand0, Variadic<AnyType>:$operand1); 1778 let assemblyFormat = [{ 1779 ` ` `(` $operand0 `)` `,` `(` $operand1 `:` type($operand1) `)` attr-dict 1780 }]; 1781} 1782 1783// Test various mixings of optional operand and result type formatting. 1784class FormatOptionalOperandResultOpBase<string suffix, string fmt> 1785 : TEST_Op<"format_optional_operand_result_" # suffix # "_op", 1786 [AttrSizedOperandSegments]> { 1787 let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic); 1788 let results = (outs Optional<I64>:$optional_res); 1789 let assemblyFormat = fmt; 1790} 1791 1792def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{ 1793 `(` $optional `:` type($optional) `)` `:` type($optional_res) 1794 (`[` $variadic^ `]`)? attr-dict 1795}]>; 1796 1797def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{ 1798 (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res) 1799 (`[` $variadic^ `]`)? attr-dict 1800}]>; 1801 1802// Test optional result type formatting. 1803class FormatOptionalResultOpBase<string suffix, string fmt> 1804 : TEST_Op<"format_optional_result_" # suffix # "_op", 1805 [AttrSizedResultSegments]> { 1806 let results = (outs Optional<I64>:$optional, Variadic<I64>:$variadic); 1807 let assemblyFormat = fmt; 1808} 1809def FormatOptionalResultAOp : FormatOptionalResultOpBase<"a", [{ 1810 (`:` type($optional)^ `->` type($variadic))? attr-dict 1811}]>; 1812 1813def FormatOptionalResultBOp : FormatOptionalResultOpBase<"b", [{ 1814 (`:` type($optional) `->` type($variadic)^)? attr-dict 1815}]>; 1816 1817def FormatOptionalResultCOp : FormatOptionalResultOpBase<"c", [{ 1818 (`:` functional-type($optional, $variadic)^)? attr-dict 1819}]>; 1820 1821def FormatTwoVariadicOperandsNoBuildableTypeOp 1822 : TEST_Op<"format_two_variadic_operands_no_buildable_type_op", 1823 [AttrSizedOperandSegments]> { 1824 let arguments = (ins Variadic<AnyType>:$a, 1825 Variadic<AnyType>:$b); 1826 let assemblyFormat = [{ 1827 `(` $a `:` type($a) `)` `->` `(` $b `:` type($b) `)` attr-dict 1828 }]; 1829} 1830 1831def FormatInferVariadicTypeFromNonVariadic 1832 : TEST_Op<"format_infer_variadic_type_from_non_variadic", 1833 [SameOperandsAndResultType]> { 1834 let arguments = (ins Variadic<AnyType>:$operands); 1835 let results = (outs AnyType:$result); 1836 let assemblyFormat = "$operands attr-dict `:` type($result)"; 1837} 1838 1839def FormatOptionalUnitAttr : TEST_Op<"format_optional_unit_attribute"> { 1840 let arguments = (ins UnitAttr:$is_optional); 1841 let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict"; 1842} 1843 1844def FormatOptionalUnitAttrNoElide 1845 : TEST_Op<"format_optional_unit_attribute_no_elide"> { 1846 let arguments = (ins UnitAttr:$is_optional); 1847 let assemblyFormat = "($is_optional^)? attr-dict"; 1848} 1849 1850def FormatOptionalEnumAttr : TEST_Op<"format_optional_enum_attr"> { 1851 let arguments = (ins OptionalAttr<SomeI64Enum>:$attr); 1852 let assemblyFormat = "($attr^)? attr-dict"; 1853} 1854 1855def FormatOptionalWithElse : TEST_Op<"format_optional_else"> { 1856 let arguments = (ins UnitAttr:$isFirstBranchPresent); 1857 let assemblyFormat = "(`then` $isFirstBranchPresent^):(`else`)? attr-dict"; 1858} 1859 1860//===----------------------------------------------------------------------===// 1861// Custom Directives 1862 1863def FormatCustomDirectiveOperands 1864 : TEST_Op<"format_custom_directive_operands", [AttrSizedOperandSegments]> { 1865 let arguments = (ins I64:$operand, Optional<I64>:$optOperand, 1866 Variadic<I64>:$varOperands); 1867 let assemblyFormat = [{ 1868 custom<CustomDirectiveOperands>( 1869 $operand, $optOperand, $varOperands 1870 ) 1871 attr-dict 1872 }]; 1873} 1874 1875def FormatCustomDirectiveOperandsAndTypes 1876 : TEST_Op<"format_custom_directive_operands_and_types", 1877 [AttrSizedOperandSegments]> { 1878 let arguments = (ins AnyType:$operand, Optional<AnyType>:$optOperand, 1879 Variadic<AnyType>:$varOperands); 1880 let assemblyFormat = [{ 1881 custom<CustomDirectiveOperandsAndTypes>( 1882 $operand, $optOperand, $varOperands, 1883 type($operand), type($optOperand), type($varOperands) 1884 ) 1885 attr-dict 1886 }]; 1887} 1888 1889def FormatCustomDirectiveRegions : TEST_Op<"format_custom_directive_regions"> { 1890 let regions = (region AnyRegion:$region, VariadicRegion<AnyRegion>:$regions); 1891 let assemblyFormat = [{ 1892 custom<CustomDirectiveRegions>( 1893 $region, $regions 1894 ) 1895 attr-dict 1896 }]; 1897} 1898 1899def FormatCustomDirectiveResults 1900 : TEST_Op<"format_custom_directive_results", [AttrSizedResultSegments]> { 1901 let results = (outs AnyType:$result, Optional<AnyType>:$optResult, 1902 Variadic<AnyType>:$varResults); 1903 let assemblyFormat = [{ 1904 custom<CustomDirectiveResults>( 1905 type($result), type($optResult), type($varResults) 1906 ) 1907 attr-dict 1908 }]; 1909} 1910 1911def FormatCustomDirectiveResultsWithTypeRefs 1912 : TEST_Op<"format_custom_directive_results_with_type_refs", 1913 [AttrSizedResultSegments]> { 1914 let results = (outs AnyType:$result, Optional<AnyType>:$optResult, 1915 Variadic<AnyType>:$varResults); 1916 let assemblyFormat = [{ 1917 custom<CustomDirectiveResults>( 1918 type($result), type($optResult), type($varResults) 1919 ) 1920 custom<CustomDirectiveWithTypeRefs>( 1921 ref(type($result)), ref(type($optResult)), ref(type($varResults)) 1922 ) 1923 attr-dict 1924 }]; 1925} 1926 1927def FormatCustomDirectiveWithOptionalOperandRef 1928 : TEST_Op<"format_custom_directive_with_optional_operand_ref"> { 1929 let arguments = (ins Optional<I64>:$optOperand); 1930 let assemblyFormat = [{ 1931 ($optOperand^)? `:` 1932 custom<CustomDirectiveOptionalOperandRef>(ref($optOperand)) 1933 attr-dict 1934 }]; 1935} 1936 1937def FormatCustomDirectiveSuccessors 1938 : TEST_Op<"format_custom_directive_successors", [Terminator]> { 1939 let successors = (successor AnySuccessor:$successor, 1940 VariadicSuccessor<AnySuccessor>:$successors); 1941 let assemblyFormat = [{ 1942 custom<CustomDirectiveSuccessors>( 1943 $successor, $successors 1944 ) 1945 attr-dict 1946 }]; 1947} 1948 1949def FormatCustomDirectiveAttributes 1950 : TEST_Op<"format_custom_directive_attributes"> { 1951 let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr); 1952 let assemblyFormat = [{ 1953 custom<CustomDirectiveAttributes>( 1954 $attr, $optAttr 1955 ) 1956 attr-dict 1957 }]; 1958} 1959 1960def FormatCustomDirectiveAttrDict 1961 : TEST_Op<"format_custom_directive_attrdict"> { 1962 let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr); 1963 let assemblyFormat = [{ 1964 custom<CustomDirectiveAttrDict>( attr-dict ) 1965 }]; 1966} 1967 1968//===----------------------------------------------------------------------===// 1969// AllTypesMatch type inference 1970 1971def FormatAllTypesMatchVarOp : TEST_Op<"format_all_types_match_var", [ 1972 AllTypesMatch<["value1", "value2", "result"]> 1973 ]> { 1974 let arguments = (ins AnyType:$value1, AnyType:$value2); 1975 let results = (outs AnyType:$result); 1976 let assemblyFormat = "attr-dict $value1 `,` $value2 `:` type($value1)"; 1977} 1978 1979def FormatAllTypesMatchAttrOp : TEST_Op<"format_all_types_match_attr", [ 1980 AllTypesMatch<["value1", "value2", "result"]> 1981 ]> { 1982 let arguments = (ins AnyAttr:$value1, AnyType:$value2); 1983 let results = (outs AnyType:$result); 1984 let assemblyFormat = "attr-dict $value1 `,` $value2"; 1985} 1986 1987//===----------------------------------------------------------------------===// 1988// TypesMatchWith type inference 1989 1990def FormatTypesMatchVarOp : TEST_Op<"format_types_match_var", [ 1991 TypesMatchWith<"result type matches operand", "value", "result", "$_self"> 1992 ]> { 1993 let arguments = (ins AnyType:$value); 1994 let results = (outs AnyType:$result); 1995 let assemblyFormat = "attr-dict $value `:` type($value)"; 1996} 1997 1998def FormatTypesMatchVariadicOp : TEST_Op<"format_types_match_variadic", [ 1999 RangedTypesMatchWith<"result type matches operand", "value", "result", 2000 "llvm::make_range($_self.begin(), $_self.end())"> 2001 ]> { 2002 let arguments = (ins Variadic<AnyType>:$value); 2003 let results = (outs Variadic<AnyType>:$result); 2004 let assemblyFormat = "attr-dict $value `:` type($value)"; 2005} 2006 2007def FormatTypesMatchAttrOp : TEST_Op<"format_types_match_attr", [ 2008 TypesMatchWith<"result type matches constant", "value", "result", "$_self"> 2009 ]> { 2010 let arguments = (ins AnyAttr:$value); 2011 let results = (outs AnyType:$result); 2012 let assemblyFormat = "attr-dict $value"; 2013} 2014 2015def FormatTypesMatchContextOp : TEST_Op<"format_types_match_context", [ 2016 TypesMatchWith<"tuple result type matches operand type", "value", "result", 2017 "::mlir::TupleType::get($_ctxt, $_self)"> 2018 ]> { 2019 let arguments = (ins AnyType:$value); 2020 let results = (outs AnyType:$result); 2021 let assemblyFormat = "attr-dict $value `:` type($value)"; 2022} 2023 2024//===----------------------------------------------------------------------===// 2025// InferTypeOpInterface type inference in assembly format 2026 2027def FormatInferTypeOp : TEST_Op<"format_infer_type", [InferTypeOpInterface]> { 2028 let results = (outs AnyType); 2029 let assemblyFormat = "attr-dict"; 2030 2031 let extraClassDeclaration = [{ 2032 static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, 2033 ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands, 2034 ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions, 2035 ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) { 2036 inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)}); 2037 return ::mlir::success(); 2038 } 2039 }]; 2040} 2041 2042//===----------------------------------------------------------------------===// 2043// Test SideEffects 2044//===----------------------------------------------------------------------===// 2045 2046def SideEffectOp : TEST_Op<"side_effect_op", 2047 [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 2048 DeclareOpInterfaceMethods<TestEffectOpInterface>]> { 2049 let results = (outs AnyType:$result); 2050} 2051 2052//===----------------------------------------------------------------------===// 2053// Test CopyOpInterface 2054//===----------------------------------------------------------------------===// 2055 2056def CopyOp : TEST_Op<"copy", [CopyOpInterface]> { 2057 let description = [{ 2058 Represents a copy operation. 2059 }]; 2060 let arguments = (ins Res<AnyRankedOrUnrankedMemRef, "", [MemRead]>:$source, 2061 Res<AnyRankedOrUnrankedMemRef, "", [MemWrite]>:$target); 2062 let assemblyFormat = [{ 2063 `(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)` 2064 attr-dict 2065 }]; 2066 let extraClassDeclaration = [{ 2067 ::mlir::Value getSource() { return source(); } 2068 ::mlir::Value getTarget() { return target(); } 2069 }]; 2070} 2071 2072//===----------------------------------------------------------------------===// 2073// Test Buffer/Tensor 2074//===----------------------------------------------------------------------===// 2075 2076def RegionYieldOp : TEST_Op<"region_yield", 2077 [NoSideEffect, ReturnLike, Terminator]> { 2078 let description = [{ 2079 This operation is used in a region and yields the corresponding type for 2080 that operation. 2081 }]; 2082 let arguments = (ins AnyType:$result); 2083 let assemblyFormat = [{ 2084 $result `:` type($result) attr-dict 2085 }]; 2086 let builders = [OpBuilder<(ins), 2087 [{ build($_builder, $_state, {}); }]> 2088 ]; 2089} 2090 2091class BufferBasedOpBase<string mnemonic, list<OpTrait> traits> 2092 : TEST_Op<mnemonic, traits> { 2093 let description = [{ 2094 A buffer based operation, that uses memRefs as input and output. 2095 }]; 2096 let arguments = (ins AnyRankedOrUnrankedMemRef:$input, 2097 AnyRankedOrUnrankedMemRef:$output); 2098} 2099 2100def BufferBasedOp : BufferBasedOpBase<"buffer_based", []>{ 2101 let assemblyFormat = [{ 2102 `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)` 2103 attr-dict 2104 }]; 2105} 2106 2107def RegionBufferBasedOp : BufferBasedOpBase<"region_buffer_based", 2108 [SingleBlockImplicitTerminator<"RegionYieldOp">]> { 2109 let regions = (region AnyRegion:$region); 2110 let assemblyFormat = [{ 2111 `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)` 2112 $region attr-dict 2113 }]; 2114} 2115 2116def TensorBasedOp : TEST_Op<"tensor_based", []> { 2117 let description = [{ 2118 A tensor based operation, that uses a tensor as an input and results in a 2119 tensor again. 2120 }]; 2121 let arguments = (ins AnyRankedTensor:$input); 2122 let results = (outs AnyRankedTensor:$result); 2123 let assemblyFormat = [{ 2124 `in` `(` $input`:` type($input) `)` `->` type($result) attr-dict 2125 }]; 2126} 2127 2128//===----------------------------------------------------------------------===// 2129// Test RegionBranchOpInterface 2130//===----------------------------------------------------------------------===// 2131 2132def RegionIfYieldOp : TEST_Op<"region_if_yield", 2133 [NoSideEffect, ReturnLike, Terminator]> { 2134 let arguments = (ins Variadic<AnyType>:$results); 2135 let assemblyFormat = [{ 2136 $results `:` type($results) attr-dict 2137 }]; 2138} 2139 2140def RegionIfOp : TEST_Op<"region_if", 2141 [DeclareOpInterfaceMethods<RegionBranchOpInterface>, 2142 SingleBlockImplicitTerminator<"RegionIfYieldOp">, 2143 RecursiveSideEffects]> { 2144 let description =[{ 2145 Represents an abstract if-then-else-join pattern. In this context, the then 2146 and else regions jump to the join region, which finally returns to its 2147 parent op. 2148 }]; 2149 2150 let printer = [{ return ::print(p, *this); }]; 2151 let parser = [{ return ::parseRegionIfOp(parser, result); }]; 2152 let arguments = (ins Variadic<AnyType>); 2153 let results = (outs Variadic<AnyType>:$results); 2154 let regions = (region SizedRegion<1>:$thenRegion, 2155 AnyRegion:$elseRegion, 2156 AnyRegion:$joinRegion); 2157 let extraClassDeclaration = [{ 2158 ::mlir::Block::BlockArgListType getThenArgs() { 2159 return getBody(0)->getArguments(); 2160 } 2161 ::mlir::Block::BlockArgListType getElseArgs() { 2162 return getBody(1)->getArguments(); 2163 } 2164 ::mlir::Block::BlockArgListType getJoinArgs() { 2165 return getBody(2)->getArguments(); 2166 } 2167 ::mlir::OperandRange getSuccessorEntryOperands(unsigned index); 2168 }]; 2169} 2170 2171//===----------------------------------------------------------------------===// 2172// Test TableGen generated build() methods 2173//===----------------------------------------------------------------------===// 2174 2175def TableGenConstant : TEST_Op<"tblgen_constant"> { 2176 let results = (outs AnyType); 2177} 2178 2179// No variadic args or results. 2180def TableGenBuildOp0 : TEST_Op<"tblgen_build_0"> { 2181 let arguments = (ins AnyType:$value); 2182 let results = (outs AnyType:$result); 2183} 2184 2185// Sigle variadic arg and single variadic results. 2186def TableGenBuildOp1 : TEST_Op<"tblgen_build_1"> { 2187 let arguments = (ins Variadic<AnyType>:$inputs); 2188 let results = (outs Variadic<AnyType>:$results); 2189} 2190 2191// Single variadic arg and non-variadic results. 2192def TableGenBuildOp2 : TEST_Op<"tblgen_build_2"> { 2193 let arguments = (ins Variadic<AnyType>:$inputs); 2194 let results = (outs AnyType:$result); 2195} 2196 2197// Single variadic arg and multiple variadic results. 2198def TableGenBuildOp3 : TEST_Op<"tblgen_build_3", [SameVariadicResultSize]> { 2199 let arguments = (ins Variadic<AnyType>:$inputs); 2200 let results = (outs Variadic<AnyType>:$resultA, Variadic<AnyType>:$resultB); 2201} 2202 2203// Single variadic arg, non variadic results, with SameOperandsAndResultType. 2204// Tests suppression of ambiguous build methods for operations with 2205// SameOperandsAndResultType trait. 2206def TableGenBuildOp4 : TEST_Op<"tblgen_build_4", [SameOperandsAndResultType]> { 2207 let arguments = (ins Variadic<AnyType>:$inputs); 2208 let results = (outs AnyType:$result); 2209} 2210 2211// Single variadic arg with SameOperandsAndResultType and InferTypeOpInterface. 2212// Tests suppression of ambiguous build methods for operations with 2213// SameOperandsAndResultType and InferTypeOpInterface. 2214def TableGenBuildOp5 : TEST_Op<"tblgen_build_5", 2215 [SameOperandsAndResultType, InferTypeOpInterface]> { 2216 let arguments = (ins Variadic<AnyType>:$inputs); 2217 let results = (outs AnyType:$result); 2218 2219 let extraClassDeclaration = [{ 2220 static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *, 2221 ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands, 2222 ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions, 2223 ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) { 2224 inferredReturnTypes.assign({operands[0].getType()}); 2225 return ::mlir::success(); 2226 } 2227 }]; 2228} 2229 2230//===----------------------------------------------------------------------===// 2231// Test BufferPlacement 2232//===----------------------------------------------------------------------===// 2233 2234def GetTupleElementOp: TEST_Op<"get_tuple_element"> { 2235 let description = [{ 2236 Test op that returns a specified element of the tuple. 2237 }]; 2238 2239 let arguments = (ins 2240 TupleOf<[AnyType]>, 2241 I32Attr:$index 2242 ); 2243 let results = (outs AnyType); 2244} 2245 2246def MakeTupleOp: TEST_Op<"make_tuple"> { 2247 let description = [{ 2248 Test op that creates a tuple value from a list of values. 2249 }]; 2250 2251 let arguments = (ins 2252 Variadic<AnyType>:$inputs 2253 ); 2254 let results = (outs TupleOf<[AnyType]>); 2255} 2256 2257//===----------------------------------------------------------------------===// 2258// Test Target DataLayout 2259//===----------------------------------------------------------------------===// 2260 2261def OpWithDataLayoutOp : TEST_Op<"op_with_data_layout", 2262 [HasDefaultDLTIDataLayout, DataLayoutOpInterface]> { 2263 let summary = 2264 "An op that uses DataLayout implementation from the Target dialect"; 2265 let regions = (region VariadicRegion<AnyRegion>:$regions); 2266} 2267 2268def DataLayoutQueryOp : TEST_Op<"data_layout_query"> { 2269 let summary = "A token op recognized by data layout query test pass"; 2270 let description = [{ 2271 The data layout query pass pattern-matches this op and attaches to it an 2272 array attribute containing the result of data layout query of the result 2273 type of this op. 2274 }]; 2275 2276 let results = (outs AnyType:$res); 2277} 2278 2279//===----------------------------------------------------------------------===// 2280// Test Reducer Patterns 2281//===----------------------------------------------------------------------===// 2282 2283def OpCrashLong : TEST_Op<"op_crash_long"> { 2284 let arguments = (ins I32, I32, I32); 2285 let results = (outs I32); 2286} 2287 2288def OpCrashShort : TEST_Op<"op_crash_short"> { 2289 let results = (outs I32); 2290} 2291 2292def : Pat<(OpCrashLong $_, $_, $_), (OpCrashShort)>; 2293 2294//===----------------------------------------------------------------------===// 2295// Test LinalgConvolutionOpInterface. 2296//===----------------------------------------------------------------------===// 2297 2298def TestLinalgConvOpNotLinalgOp : TEST_Op<"conv_op_not_linalg_op", [ 2299 LinalgConvolutionOpInterface]> { 2300 let arguments = (ins 2301 AnyType:$image, AnyType:$filter, AnyType:$output); 2302 let results = (outs AnyRankedTensor:$result); 2303} 2304 2305def TestLinalgConvOp : 2306 TEST_Op<"linalg_conv_op", [AttrSizedOperandSegments, 2307 LinalgStructuredInterface, LinalgConvolutionOpInterface]> { 2308 2309 let arguments = (ins Variadic<AnyType>:$inputs, 2310 Variadic<AnyType>:$outputs); 2311 let results = (outs Variadic<AnyType>:$results); 2312 let regions = (region AnyRegion:$region); 2313 2314 let assemblyFormat = [{ 2315 attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)? 2316 `outs` `(` $outputs `:` type($outputs) `)` 2317 $region (`->` type($results)^)? 2318 }]; 2319 2320 let extraClassDeclaration = [{ 2321 bool hasIndexSemantics() { return false; } 2322 2323 static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block) { 2324 b.create<mlir::linalg::YieldOp>(block.getArguments().back()); 2325 } 2326 2327 static std::function<void(mlir::ImplicitLocOpBuilder &b, mlir::Block &block)> 2328 getRegionBuilder() { 2329 return ®ionBuilder; 2330 } 2331 2332 mlir::ArrayAttr iterator_types() { 2333 return getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types"); 2334 } 2335 2336 mlir::ArrayAttr indexing_maps() { 2337 return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps"); 2338 } 2339 2340 std::string getLibraryCallName() { 2341 return ""; 2342 } 2343 }]; 2344} 2345 2346#endif // TEST_OPS 2347