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