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