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 OpWithResultShapePerDimInterfaceOp : TEST_Op<"op_with_result_shape_per_dim_interface", 575 [DeclareOpInterfaceMethods<InferShapedTypeOpInterface, 576 ["reifyReturnTypeShapesPerResultDim"]>]> { 577 let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2); 578 let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2); 579} 580 581def IsNotScalar : Constraint<CPred<"$0.getType().getRank() != 0">>; 582 583def UpdateAttr : Pat<(I32ElementsAttrOp $attr), 584 (I32ElementsAttrOp ConstantAttr<I32ElementsAttr, "0">), 585 [(IsNotScalar $attr)]>; 586 587def TestBranchOp : TEST_Op<"br", 588 [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator]> { 589 let arguments = (ins Variadic<AnyType>:$targetOperands); 590 let successors = (successor AnySuccessor:$target); 591} 592 593def AttrSizedOperandOp : TEST_Op<"attr_sized_operands", 594 [AttrSizedOperandSegments]> { 595 let arguments = (ins 596 Variadic<I32>:$a, 597 Variadic<I32>:$b, 598 I32:$c, 599 Variadic<I32>:$d, 600 I32ElementsAttr:$operand_segment_sizes 601 ); 602} 603 604def AttrSizedResultOp : TEST_Op<"attr_sized_results", 605 [AttrSizedResultSegments]> { 606 let arguments = (ins 607 I32ElementsAttr:$result_segment_sizes 608 ); 609 let results = (outs 610 Variadic<I32>:$a, 611 Variadic<I32>:$b, 612 I32:$c, 613 Variadic<I32>:$d 614 ); 615} 616 617// This is used to test encoding of a string attribute into an SSA name of a 618// pretty printed value name. 619def StringAttrPrettyNameOp 620 : TEST_Op<"string_attr_pretty_name", 621 [DeclareOpInterfaceMethods<OpAsmOpInterface>]> { 622 let arguments = (ins StrArrayAttr:$names); 623 let results = (outs Variadic<I32>:$r); 624 625 let printer = [{ return ::print(p, *this); }]; 626 let parser = [{ return ::parse$cppClass(parser, result); }]; 627} 628 629//===----------------------------------------------------------------------===// 630// Test Locations 631//===----------------------------------------------------------------------===// 632 633def TestLocationSrcOp : TEST_Op<"loc_src"> { 634 let arguments = (ins I32:$input); 635 let results = (outs I32:$output); 636} 637 638def TestLocationDstOp : TEST_Op<"loc_dst", [SameOperandsAndResultType]> { 639 let arguments = (ins I32:$input); 640 let results = (outs I32:$output); 641} 642 643//===----------------------------------------------------------------------===// 644// Test Patterns 645//===----------------------------------------------------------------------===// 646 647def OpA : TEST_Op<"op_a"> { 648 let arguments = (ins I32, I32Attr:$attr); 649 let results = (outs I32); 650} 651 652def OpB : TEST_Op<"op_b"> { 653 let arguments = (ins I32, I32Attr:$attr); 654 let results = (outs I32); 655} 656 657// Test named pattern. 658def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>; 659 660// Test with fused location. 661def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>; 662 663// Test added benefit. 664def OpD : TEST_Op<"op_d">, Arguments<(ins I32)>, Results<(outs I32)>; 665def OpE : TEST_Op<"op_e">, Arguments<(ins I32)>, Results<(outs I32)>; 666def OpF : TEST_Op<"op_f">, Arguments<(ins I32)>, Results<(outs I32)>; 667def OpG : TEST_Op<"op_g">, Arguments<(ins I32)>, Results<(outs I32)>; 668// Verify that bumping benefit results in selecting different op. 669def : Pat<(OpD $input), (OpE $input)>; 670def : Pat<(OpD $input), (OpF $input), [], (addBenefit 10)>; 671// Verify that patterns with more source nodes are selected before those with fewer. 672def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>; 673def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>; 674 675// Test patterns for zero-result op. 676def OpH : TEST_Op<"op_h">, Arguments<(ins I32)>, Results<(outs)>; 677def OpI : TEST_Op<"op_i">, Arguments<(ins I32)>, Results<(outs)>; 678def : Pat<(OpH $input), (OpI $input)>; 679 680// Test patterns for zero-input op. 681def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32)>; 682def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32)>; 683def : Pat<(OpJ), (OpK)>; 684 685// Test that natives calls are only called once during rewrites. 686def OpM : TEST_Op<"op_m"> { 687 let arguments = (ins I32, OptionalAttr<I32Attr>:$optional_attr); 688 let results = (outs I32); 689} 690 691def OpN : TEST_Op<"op_n"> { 692 let arguments = (ins I32, I32); 693 let results = (outs I32); 694} 695 696def OpO : TEST_Op<"op_o"> { 697 let arguments = (ins I32); 698 let results = (outs I32); 699} 700 701def OpP : TEST_Op<"op_p"> { 702 let arguments = (ins I32, I32, I32, I32, I32, I32); 703 let results = (outs I32); 704} 705 706// Test same operand name enforces equality condition check. 707def TestEqualArgsPattern : Pat<(OpN $a, $a), (OpO $a)>; 708 709// Test when equality is enforced at different depth. 710def TestNestedOpEqualArgsPattern : 711 Pat<(OpN $b, (OpP $a, $b, $c, $d, $e, $f)), (replaceWithValue $b)>; 712 713// Test multiple equal arguments check enforced. 714def TestMultipleEqualArgsPattern : 715 Pat<(OpP $a, $b, $a, $a, $b, $c), (OpN $c, $b)>; 716 717// Test for memrefs normalization of an op with normalizable memrefs. 718def OpNorm : TEST_Op<"op_norm", [MemRefsNormalizable]> { 719 let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y); 720} 721// Test for memrefs normalization of an op without normalizable memrefs. 722def OpNonNorm : TEST_Op<"op_nonnorm"> { 723 let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y); 724} 725// Test for memrefs normalization of an op that has normalizable memref results. 726def OpNormRet : TEST_Op<"op_norm_ret", [MemRefsNormalizable]> { 727 let arguments = (ins AnyMemRef:$X); 728 let results = (outs AnyMemRef:$Y, AnyMemRef:$Z); 729} 730 731// Test for memrefs normalization of an op with a reference to a function 732// symbol. 733def OpFuncRef : TEST_Op<"op_funcref"> { 734 let summary = "Test op with a reference to a function symbol"; 735 let description = [{ 736 The "test.op_funcref" is a test op with a reference to a function symbol. 737 }]; 738 let builders = [OpBuilder<(ins "FuncOp":$function)>]; 739} 740 741// Pattern add the argument plus a increasing static number hidden in 742// OpMTest function. That value is set into the optional argument. 743// That way, we will know if operations is called once or twice. 744def OpMGetNullAttr : NativeCodeCall<"Attribute()">; 745def OpMAttributeIsNull : Constraint<CPred<"! ($_self)">, "Attribute is null">; 746def OpMVal : NativeCodeCall<"OpMTest($_builder, $0)">; 747def : Pat<(OpM $attr, $optAttr), (OpM $attr, (OpMVal $attr) ), 748 [(OpMAttributeIsNull:$optAttr)]>; 749 750// Test `$_` for ignoring op argument match. 751def TestIgnoreArgMatchSrcOp : TEST_Op<"ignore_arg_match_src"> { 752 let arguments = (ins 753 AnyType:$a, AnyType:$b, AnyType:$c, 754 AnyAttr:$d, AnyAttr:$e, AnyAttr:$f); 755} 756def TestIgnoreArgMatchDstOp : TEST_Op<"ignore_arg_match_dst"> { 757 let arguments = (ins AnyType:$b, AnyAttr:$f); 758} 759def : Pat<(TestIgnoreArgMatchSrcOp $_, $b, I32, I64Attr:$_, $_, $f), 760 (TestIgnoreArgMatchDstOp $b, $f)>; 761 762def OpInterleavedOperandAttribute1 : TEST_Op<"interleaved_operand_attr1"> { 763 let arguments = (ins 764 I32:$input1, 765 I64Attr:$attr1, 766 I32:$input2, 767 I64Attr:$attr2 768 ); 769} 770 771def OpInterleavedOperandAttribute2 : TEST_Op<"interleaved_operand_attr2"> { 772 let arguments = (ins 773 I32:$input1, 774 I64Attr:$attr1, 775 I32:$input2, 776 I64Attr:$attr2 777 ); 778} 779 780def ManyArgsOp : TEST_Op<"many_arguments"> { 781 let arguments = (ins 782 I32:$input1, I32:$input2, I32:$input3, I32:$input4, I32:$input5, 783 I32:$input6, I32:$input7, I32:$input8, I32:$input9, 784 I64Attr:$attr1, I64Attr:$attr2, I64Attr:$attr3, I64Attr:$attr4, 785 I64Attr:$attr5, I64Attr:$attr6, I64Attr:$attr7, I64Attr:$attr8, 786 I64Attr:$attr9 787 ); 788} 789 790// Test that DRR does not blow up when seeing lots of arguments. 791def : Pat<(ManyArgsOp 792 $input1, $input2, $input3, $input4, $input5, 793 $input6, $input7, $input8, $input9, 794 ConstantAttr<I64Attr, "42">, 795 $attr2, $attr3, $attr4, $attr5, $attr6, 796 $attr7, $attr8, $attr9), 797 (ManyArgsOp 798 $input1, $input2, $input3, $input4, $input5, 799 $input6, $input7, $input8, $input9, 800 ConstantAttr<I64Attr, "24">, 801 $attr2, $attr3, $attr4, $attr5, $attr6, 802 $attr7, $attr8, $attr9)>; 803 804// Test that we can capture and reference interleaved operands and attributes. 805def : Pat<(OpInterleavedOperandAttribute1 $input1, $attr1, $input2, $attr2), 806 (OpInterleavedOperandAttribute2 $input1, $attr1, $input2, $attr2)>; 807 808// Test NativeCodeCall. 809def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> { 810 let arguments = (ins 811 I32:$input1, I32:$input2, 812 BoolAttr:$choice, 813 I64Attr:$attr1, I64Attr:$attr2 814 ); 815 let results = (outs I32); 816} 817def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> { 818 let arguments = (ins I32:$input, I64ArrayAttr:$attr); 819 let results = (outs I32); 820} 821// Native code call to invoke a C++ function 822def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">; 823// Native code call to invoke a C++ expression 824def CreateArrayAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">; 825// Test that we can use NativeCodeCall to create operand and attribute. 826// This pattern chooses between $input1 and $input2 according to $choice and 827// it combines $attr1 and $attr2 into an array attribute. 828def : Pat<(OpNativeCodeCall1 $input1, $input2, 829 ConstBoolAttrTrue:$choice, $attr1, $attr2), 830 (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice), 831 (CreateArrayAttr $attr1, $attr2))>; 832// Note: the following is just for testing purpose. 833// Should use the replaceWithValue directive instead. 834def UseOpResult: NativeCodeCall<"$0">; 835// Test that we can use NativeCodeCall to create result. 836def : Pat<(OpNativeCodeCall1 $input1, $input2, 837 ConstBoolAttrFalse, $attr1, $attr2), 838 (UseOpResult $input2)>; 839 840def OpNativeCodeCall3 : TEST_Op<"native_code_call3"> { 841 let arguments = (ins I32:$input); 842 let results = (outs I32); 843} 844// Test that NativeCodeCall is not ignored if it is not used to directly 845// replace the matched root op. 846def : Pattern<(OpNativeCodeCall3 $input), 847 [(NativeCodeCall<"createOpI($_builder, $_loc, $0)"> $input), 848 (OpK)]>; 849 850def OpNativeCodeCall4 : TEST_Op<"native_code_call4"> { 851 let arguments = (ins AnyType:$input1); 852 let results = (outs I32:$output1, I32:$output2); 853} 854def OpNativeCodeCall5 : TEST_Op<"native_code_call5"> { 855 let arguments = (ins I32:$input1, I32:$input2); 856 let results = (outs I32:$output1, I32:$output2); 857} 858 859def GetFirstI32Result : NativeCodeCall<"success(getFirstI32Result($_self, $0))">; 860def BindNativeCodeCallResult : NativeCodeCall<"bindNativeCodeCallResult($0)">; 861def : Pat<(OpNativeCodeCall4 (GetFirstI32Result $ret)), 862 (OpNativeCodeCall5 (BindNativeCodeCallResult:$native $ret), $native)>; 863 864// Test AllAttrConstraintsOf. 865def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> { 866 let arguments = (ins I64ArrayAttr:$attr); 867 let results = (outs I32); 868} 869def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> { 870 let arguments = (ins I64ArrayAttr:$attr); 871 let results = (outs I32); 872} 873def Constraint0 : AttrConstraint< 874 CPred<"$_self.cast<ArrayAttr>()[0]." 875 "cast<IntegerAttr>().getInt() == 0">, 876 "[0] == 0">; 877def Constraint1 : AttrConstraint< 878 CPred<"$_self.cast<ArrayAttr>()[1].cast<IntegerAttr>().getInt() == 1">, 879 "[1] == 1">; 880def : Pat<(OpAllAttrConstraint1 881 AllAttrConstraintsOf<[Constraint0, Constraint1]>:$attr), 882 (OpAllAttrConstraint2 $attr)>; 883 884// Op for testing RewritePattern removing op with inner ops. 885def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> { 886 let regions = (region SizedRegion<1>:$region); 887 let hasCanonicalizer = 1; 888} 889 890def TestOpConstant : TEST_Op<"constant", [ConstantLike, NoSideEffect]> { 891 let arguments = (ins AnyAttr:$value); 892 let results = (outs AnyType); 893 let extraClassDeclaration = [{ 894 Attribute getValue() { return (*this)->getAttr("value"); } 895 }]; 896 897 let hasFolder = 1; 898} 899 900def OpR : TEST_Op<"op_r">, Arguments<(ins AnyInteger, AnyInteger)>, Results<(outs AnyInteger)>; 901def OpS : TEST_Op<"op_s">, Arguments<(ins AnyInteger, AnyAttr:$value)>, Results<(outs AnyInteger)>; 902 903def : Pat<(OpR $input1, (ConstantLikeMatcher I32Attr:$input2)), 904 (OpS:$unused $input1, $input2)>; 905 906// Op for testing trivial removal via folding of op with inner ops and no uses. 907def TestOpWithRegionFoldNoSideEffect : TEST_Op< 908 "op_with_region_fold_no_side_effect", [NoSideEffect]> { 909 let regions = (region SizedRegion<1>:$region); 910} 911 912// Op for testing folding of outer op with inner ops. 913def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> { 914 let arguments = (ins I32:$operand); 915 let results = (outs I32); 916 let regions = (region SizedRegion<1>:$region); 917 let hasFolder = 1; 918} 919 920def TestOpWithVariadicResultsAndFolder: TEST_Op<"op_with_variadic_results_and_folder"> { 921 let arguments = (ins Variadic<I32>:$operands); 922 let results = (outs Variadic<I32>); 923 let hasFolder = 1; 924} 925 926def TestCommutativeOp : TEST_Op<"op_commutative", [Commutative]> { 927 let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4); 928 let results = (outs I32); 929} 930 931def TestIdempotentTraitOp 932 : TEST_Op<"op_idempotent_trait", 933 [SameOperandsAndResultType, NoSideEffect, Idempotent]> { 934 let arguments = (ins I32:$op1); 935 let results = (outs I32); 936} 937 938def TestInvolutionTraitNoOperationFolderOp 939 : TEST_Op<"op_involution_trait_no_operation_fold", 940 [SameOperandsAndResultType, NoSideEffect, Involution]> { 941 let arguments = (ins I32:$op1); 942 let results = (outs I32); 943} 944 945def TestInvolutionTraitFailingOperationFolderOp 946 : TEST_Op<"op_involution_trait_failing_operation_fold", 947 [SameOperandsAndResultType, NoSideEffect, Involution]> { 948 let arguments = (ins I32:$op1); 949 let results = (outs I32); 950 let hasFolder = 1; 951} 952 953def TestInvolutionTraitSuccesfulOperationFolderOp 954 : TEST_Op<"op_involution_trait_succesful_operation_fold", 955 [SameOperandsAndResultType, NoSideEffect, Involution]> { 956 let arguments = (ins I32:$op1); 957 let results = (outs I32); 958 let hasFolder = 1; 959} 960 961def TestOpInPlaceFoldAnchor : TEST_Op<"op_in_place_fold_anchor"> { 962 let arguments = (ins I32); 963 let results = (outs I32); 964} 965 966def TestOpInPlaceFold : TEST_Op<"op_in_place_fold"> { 967 let arguments = (ins I32:$op, I32Attr:$attr); 968 let results = (outs I32); 969 let hasFolder = 1; 970} 971 972// An op that always fold itself. 973def TestPassthroughFold : TEST_Op<"passthrough_fold"> { 974 let arguments = (ins AnyType:$op); 975 let results = (outs AnyType); 976 let hasFolder = 1; 977} 978 979def TestDialectCanonicalizerOp : TEST_Op<"dialect_canonicalizable"> { 980 let arguments = (ins); 981 let results = (outs I32); 982} 983 984//===----------------------------------------------------------------------===// 985// Test Patterns (Symbol Binding) 986 987// Test symbol binding. 988def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> { 989 let arguments = (ins I32:$operand, I64Attr:$attr); 990 let results = (outs I32); 991} 992def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> { 993 let arguments = (ins I32:$operand); 994 let results = (outs I32); 995} 996def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> { 997 let arguments = (ins I32:$operand); 998 let results = (outs I32); 999 let builders = OpSymbolBindingB.builders; 1000} 1001def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> { 1002 let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr); 1003 let results = (outs I32); 1004} 1005def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">; 1006def : Pattern< 1007 // Bind to source pattern op operand/attribute/result 1008 (OpSymbolBindingA:$res_a $operand, $attr), [ 1009 // Bind to auxiliary op result 1010 (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)), 1011 1012 // Use bound symbols in resultant ops 1013 (OpSymbolBindingD $res_b, $res_c, $attr)], 1014 // Use bound symbols in additional constraints 1015 [(HasOneUse $res_a)]>; 1016 1017def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> { 1018 let arguments = (ins I32:$operand); 1019} 1020 1021// Test that we can bind to an op without results and reference it later. 1022def : Pat<(OpSymbolBindingNoResult:$op $operand), 1023 (NativeCodeCall<"handleNoResultOp($_builder, $0)"> $op)>; 1024 1025//===----------------------------------------------------------------------===// 1026// Test Patterns (Attributes) 1027 1028// Test matching against op attributes. 1029def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> { 1030 let arguments = (ins 1031 I32Attr:$required_attr, 1032 OptionalAttr<I32Attr>:$optional_attr, 1033 DefaultValuedAttr<I32Attr, "42">:$default_valued_attr, 1034 I32Attr:$more_attr 1035 ); 1036 let results = (outs I32); 1037} 1038def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> { 1039 let arguments = OpAttrMatch1.arguments; 1040 let results = (outs I32); 1041} 1042def MoreConstraint : AttrConstraint< 1043 CPred<"$_self.cast<IntegerAttr>().getInt() == 4">, "more constraint">; 1044def : Pat<(OpAttrMatch1 $required, $optional, $default_valued, 1045 MoreConstraint:$more), 1046 (OpAttrMatch2 $required, $optional, $default_valued, $more)>; 1047 1048// Test unit attrs. 1049def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> { 1050 let arguments = (ins UnitAttr:$attr); 1051 let results = (outs I32); 1052} 1053def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> { 1054 let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2); 1055 let results = (outs I32); 1056} 1057def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>; 1058 1059// Test with constant attr. 1060def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>; 1061def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>; 1062 1063// Test string enum attribute in rewrites. 1064def : Pat<(StrEnumAttrOp StrCaseA), (StrEnumAttrOp StrCaseB)>; 1065// Test integer enum attribute in rewrites. 1066def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>; 1067def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>; 1068 1069//===----------------------------------------------------------------------===// 1070// Test Patterns (Multi-result Ops) 1071 1072def MultiResultOpKind1: I64EnumAttrCase<"kind1", 1>; 1073def MultiResultOpKind2: I64EnumAttrCase<"kind2", 2>; 1074def MultiResultOpKind3: I64EnumAttrCase<"kind3", 3>; 1075def MultiResultOpKind4: I64EnumAttrCase<"kind4", 4>; 1076def MultiResultOpKind5: I64EnumAttrCase<"kind5", 5>; 1077def MultiResultOpKind6: I64EnumAttrCase<"kind6", 6>; 1078 1079def MultiResultOpEnum: I64EnumAttr< 1080 "MultiResultOpEnum", "Multi-result op kinds", [ 1081 MultiResultOpKind1, MultiResultOpKind2, MultiResultOpKind3, 1082 MultiResultOpKind4, MultiResultOpKind5, MultiResultOpKind6 1083 ]>; 1084 1085def ThreeResultOp : TEST_Op<"three_result"> { 1086 let arguments = (ins MultiResultOpEnum:$kind); 1087 let results = (outs I32:$result1, F32:$result2, F32:$result3); 1088} 1089 1090def AnotherThreeResultOp : TEST_Op<"another_three_result", [DeclareOpInterfaceMethods<InferTypeOpInterface>]> { 1091 let arguments = (ins MultiResultOpEnum:$kind); 1092 let results = (outs I32:$result1, F32:$result2, F32:$result3); 1093} 1094 1095def TwoResultOp : TEST_Op<"two_result"> { 1096 let arguments = (ins MultiResultOpEnum:$kind); 1097 let results = (outs I32:$result1, F32:$result2); 1098} 1099 1100def AnotherTwoResultOp : TEST_Op<"another_two_result"> { 1101 let arguments = (ins MultiResultOpEnum:$kind); 1102 let results = (outs F32:$result1, F32:$result2); 1103} 1104 1105def OneResultOp1 : TEST_Op<"one_result1"> { 1106 let arguments = (ins MultiResultOpEnum:$kind); 1107 let results = (outs F32:$result1); 1108} 1109 1110def OneResultOp2 : TEST_Op<"one_result2"> { 1111 let arguments = (ins MultiResultOpEnum:$kind); 1112 let results = (outs I32:$result1); 1113} 1114 1115def OneResultOp3 : TEST_Op<"one_result3"> { 1116 let arguments = (ins F32); 1117 let results = (outs I32:$result1); 1118} 1119 1120// Test using multi-result op as a whole 1121def : Pat<(ThreeResultOp MultiResultOpKind1:$kind), 1122 (AnotherThreeResultOp $kind)>; 1123 1124// Test using multi-result op as a whole for partial replacement 1125def : Pattern<(ThreeResultOp MultiResultOpKind2:$kind), 1126 [(TwoResultOp $kind), 1127 (OneResultOp1 $kind)]>; 1128def : Pattern<(ThreeResultOp MultiResultOpKind3:$kind), 1129 [(OneResultOp2 $kind), 1130 (AnotherTwoResultOp $kind)]>; 1131 1132// Test using results separately in a multi-result op 1133def : Pattern<(ThreeResultOp MultiResultOpKind4:$kind), 1134 [(TwoResultOp:$res1__0 $kind), 1135 (OneResultOp1 $kind), 1136 (TwoResultOp:$res2__1 $kind)]>; 1137 1138// Test referencing a single value in the value pack 1139// This rule only matches TwoResultOp if its second result has no use. 1140def : Pattern<(TwoResultOp:$res MultiResultOpKind5:$kind), 1141 [(OneResultOp2 $kind), 1142 (OneResultOp1 $kind)], 1143 [(HasNoUseOf:$res__1)]>; 1144 1145// Test using auxiliary ops for replacing multi-result op 1146def : Pattern< 1147 (ThreeResultOp MultiResultOpKind6:$kind), [ 1148 // Auxiliary op generated to help building the final result but not 1149 // directly used to replace the source op's results. 1150 (TwoResultOp:$interm $kind), 1151 1152 (OneResultOp3 $interm__1), 1153 (AnotherTwoResultOp $kind) 1154 ]>; 1155 1156//===----------------------------------------------------------------------===// 1157// Test Patterns (Variadic Ops) 1158 1159def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> { 1160 let arguments = (ins Variadic<I32>); 1161 let results = (outs Variadic<I32>); 1162} 1163def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> { 1164 let arguments = (ins Variadic<I32>); 1165 let results = (outs Variadic<I32>); 1166} 1167 1168// Rewrite an op with one variadic operand and one variadic result to 1169// another similar op. 1170def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>; 1171 1172def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1", 1173 [SameVariadicOperandSize]> { 1174 let arguments = (ins 1175 Variadic<I32>:$input1, 1176 F32:$input2, 1177 Variadic<I32>:$input3 1178 ); 1179} 1180 1181def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2", 1182 [SameVariadicOperandSize]> { 1183 let arguments = (ins 1184 Variadic<I32>:$input1, 1185 F32:$input2, 1186 Variadic<I32>:$input3 1187 ); 1188} 1189 1190// Rewrite an op with both variadic operands and normal operands. 1191def : Pat<(MixedVOperandOp1 $input1, $input2, $input3), 1192 (MixedVOperandOp2 $input1, $input2, $input3)>; 1193 1194def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> { 1195 let results = (outs 1196 Variadic<I32>:$output1, 1197 F32:$output2, 1198 Variadic<I32>:$output3 1199 ); 1200} 1201 1202def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> { 1203 let results = (outs 1204 Variadic<I32>:$output1, 1205 F32:$output2, 1206 Variadic<I32>:$output3 1207 ); 1208} 1209 1210// Rewrite an op with both variadic results and normal results. 1211// Note that because we are generating the op with a top-level result pattern, 1212// we are able to deduce the correct result types for the generated op using 1213// the information from the matched root op. 1214def : Pat<(MixedVResultOp1), (MixedVResultOp2)>; 1215 1216def OneI32ResultOp : TEST_Op<"one_i32_out"> { 1217 let results = (outs I32); 1218} 1219 1220def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3", 1221 [SameVariadicOperandSize]> { 1222 let arguments = (ins 1223 I32:$input1, 1224 Variadic<I32>:$input2, 1225 Variadic<I32>:$input3, 1226 I32Attr:$count 1227 ); 1228 1229 let results = (outs I32); 1230} 1231 1232def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3", 1233 [SameVariadicResultSize]> { 1234 let arguments = (ins I32Attr:$count); 1235 1236 let results = (outs 1237 I32:$output1, 1238 Variadic<I32>:$output2, 1239 Variadic<I32>:$output3 1240 ); 1241 1242 // We will use this op in a nested result pattern, where we cannot deduce the 1243 // result type. So need to provide a builder not requiring result types. 1244 let builders = [ 1245 OpBuilder<(ins "IntegerAttr":$count), 1246 [{ 1247 auto i32Type = $_builder.getIntegerType(32); 1248 $_state.addTypes(i32Type); // $output1 1249 SmallVector<Type, 4> types(count.getInt(), i32Type); 1250 $_state.addTypes(types); // $output2 1251 $_state.addTypes(types); // $output3 1252 $_state.addAttribute("count", count); 1253 }]> 1254 ]; 1255} 1256 1257// Generates an op with variadic results using nested pattern. 1258def : Pat<(OneI32ResultOp), 1259 (MixedVOperandOp3 1260 (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">), 1261 (replaceWithValue $results__1), 1262 (replaceWithValue $results__2), 1263 ConstantAttr<I32Attr, "2">)>; 1264 1265//===----------------------------------------------------------------------===// 1266// Test Patterns (Location) 1267 1268// Test that we can specify locations for generated ops. 1269def : Pat<(TestLocationSrcOp:$res1 1270 (TestLocationSrcOp:$res2 1271 (TestLocationSrcOp:$res3 $input))), 1272 (TestLocationDstOp 1273 (TestLocationDstOp 1274 (TestLocationDstOp $input, (location $res1)), 1275 (location "named")), 1276 (location "fused", $res2, $res3))>; 1277 1278//===----------------------------------------------------------------------===// 1279// Test Legalization 1280//===----------------------------------------------------------------------===// 1281 1282def Test_LegalizerEnum_Success : StrEnumAttrCase<"Success">; 1283def Test_LegalizerEnum_Failure : StrEnumAttrCase<"Failure">; 1284 1285def Test_LegalizerEnum : StrEnumAttr<"Success", "Failure", 1286 [Test_LegalizerEnum_Success, Test_LegalizerEnum_Failure]>; 1287 1288def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>; 1289def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>; 1290def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>; 1291def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>; 1292def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>; 1293def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>; 1294def LegalOpA : TEST_Op<"legal_op_a">, 1295 Arguments<(ins Test_LegalizerEnum:$status)>, Results<(outs I32)>; 1296def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>; 1297 1298// Check that the conversion infrastructure can properly undo the creation of 1299// operations where an operation was created before its parent, in this case, 1300// in the parent's builder. 1301def IllegalOpTerminator : TEST_Op<"illegal_op_terminator", [Terminator]>; 1302def IllegalOpWithRegion : TEST_Op<"illegal_op_with_region"> { 1303 let skipDefaultBuilders = 1; 1304 let builders = [OpBuilder<(ins), 1305 [{ 1306 Region *bodyRegion = $_state.addRegion(); 1307 OpBuilder::InsertionGuard g($_builder); 1308 Block *body = $_builder.createBlock(bodyRegion); 1309 $_builder.setInsertionPointToEnd(body); 1310 $_builder.create<IllegalOpTerminator>($_state.location); 1311 }]>]; 1312} 1313def IllegalOpWithRegionAnchor : TEST_Op<"illegal_op_with_region_anchor">; 1314 1315// Check that smaller pattern depths are chosen, i.e. prioritize more direct 1316// mappings. 1317def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>; 1318 1319def : Pat<(ILLegalOpA), (ILLegalOpB)>; 1320def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>; 1321 1322// Check that the higher benefit pattern is taken for multiple legalizations 1323// with the same depth. 1324def : Pat<(ILLegalOpC), (ILLegalOpD)>; 1325def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>; 1326 1327def : Pat<(ILLegalOpC), (ILLegalOpE), [], (addBenefit 10)>; 1328def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>; 1329 1330// Check that patterns use the most up-to-date value when being replaced. 1331def TestRewriteOp : TEST_Op<"rewrite">, 1332 Arguments<(ins AnyType)>, Results<(outs AnyType)>; 1333def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>; 1334 1335// Check that patterns can specify bounded recursion when rewriting. 1336def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> { 1337 let arguments = (ins I64Attr:$depth); 1338 let assemblyFormat = "$depth attr-dict"; 1339} 1340 1341// Test legalization pattern: this op will be erase and will also erase the 1342// producer of its operand. 1343def BlackHoleOp : TEST_Op<"blackhole">, 1344 Arguments<(ins AnyType)>; 1345 1346//===----------------------------------------------------------------------===// 1347// Test Type Legalization 1348//===----------------------------------------------------------------------===// 1349 1350def TestRegionBuilderOp : TEST_Op<"region_builder">; 1351def TestReturnOp : TEST_Op<"return", [ReturnLike, Terminator]> { 1352 let arguments = (ins Variadic<AnyType>); 1353 let builders = [OpBuilder<(ins), 1354 [{ build($_builder, $_state, {}); }]> 1355 ]; 1356} 1357def TestCastOp : TEST_Op<"cast">, 1358 Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>; 1359def TestInvalidOp : TEST_Op<"invalid", [Terminator]>, 1360 Arguments<(ins Variadic<AnyType>)>; 1361def TestTypeProducerOp : TEST_Op<"type_producer">, 1362 Results<(outs AnyType)>; 1363def TestAnotherTypeProducerOp : TEST_Op<"another_type_producer">, 1364 Results<(outs AnyType)>; 1365def TestTypeConsumerOp : TEST_Op<"type_consumer">, 1366 Arguments<(ins AnyType)>; 1367def TestValidOp : TEST_Op<"valid", [Terminator]>, 1368 Arguments<(ins Variadic<AnyType>)>; 1369 1370def TestMergeBlocksOp : TEST_Op<"merge_blocks"> { 1371 let summary = "merge_blocks operation"; 1372 let description = [{ 1373 Test op with multiple blocks that are merged with Dialect Conversion" 1374 }]; 1375 1376 let regions = (region AnyRegion:$body); 1377 let results = (outs Variadic<AnyType>:$result); 1378} 1379 1380def TestSignatureConversionUndoOp : TEST_Op<"signature_conversion_undo"> { 1381 let regions = (region AnyRegion); 1382} 1383 1384//===----------------------------------------------------------------------===// 1385// Test parser. 1386//===----------------------------------------------------------------------===// 1387 1388def ParseIntegerLiteralOp : TEST_Op<"parse_integer_literal"> { 1389 let results = (outs Variadic<Index>:$results); 1390 let parser = [{ return ::parse$cppClass(parser, result); }]; 1391 let printer = [{ return ::print(p, *this); }]; 1392} 1393 1394def ParseWrappedKeywordOp : TEST_Op<"parse_wrapped_keyword"> { 1395 let arguments = (ins StrAttr:$keyword); 1396 let parser = [{ return ::parse$cppClass(parser, result); }]; 1397 let printer = [{ return ::print(p, *this); }]; 1398} 1399 1400//===----------------------------------------------------------------------===// 1401// Test region argument list parsing. 1402 1403def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> { 1404 let summary = "isolated region operation"; 1405 let description = [{ 1406 Test op with an isolated region, to test passthrough region arguments. Each 1407 argument is of index type. 1408 }]; 1409 1410 let arguments = (ins Index); 1411 let regions = (region SizedRegion<1>:$region); 1412 let parser = [{ return ::parse$cppClass(parser, result); }]; 1413 let printer = [{ return ::print(p, *this); }]; 1414} 1415 1416def SSACFGRegionOp : TEST_Op<"ssacfg_region", [ 1417 DeclareOpInterfaceMethods<RegionKindInterface>]> { 1418 let summary = "operation with an SSACFG region"; 1419 let description = [{ 1420 Test op that defines an SSACFG region. 1421 }]; 1422 1423 let regions = (region VariadicRegion<AnyRegion>:$regions); 1424 let arguments = (ins Variadic<AnyType>); 1425 let results = (outs Variadic<AnyType>); 1426} 1427 1428def GraphRegionOp : TEST_Op<"graph_region", [ 1429 DeclareOpInterfaceMethods<RegionKindInterface>]> { 1430 let summary = "operation with a graph region"; 1431 let description = [{ 1432 Test op that defines a graph region. 1433 }]; 1434 1435 let regions = (region AnyRegion:$region); 1436 let parser = [{ return ::parse$cppClass(parser, result); }]; 1437 let printer = [{ return ::print(p, *this); }]; 1438} 1439 1440def AffineScopeOp : TEST_Op<"affine_scope", [AffineScope]> { 1441 let summary = "affine scope operation"; 1442 let description = [{ 1443 Test op that defines a new affine scope. 1444 }]; 1445 1446 let regions = (region SizedRegion<1>:$region); 1447 let parser = [{ return ::parse$cppClass(parser, result); }]; 1448 let printer = [{ return ::print(p, *this); }]; 1449} 1450 1451def WrappingRegionOp : TEST_Op<"wrapping_region", 1452 [SingleBlockImplicitTerminator<"TestReturnOp">]> { 1453 let summary = "wrapping region operation"; 1454 let description = [{ 1455 Test op wrapping another op in a region, to test calling 1456 parseGenericOperation from the custom parser. 1457 }]; 1458 1459 let results = (outs Variadic<AnyType>); 1460 let regions = (region SizedRegion<1>:$region); 1461 let parser = [{ return ::parse$cppClass(parser, result); }]; 1462 let printer = [{ return ::print(p, *this); }]; 1463} 1464 1465def PolyForOp : TEST_Op<"polyfor"> 1466{ 1467 let summary = "polyfor operation"; 1468 let description = [{ 1469 Test op with multiple region arguments, each argument of index type. 1470 }]; 1471 1472 let regions = (region SizedRegion<1>:$region); 1473 let parser = [{ return ::parse$cppClass(parser, result); }]; 1474} 1475 1476//===----------------------------------------------------------------------===// 1477// Test OpAsmInterface. 1478 1479def AsmInterfaceOp : TEST_Op<"asm_interface_op"> { 1480 let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results, 1481 AnyType); 1482} 1483 1484def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> { 1485 let results = (outs AnyType); 1486} 1487 1488//===----------------------------------------------------------------------===// 1489// Test Op Asm Format 1490//===----------------------------------------------------------------------===// 1491 1492def FormatLiteralOp : TEST_Op<"format_literal_op"> { 1493 let assemblyFormat = [{ 1494 `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` `` `(` ` ` `)` 1495 `?` `+` `*` `{` `\n` `}` attr-dict 1496 }]; 1497} 1498 1499// Test that we elide attributes that are within the syntax. 1500def FormatAttrOp : TEST_Op<"format_attr_op"> { 1501 let arguments = (ins I64Attr:$attr); 1502 let assemblyFormat = "$attr attr-dict"; 1503} 1504 1505// Test that we elide optional attributes that are within the syntax. 1506def FormatOptAttrAOp : TEST_Op<"format_opt_attr_op_a"> { 1507 let arguments = (ins OptionalAttr<I64Attr>:$opt_attr); 1508 let assemblyFormat = "(`(` $opt_attr^ `)` )? attr-dict"; 1509} 1510def FormatOptAttrBOp : TEST_Op<"format_opt_attr_op_b"> { 1511 let arguments = (ins OptionalAttr<I64Attr>:$opt_attr); 1512 let assemblyFormat = "($opt_attr^)? attr-dict"; 1513} 1514 1515// Test that we format symbol name attributes properly. 1516def FormatSymbolNameAttrOp : TEST_Op<"format_symbol_name_attr_op"> { 1517 let arguments = (ins SymbolNameAttr:$attr); 1518 let assemblyFormat = "$attr attr-dict"; 1519} 1520 1521// Test that we format optional symbol name attributes properly. 1522def FormatOptSymbolNameAttrOp : TEST_Op<"format_opt_symbol_name_attr_op"> { 1523 let arguments = (ins OptionalAttr<SymbolNameAttr>:$opt_attr); 1524 let assemblyFormat = "($opt_attr^)? attr-dict"; 1525} 1526 1527// Test that we elide attributes that are within the syntax. 1528def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> { 1529 let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$opt_attr); 1530 let assemblyFormat = "attr-dict-with-keyword"; 1531} 1532 1533// Test that we don't need to provide types in the format if they are buildable. 1534def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> { 1535 let arguments = (ins I64:$buildable); 1536 let results = (outs I64:$buildable_res); 1537 let assemblyFormat = "$buildable attr-dict"; 1538} 1539 1540// Test various mixings of region formatting. 1541class FormatRegionBase<string suffix, string fmt> 1542 : TEST_Op<"format_region_" # suffix # "_op"> { 1543 let regions = (region AnyRegion:$region); 1544 let assemblyFormat = fmt; 1545} 1546def FormatRegionAOp : FormatRegionBase<"a", [{ 1547 regions attr-dict 1548}]>; 1549def FormatRegionBOp : FormatRegionBase<"b", [{ 1550 $region attr-dict 1551}]>; 1552def FormatRegionCOp : FormatRegionBase<"c", [{ 1553 (`region` $region^)? attr-dict 1554}]>; 1555class FormatVariadicRegionBase<string suffix, string fmt> 1556 : TEST_Op<"format_variadic_region_" # suffix # "_op"> { 1557 let regions = (region VariadicRegion<AnyRegion>:$regions); 1558 let assemblyFormat = fmt; 1559} 1560def FormatVariadicRegionAOp : FormatVariadicRegionBase<"a", [{ 1561 $regions attr-dict 1562}]>; 1563def FormatVariadicRegionBOp : FormatVariadicRegionBase<"b", [{ 1564 ($regions^ `found_regions`)? attr-dict 1565}]>; 1566class FormatRegionImplicitTerminatorBase<string suffix, string fmt> 1567 : TEST_Op<"format_implicit_terminator_region_" # suffix # "_op", 1568 [SingleBlockImplicitTerminator<"TestReturnOp">]> { 1569 let regions = (region AnyRegion:$region); 1570 let assemblyFormat = fmt; 1571} 1572def FormatFormatRegionImplicitTerminatorAOp 1573 : FormatRegionImplicitTerminatorBase<"a", [{ 1574 $region attr-dict 1575}]>; 1576 1577// Test various mixings of result type formatting. 1578class FormatResultBase<string suffix, string fmt> 1579 : TEST_Op<"format_result_" # suffix # "_op"> { 1580 let results = (outs I64:$buildable_res, AnyMemRef:$result); 1581 let assemblyFormat = fmt; 1582} 1583def FormatResultAOp : FormatResultBase<"a", [{ 1584 type($result) attr-dict 1585}]>; 1586def FormatResultBOp : FormatResultBase<"b", [{ 1587 type(results) attr-dict 1588}]>; 1589def FormatResultCOp : FormatResultBase<"c", [{ 1590 functional-type($buildable_res, $result) attr-dict 1591}]>; 1592 1593def FormatVariadicResult : TEST_Op<"format_variadic_result"> { 1594 let results = (outs Variadic<I64>:$result); 1595 let assemblyFormat = [{ `:` type($result) attr-dict}]; 1596} 1597 1598def FormatMultipleVariadicResults : TEST_Op<"format_multiple_variadic_results", 1599 [AttrSizedResultSegments]> { 1600 let results = (outs Variadic<I64>:$result0, Variadic<AnyType>:$result1); 1601 let assemblyFormat = [{ 1602 `:` `(` type($result0) `)` `,` `(` type($result1) `)` attr-dict 1603 }]; 1604} 1605 1606// Test various mixings of operand type formatting. 1607class FormatOperandBase<string suffix, string fmt> 1608 : TEST_Op<"format_operand_" # suffix # "_op"> { 1609 let arguments = (ins I64:$buildable, AnyMemRef:$operand); 1610 let assemblyFormat = fmt; 1611} 1612 1613def FormatOperandAOp : FormatOperandBase<"a", [{ 1614 operands `:` type(operands) attr-dict 1615}]>; 1616def FormatOperandBOp : FormatOperandBase<"b", [{ 1617 operands `:` type($operand) attr-dict 1618}]>; 1619def FormatOperandCOp : FormatOperandBase<"c", [{ 1620 $buildable `,` $operand `:` type(operands) attr-dict 1621}]>; 1622def FormatOperandDOp : FormatOperandBase<"d", [{ 1623 $buildable `,` $operand `:` type($operand) attr-dict 1624}]>; 1625def FormatOperandEOp : FormatOperandBase<"e", [{ 1626 $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict 1627}]>; 1628 1629def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> { 1630 let successors = (successor VariadicSuccessor<AnySuccessor>:$targets); 1631 let assemblyFormat = "$targets attr-dict"; 1632} 1633 1634def FormatVariadicOperand : TEST_Op<"format_variadic_operand"> { 1635 let arguments = (ins Variadic<I64>:$operand); 1636 let assemblyFormat = [{ $operand `:` type($operand) attr-dict}]; 1637} 1638 1639def FormatMultipleVariadicOperands : 1640 TEST_Op<"format_multiple_variadic_operands", [AttrSizedOperandSegments]> { 1641 let arguments = (ins Variadic<I64>:$operand0, Variadic<AnyType>:$operand1); 1642 let assemblyFormat = [{ 1643 ` ` `(` $operand0 `)` `,` `(` $operand1 `:` type($operand1) `)` attr-dict 1644 }]; 1645} 1646 1647// Test various mixings of optional operand and result type formatting. 1648class FormatOptionalOperandResultOpBase<string suffix, string fmt> 1649 : TEST_Op<"format_optional_operand_result_" # suffix # "_op", 1650 [AttrSizedOperandSegments]> { 1651 let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic); 1652 let results = (outs Optional<I64>:$optional_res); 1653 let assemblyFormat = fmt; 1654} 1655 1656def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{ 1657 `(` $optional `:` type($optional) `)` `:` type($optional_res) 1658 (`[` $variadic^ `]`)? attr-dict 1659}]>; 1660 1661def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{ 1662 (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res) 1663 (`[` $variadic^ `]`)? attr-dict 1664}]>; 1665 1666// Test optional result type formatting. 1667class FormatOptionalResultOpBase<string suffix, string fmt> 1668 : TEST_Op<"format_optional_result_" # suffix # "_op", 1669 [AttrSizedResultSegments]> { 1670 let results = (outs Optional<I64>:$optional, Variadic<I64>:$variadic); 1671 let assemblyFormat = fmt; 1672} 1673def FormatOptionalResultAOp : FormatOptionalResultOpBase<"a", [{ 1674 (`:` type($optional)^ `->` type($variadic))? attr-dict 1675}]>; 1676 1677def FormatOptionalResultBOp : FormatOptionalResultOpBase<"b", [{ 1678 (`:` type($optional) `->` type($variadic)^)? attr-dict 1679}]>; 1680 1681def FormatOptionalResultCOp : FormatOptionalResultOpBase<"c", [{ 1682 (`:` functional-type($optional, $variadic)^)? attr-dict 1683}]>; 1684 1685def FormatTwoVariadicOperandsNoBuildableTypeOp 1686 : TEST_Op<"format_two_variadic_operands_no_buildable_type_op", 1687 [AttrSizedOperandSegments]> { 1688 let arguments = (ins Variadic<AnyType>:$a, 1689 Variadic<AnyType>:$b); 1690 let assemblyFormat = [{ 1691 `(` $a `:` type($a) `)` `->` `(` $b `:` type($b) `)` attr-dict 1692 }]; 1693} 1694 1695def FormatInferVariadicTypeFromNonVariadic 1696 : TEST_Op<"format_infer_variadic_type_from_non_variadic", 1697 [SameOperandsAndResultType]> { 1698 let arguments = (ins Variadic<AnyType>:$operands); 1699 let results = (outs AnyType:$result); 1700 let assemblyFormat = "$operands attr-dict `:` type($result)"; 1701} 1702 1703def FormatOptionalUnitAttr : TEST_Op<"format_optional_unit_attribute"> { 1704 let arguments = (ins UnitAttr:$is_optional); 1705 let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict"; 1706} 1707 1708def FormatOptionalUnitAttrNoElide 1709 : TEST_Op<"format_optional_unit_attribute_no_elide"> { 1710 let arguments = (ins UnitAttr:$is_optional); 1711 let assemblyFormat = "($is_optional^)? attr-dict"; 1712} 1713 1714def FormatOptionalEnumAttr : TEST_Op<"format_optional_enum_attr"> { 1715 let arguments = (ins OptionalAttr<SomeI64Enum>:$attr); 1716 let assemblyFormat = "($attr^)? attr-dict"; 1717} 1718 1719def FormatOptionalWithElse : TEST_Op<"format_optional_else"> { 1720 let arguments = (ins UnitAttr:$isFirstBranchPresent); 1721 let assemblyFormat = "(`then` $isFirstBranchPresent^):(`else`)? attr-dict"; 1722} 1723 1724//===----------------------------------------------------------------------===// 1725// Custom Directives 1726 1727def FormatCustomDirectiveOperands 1728 : TEST_Op<"format_custom_directive_operands", [AttrSizedOperandSegments]> { 1729 let arguments = (ins I64:$operand, Optional<I64>:$optOperand, 1730 Variadic<I64>:$varOperands); 1731 let assemblyFormat = [{ 1732 custom<CustomDirectiveOperands>( 1733 $operand, $optOperand, $varOperands 1734 ) 1735 attr-dict 1736 }]; 1737} 1738 1739def FormatCustomDirectiveOperandsAndTypes 1740 : TEST_Op<"format_custom_directive_operands_and_types", 1741 [AttrSizedOperandSegments]> { 1742 let arguments = (ins AnyType:$operand, Optional<AnyType>:$optOperand, 1743 Variadic<AnyType>:$varOperands); 1744 let assemblyFormat = [{ 1745 custom<CustomDirectiveOperandsAndTypes>( 1746 $operand, $optOperand, $varOperands, 1747 type($operand), type($optOperand), type($varOperands) 1748 ) 1749 attr-dict 1750 }]; 1751} 1752 1753def FormatCustomDirectiveRegions : TEST_Op<"format_custom_directive_regions"> { 1754 let regions = (region AnyRegion:$region, VariadicRegion<AnyRegion>:$regions); 1755 let assemblyFormat = [{ 1756 custom<CustomDirectiveRegions>( 1757 $region, $regions 1758 ) 1759 attr-dict 1760 }]; 1761} 1762 1763def FormatCustomDirectiveResults 1764 : TEST_Op<"format_custom_directive_results", [AttrSizedResultSegments]> { 1765 let results = (outs AnyType:$result, Optional<AnyType>:$optResult, 1766 Variadic<AnyType>:$varResults); 1767 let assemblyFormat = [{ 1768 custom<CustomDirectiveResults>( 1769 type($result), type($optResult), type($varResults) 1770 ) 1771 attr-dict 1772 }]; 1773} 1774 1775def FormatCustomDirectiveResultsWithTypeRefs 1776 : TEST_Op<"format_custom_directive_results_with_type_refs", 1777 [AttrSizedResultSegments]> { 1778 let results = (outs AnyType:$result, Optional<AnyType>:$optResult, 1779 Variadic<AnyType>:$varResults); 1780 let assemblyFormat = [{ 1781 custom<CustomDirectiveResults>( 1782 type($result), type($optResult), type($varResults) 1783 ) 1784 custom<CustomDirectiveWithTypeRefs>( 1785 ref(type($result)), ref(type($optResult)), ref(type($varResults)) 1786 ) 1787 attr-dict 1788 }]; 1789} 1790 1791def FormatCustomDirectiveWithOptionalOperandRef 1792 : TEST_Op<"format_custom_directive_with_optional_operand_ref"> { 1793 let arguments = (ins Optional<I64>:$optOperand); 1794 let assemblyFormat = [{ 1795 ($optOperand^)? `:` 1796 custom<CustomDirectiveOptionalOperandRef>(ref($optOperand)) 1797 attr-dict 1798 }]; 1799} 1800 1801def FormatCustomDirectiveSuccessors 1802 : TEST_Op<"format_custom_directive_successors", [Terminator]> { 1803 let successors = (successor AnySuccessor:$successor, 1804 VariadicSuccessor<AnySuccessor>:$successors); 1805 let assemblyFormat = [{ 1806 custom<CustomDirectiveSuccessors>( 1807 $successor, $successors 1808 ) 1809 attr-dict 1810 }]; 1811} 1812 1813def FormatCustomDirectiveAttributes 1814 : TEST_Op<"format_custom_directive_attributes"> { 1815 let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr); 1816 let assemblyFormat = [{ 1817 custom<CustomDirectiveAttributes>( 1818 $attr, $optAttr 1819 ) 1820 attr-dict 1821 }]; 1822} 1823 1824def FormatCustomDirectiveAttrDict 1825 : TEST_Op<"format_custom_directive_attrdict"> { 1826 let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr); 1827 let assemblyFormat = [{ 1828 custom<CustomDirectiveAttrDict>( attr-dict ) 1829 }]; 1830} 1831 1832//===----------------------------------------------------------------------===// 1833// AllTypesMatch type inference 1834 1835def FormatAllTypesMatchVarOp : TEST_Op<"format_all_types_match_var", [ 1836 AllTypesMatch<["value1", "value2", "result"]> 1837 ]> { 1838 let arguments = (ins AnyType:$value1, AnyType:$value2); 1839 let results = (outs AnyType:$result); 1840 let assemblyFormat = "attr-dict $value1 `,` $value2 `:` type($value1)"; 1841} 1842 1843def FormatAllTypesMatchAttrOp : TEST_Op<"format_all_types_match_attr", [ 1844 AllTypesMatch<["value1", "value2", "result"]> 1845 ]> { 1846 let arguments = (ins AnyAttr:$value1, AnyType:$value2); 1847 let results = (outs AnyType:$result); 1848 let assemblyFormat = "attr-dict $value1 `,` $value2"; 1849} 1850 1851//===----------------------------------------------------------------------===// 1852// TypesMatchWith type inference 1853 1854def FormatTypesMatchVarOp : TEST_Op<"format_types_match_var", [ 1855 TypesMatchWith<"result type matches operand", "value", "result", "$_self"> 1856 ]> { 1857 let arguments = (ins AnyType:$value); 1858 let results = (outs AnyType:$result); 1859 let assemblyFormat = "attr-dict $value `:` type($value)"; 1860} 1861 1862def FormatTypesMatchVariadicOp : TEST_Op<"format_types_match_variadic", [ 1863 RangedTypesMatchWith<"result type matches operand", "value", "result", 1864 "llvm::make_range($_self.begin(), $_self.end())"> 1865 ]> { 1866 let arguments = (ins Variadic<AnyType>:$value); 1867 let results = (outs Variadic<AnyType>:$result); 1868 let assemblyFormat = "attr-dict $value `:` type($value)"; 1869} 1870 1871def FormatTypesMatchAttrOp : TEST_Op<"format_types_match_attr", [ 1872 TypesMatchWith<"result type matches constant", "value", "result", "$_self"> 1873 ]> { 1874 let arguments = (ins AnyAttr:$value); 1875 let results = (outs AnyType:$result); 1876 let assemblyFormat = "attr-dict $value"; 1877} 1878 1879//===----------------------------------------------------------------------===// 1880// Test SideEffects 1881//===----------------------------------------------------------------------===// 1882 1883def SideEffectOp : TEST_Op<"side_effect_op", 1884 [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 1885 DeclareOpInterfaceMethods<TestEffectOpInterface>]> { 1886 let results = (outs AnyType:$result); 1887} 1888 1889//===----------------------------------------------------------------------===// 1890// Test CopyOpInterface 1891//===----------------------------------------------------------------------===// 1892 1893def CopyOp : TEST_Op<"copy", [CopyOpInterface]> { 1894 let description = [{ 1895 Represents a copy operation. 1896 }]; 1897 let arguments = (ins Res<AnyRankedOrUnrankedMemRef, "", [MemRead]>:$source, 1898 Res<AnyRankedOrUnrankedMemRef, "", [MemWrite]>:$target); 1899 let assemblyFormat = [{ 1900 `(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)` 1901 attr-dict 1902 }]; 1903 let extraClassDeclaration = [{ 1904 Value getSource() { return source(); } 1905 Value getTarget() { return target(); } 1906 }]; 1907} 1908 1909//===----------------------------------------------------------------------===// 1910// Test Buffer/Tensor 1911//===----------------------------------------------------------------------===// 1912 1913def RegionYieldOp : TEST_Op<"region_yield", 1914 [NoSideEffect, ReturnLike, Terminator]> { 1915 let description = [{ 1916 This operation is used in a region and yields the corresponding type for 1917 that operation. 1918 }]; 1919 let arguments = (ins AnyType:$result); 1920 let assemblyFormat = [{ 1921 $result `:` type($result) attr-dict 1922 }]; 1923 let builders = [OpBuilder<(ins), 1924 [{ build($_builder, $_state, {}); }]> 1925 ]; 1926} 1927 1928class BufferBasedOpBase<string mnemonic, list<OpTrait> traits> 1929 : TEST_Op<mnemonic, traits> { 1930 let description = [{ 1931 A buffer based operation, that uses memRefs as input and output. 1932 }]; 1933 let arguments = (ins AnyRankedOrUnrankedMemRef:$input, 1934 AnyRankedOrUnrankedMemRef:$output); 1935} 1936 1937def BufferBasedOp : BufferBasedOpBase<"buffer_based", []>{ 1938 let assemblyFormat = [{ 1939 `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)` 1940 attr-dict 1941 }]; 1942} 1943 1944def RegionBufferBasedOp : BufferBasedOpBase<"region_buffer_based", 1945 [SingleBlockImplicitTerminator<"RegionYieldOp">]> { 1946 let regions = (region AnyRegion:$region); 1947 let assemblyFormat = [{ 1948 `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)` 1949 $region attr-dict 1950 }]; 1951} 1952 1953def TensorBasedOp : TEST_Op<"tensor_based", []> { 1954 let description = [{ 1955 A tensor based operation, that uses a tensor as an input and results in a 1956 tensor again. 1957 }]; 1958 let arguments = (ins AnyRankedTensor:$input); 1959 let results = (outs AnyRankedTensor:$result); 1960 let assemblyFormat = [{ 1961 `in` `(` $input`:` type($input) `)` `->` type($result) attr-dict 1962 }]; 1963} 1964 1965//===----------------------------------------------------------------------===// 1966// Test RegionBranchOpInterface 1967//===----------------------------------------------------------------------===// 1968 1969def RegionIfYieldOp : TEST_Op<"region_if_yield", 1970 [NoSideEffect, ReturnLike, Terminator]> { 1971 let arguments = (ins Variadic<AnyType>:$results); 1972 let assemblyFormat = [{ 1973 $results `:` type($results) attr-dict 1974 }]; 1975} 1976 1977def RegionIfOp : TEST_Op<"region_if", 1978 [DeclareOpInterfaceMethods<RegionBranchOpInterface>, 1979 SingleBlockImplicitTerminator<"RegionIfYieldOp">, 1980 RecursiveSideEffects]> { 1981 let description =[{ 1982 Represents an abstract if-then-else-join pattern. In this context, the then 1983 and else regions jump to the join region, which finally returns to its 1984 parent op. 1985 }]; 1986 1987 let printer = [{ return ::print(p, *this); }]; 1988 let parser = [{ return ::parseRegionIfOp(parser, result); }]; 1989 let arguments = (ins Variadic<AnyType>); 1990 let results = (outs Variadic<AnyType>:$results); 1991 let regions = (region SizedRegion<1>:$thenRegion, 1992 AnyRegion:$elseRegion, 1993 AnyRegion:$joinRegion); 1994 let extraClassDeclaration = [{ 1995 Block::BlockArgListType getThenArgs() { 1996 return getBody(0)->getArguments(); 1997 } 1998 Block::BlockArgListType getElseArgs() { 1999 return getBody(1)->getArguments(); 2000 } 2001 Block::BlockArgListType getJoinArgs() { 2002 return getBody(2)->getArguments(); 2003 } 2004 OperandRange getSuccessorEntryOperands(unsigned index); 2005 }]; 2006} 2007 2008//===----------------------------------------------------------------------===// 2009// Test TableGen generated build() methods 2010//===----------------------------------------------------------------------===// 2011 2012def TableGenConstant : TEST_Op<"tblgen_constant"> { 2013 let results = (outs AnyType); 2014} 2015 2016// No variadic args or results. 2017def TableGenBuildOp0 : TEST_Op<"tblgen_build_0"> { 2018 let arguments = (ins AnyType:$value); 2019 let results = (outs AnyType:$result); 2020} 2021 2022// Sigle variadic arg and single variadic results. 2023def TableGenBuildOp1 : TEST_Op<"tblgen_build_1"> { 2024 let arguments = (ins Variadic<AnyType>:$inputs); 2025 let results = (outs Variadic<AnyType>:$results); 2026} 2027 2028// Single variadic arg and non-variadic results. 2029def TableGenBuildOp2 : TEST_Op<"tblgen_build_2"> { 2030 let arguments = (ins Variadic<AnyType>:$inputs); 2031 let results = (outs AnyType:$result); 2032} 2033 2034// Single variadic arg and multiple variadic results. 2035def TableGenBuildOp3 : TEST_Op<"tblgen_build_3", [SameVariadicResultSize]> { 2036 let arguments = (ins Variadic<AnyType>:$inputs); 2037 let results = (outs Variadic<AnyType>:$resultA, Variadic<AnyType>:$resultB); 2038} 2039 2040// Single variadic arg, non variadic results, with SameOperandsAndResultType. 2041// Tests suppression of ambiguous build methods for operations with 2042// SameOperandsAndResultType trait. 2043def TableGenBuildOp4 : TEST_Op<"tblgen_build_4", [SameOperandsAndResultType]> { 2044 let arguments = (ins Variadic<AnyType>:$inputs); 2045 let results = (outs AnyType:$result); 2046} 2047 2048// Single variadic arg with SameOperandsAndResultType and InferTypeOpInterface. 2049// Tests suppression of ambiguous build methods for operations with 2050// SameOperandsAndResultType and InferTypeOpInterface. 2051def TableGenBuildOp5 : TEST_Op<"tblgen_build_5", 2052 [SameOperandsAndResultType, InferTypeOpInterface]> { 2053 let arguments = (ins Variadic<AnyType>:$inputs); 2054 let results = (outs AnyType:$result); 2055 2056 let extraClassDeclaration = [{ 2057 static LogicalResult inferReturnTypes(MLIRContext *, 2058 Optional<Location> location, ValueRange operands, 2059 DictionaryAttr attributes, RegionRange regions, 2060 SmallVectorImpl<Type> &inferredReturnTypes) { 2061 inferredReturnTypes.assign({operands[0].getType()}); 2062 return success(); 2063 } 2064 }]; 2065} 2066 2067//===----------------------------------------------------------------------===// 2068// Test BufferPlacement 2069//===----------------------------------------------------------------------===// 2070 2071def GetTupleElementOp: TEST_Op<"get_tuple_element"> { 2072 let description = [{ 2073 Test op that returns a specified element of the tuple. 2074 }]; 2075 2076 let arguments = (ins 2077 TupleOf<[AnyType]>, 2078 I32Attr:$index 2079 ); 2080 let results = (outs AnyType); 2081} 2082 2083def MakeTupleOp: TEST_Op<"make_tuple"> { 2084 let description = [{ 2085 Test op that creates a tuple value from a list of values. 2086 }]; 2087 2088 let arguments = (ins 2089 Variadic<AnyType>:$inputs 2090 ); 2091 let results = (outs TupleOf<[AnyType]>); 2092} 2093 2094//===----------------------------------------------------------------------===// 2095// Test Target DataLayout 2096//===----------------------------------------------------------------------===// 2097 2098def OpWithDataLayoutOp : TEST_Op<"op_with_data_layout", 2099 [HasDefaultDLTIDataLayout, DataLayoutOpInterface]> { 2100 let summary = 2101 "An op that uses DataLayout implementation from the Target dialect"; 2102 let regions = (region VariadicRegion<AnyRegion>:$regions); 2103} 2104 2105def DataLayoutQueryOp : TEST_Op<"data_layout_query"> { 2106 let summary = "A token op recognized by data layout query test pass"; 2107 let description = [{ 2108 The data layout query pass pattern-matches this op and attaches to it an 2109 array attribute containing the result of data layout query of the result 2110 type of this op. 2111 }]; 2112 2113 let results = (outs AnyType:$res); 2114} 2115 2116//===----------------------------------------------------------------------===// 2117// Test Reducer Patterns 2118//===----------------------------------------------------------------------===// 2119 2120def OpCrashLong : TEST_Op<"op_crash_long"> { 2121 let arguments = (ins I32, I32, I32); 2122 let results = (outs I32); 2123} 2124 2125def OpCrashShort : TEST_Op<"op_crash_short"> { 2126 let results = (outs I32); 2127} 2128 2129def : Pat<(OpCrashLong $_, $_, $_), (OpCrashShort)>; 2130 2131#endif // TEST_OPS 2132