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