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