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