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