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