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