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