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