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/IR/OpBase.td" 13include "mlir/IR/OpAsmInterface.td" 14include "mlir/Interfaces/SideEffects.td" 15include "mlir/Interfaces/CallInterfaces.td" 16include "mlir/Interfaces/ControlFlowInterfaces.td" 17include "mlir/Interfaces/InferTypeOpInterface.td" 18include "mlir/Interfaces/SideEffects.td" 19 20def Test_Dialect : Dialect { 21 let name = "test"; 22 let cppNamespace = ""; 23 let hasOperationAttrVerify = 1; 24 let hasRegionArgAttrVerify = 1; 25 let hasRegionResultAttrVerify = 1; 26} 27 28class TEST_Op<string mnemonic, list<OpTrait> traits = []> : 29 Op<Test_Dialect, mnemonic, traits>; 30 31//===----------------------------------------------------------------------===// 32// Test Types 33//===----------------------------------------------------------------------===// 34 35def IntTypesOp : TEST_Op<"int_types"> { 36 let results = (outs 37 AnyI16:$any_i16, 38 SI32:$si32, 39 UI64:$ui64, 40 AnyInteger:$any_int 41 ); 42} 43 44def ComplexF64 : Complex<F64>; 45def ComplexOp : TEST_Op<"complex_f64"> { 46 let results = (outs ComplexF64); 47} 48 49def ComplexTensorOp : TEST_Op<"complex_f64_tensor"> { 50 let results = (outs TensorOf<[ComplexF64]>); 51} 52 53def AnyShaped: ShapedContainerType<[AnyType], IsShapedTypePred, "shaped">; 54 55def TupleOp : TEST_Op<"tuple_32_bit"> { 56 let results = (outs TupleOf<[I32, F32]>); 57} 58 59def NestedTupleOp : TEST_Op<"nested_tuple_32_bit"> { 60 let results = (outs NestedTupleOf<[I32, F32]>); 61} 62 63def TakesStaticMemRefOp : TEST_Op<"takes_static_memref"> { 64 let arguments = (ins AnyStaticShapeMemRef:$x); 65} 66 67def RankLessThan2I8F32MemRefOp : TEST_Op<"rank_less_than_2_I8_F32_memref"> { 68 let results = (outs MemRefRankOf<[I8, F32], [0, 1]>); 69} 70 71def NDTensorOfOp : TEST_Op<"nd_tensor_of"> { 72 let arguments = (ins 73 0DTensorOf<[F32]>:$arg0, 74 1DTensorOf<[F32]>:$arg1, 75 2DTensorOf<[I16]>:$arg2, 76 3DTensorOf<[I16]>:$arg3, 77 4DTensorOf<[I16]>:$arg4 78 ); 79} 80 81def RankedTensorOp : TEST_Op<"ranked_tensor_op"> { 82 let arguments = (ins AnyRankedTensor:$input); 83} 84 85def MultiTensorRankOf : TEST_Op<"multi_tensor_rank_of"> { 86 let arguments = (ins 87 TensorRankOf<[I8, I32, F32], [0, 1]>:$arg0 88 ); 89} 90 91//===----------------------------------------------------------------------===// 92// Test Symbols 93//===----------------------------------------------------------------------===// 94 95def SymbolOp : TEST_Op<"symbol", [Symbol]> { 96 let summary = "operation which defines a new symbol"; 97 let arguments = (ins StrAttr:$sym_name, 98 OptionalAttr<StrAttr>:$sym_visibility); 99} 100 101def SymbolScopeOp : TEST_Op<"symbol_scope", 102 [SymbolTable, SingleBlockImplicitTerminator<"TerminatorOp">]> { 103 let summary = "operation which defines a new symbol table"; 104 let regions = (region SizedRegion<1>:$region); 105} 106 107def SymbolTableRegionOp : TEST_Op<"symbol_table_region", [SymbolTable]> { 108 let summary = "operation which defines a new symbol table without a " 109 "restriction on a terminator"; 110 let regions = (region SizedRegion<1>:$region); 111} 112 113//===----------------------------------------------------------------------===// 114// Test Operands 115//===----------------------------------------------------------------------===// 116 117def MixedNormalVariadicOperandOp : TEST_Op< 118 "mixed_normal_variadic_operand", [SameVariadicOperandSize]> { 119 let arguments = (ins 120 Variadic<AnyTensor>:$input1, 121 AnyTensor:$input2, 122 Variadic<AnyTensor>:$input3 123 ); 124} 125 126//===----------------------------------------------------------------------===// 127// Test Results 128//===----------------------------------------------------------------------===// 129 130def MixedNormalVariadicResults : TEST_Op< 131 "mixed_normal_variadic_result", [SameVariadicResultSize]> { 132 let results = (outs 133 Variadic<AnyTensor>:$output1, 134 AnyTensor:$output2, 135 Variadic<AnyTensor>:$output3 136 ); 137} 138 139//===----------------------------------------------------------------------===// 140// Test Attributes 141//===----------------------------------------------------------------------===// 142 143def NonNegIntAttrOp : TEST_Op<"non_negative_int_attr"> { 144 let arguments = (ins 145 Confined<I32Attr, [IntNonNegative]>:$i32attr, 146 Confined<I64Attr, [IntNonNegative]>:$i64attr 147 ); 148} 149 150def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> { 151 let arguments = (ins 152 Confined<I32Attr, [IntPositive]>:$i32attr, 153 Confined<I64Attr, [IntPositive]>:$i64attr 154 ); 155} 156 157def TypeArrayAttrOp : TEST_Op<"type_array_attr"> { 158 let arguments = (ins TypeArrayAttr:$attr); 159} 160def TypeStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> { 161 let arguments = (ins TypedStrAttr<AnyType>:$attr); 162 let assemblyFormat = "$attr attr-dict"; 163} 164 165def StrCaseA: StrEnumAttrCase<"A">; 166def StrCaseB: StrEnumAttrCase<"B">; 167 168def SomeStrEnum: StrEnumAttr< 169 "SomeStrEnum", "", [StrCaseA, StrCaseB]>; 170 171def StrEnumAttrOp : TEST_Op<"str_enum_attr"> { 172 let arguments = (ins SomeStrEnum:$attr); 173 let results = (outs I32:$val); 174} 175 176def I32Case5: I32EnumAttrCase<"case5", 5>; 177def I32Case10: I32EnumAttrCase<"case10", 10>; 178 179def SomeI32Enum: I32EnumAttr< 180 "SomeI32Enum", "", [I32Case5, I32Case10]>; 181 182def I32EnumAttrOp : TEST_Op<"i32_enum_attr"> { 183 let arguments = (ins SomeI32Enum:$attr); 184 let results = (outs I32:$val); 185} 186 187def I64Case5: I64EnumAttrCase<"case5", 5>; 188def I64Case10: I64EnumAttrCase<"case10", 10>; 189 190def SomeI64Enum: I64EnumAttr< 191 "SomeI64Enum", "", [I64Case5, I64Case10]>; 192 193def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> { 194 let arguments = (ins SomeI64Enum:$attr); 195 let results = (outs I32:$val); 196} 197 198 199def IntAttrOp : TEST_Op<"int_attrs"> { 200 let arguments = (ins 201 AnyI32Attr:$any_i32_attr, 202 IndexAttr:$index_attr, 203 UI32Attr:$ui32_attr, 204 SI32Attr:$si32_attr 205 ); 206} 207 208def FloatElementsAttrOp : TEST_Op<"float_elements_attr"> { 209 let arguments = (ins 210 RankedF32ElementsAttr<[2]>:$scalar_f32_attr, 211 RankedF64ElementsAttr<[4, 8]>:$tensor_f64_attr 212 ); 213} 214 215// A pattern that updates dense<[3.0, 4.0]> to dense<[5.0, 6.0]>. 216// This tests both matching and generating float elements attributes. 217def UpdateFloatElementsAttr : Pat< 218 (FloatElementsAttrOp 219 ConstantAttr<RankedF32ElementsAttr<[2]>, "{3.0f, 4.0f}">:$f32attr, 220 $f64attr), 221 (FloatElementsAttrOp 222 ConstantAttr<RankedF32ElementsAttr<[2]>, "{5.0f, 6.0f}">:$f32attr, 223 $f64attr)>; 224 225def IntElementsAttrOp : TEST_Op<"int_elements_attr"> { 226 let arguments = (ins 227 AnyI32ElementsAttr:$any_i32_attr, 228 I32ElementsAttr:$i32_attr 229 ); 230} 231 232def RankedIntElementsAttrOp : TEST_Op<"ranked_int_elements_attr"> { 233 let arguments = (ins 234 RankedI32ElementsAttr<[2]>:$vector_i32_attr, 235 RankedI64ElementsAttr<[4, 8]>:$matrix_i64_attr 236 ); 237} 238 239//===----------------------------------------------------------------------===// 240// Test Attribute Constraints 241//===----------------------------------------------------------------------===// 242 243def SymbolRefOp : TEST_Op<"symbol_ref_attr"> { 244 let arguments = (ins 245 Confined<FlatSymbolRefAttr, [ReferToOp<"FuncOp">]>:$symbol 246 ); 247} 248 249//===----------------------------------------------------------------------===// 250// Test Regions 251//===----------------------------------------------------------------------===// 252 253def OneRegionOp : TEST_Op<"one_region_op", []> { 254 let regions = (region AnyRegion); 255} 256 257def TwoRegionOp : TEST_Op<"two_region_op", []> { 258 let regions = (region AnyRegion, AnyRegion); 259} 260 261def SizedRegionOp : TEST_Op<"sized_region_op", []> { 262 let regions = (region SizedRegion<2>:$my_region, SizedRegion<1>); 263} 264 265//===----------------------------------------------------------------------===// 266// Test Call Interfaces 267//===----------------------------------------------------------------------===// 268 269def ConversionCallOp : TEST_Op<"conversion_call_op", 270 [CallOpInterface]> { 271 let arguments = (ins Variadic<AnyType>:$inputs, SymbolRefAttr:$callee); 272 let results = (outs Variadic<AnyType>); 273 274 let extraClassDeclaration = [{ 275 /// Get the argument operands to the called function. 276 operand_range getArgOperands() { return inputs(); } 277 278 /// Return the callee of this operation. 279 CallInterfaceCallable getCallableForCallee() { 280 return getAttrOfType<SymbolRefAttr>("callee"); 281 } 282 }]; 283} 284 285def FunctionalRegionOp : TEST_Op<"functional_region_op", 286 [CallableOpInterface]> { 287 let regions = (region AnyRegion:$body); 288 let results = (outs FunctionType); 289 290 let extraClassDeclaration = [{ 291 Region *getCallableRegion() { return &body(); } 292 ArrayRef<Type> getCallableResults() { 293 return getType().cast<FunctionType>().getResults(); 294 } 295 }]; 296} 297 298//===----------------------------------------------------------------------===// 299// Test Traits 300//===----------------------------------------------------------------------===// 301 302def SameOperandElementTypeOp : TEST_Op<"same_operand_element_type", 303 [SameOperandsElementType]> { 304 let arguments = (ins AnyType, AnyType); 305 let results = (outs AnyType); 306} 307 308def SameOperandAndResultElementTypeOp : TEST_Op<"same_operand_and_result_element_type", 309 [SameOperandsAndResultElementType]> { 310 let arguments = (ins Variadic<AnyType>); 311 let results = (outs Variadic<AnyType>); 312} 313 314def SameOperandShapeOp : TEST_Op<"same_operand_shape", [SameOperandsShape]> { 315 let arguments = (ins Variadic<AnyShaped>); 316} 317 318def SameOperandAndResultShapeOp : TEST_Op<"same_operand_and_result_shape", 319 [SameOperandsAndResultShape]> { 320 let arguments = (ins Variadic<AnyShaped>); 321 let results = (outs Variadic<AnyShaped>); 322} 323 324def SameOperandAndResultTypeOp : TEST_Op<"same_operand_and_result_type", 325 [SameOperandsAndResultType]> { 326 let arguments = (ins Variadic<AnyType>); 327 let results = (outs Variadic<AnyType>); 328} 329 330def ArgAndResHaveFixedElementTypesOp : 331 TEST_Op<"arg_and_res_have_fixed_element_types", 332 [PredOpTrait<"fixed type combination", 333 And<[ElementTypeIsPred<"x", I32>, 334 ElementTypeIsPred<"y", F32>]>>, 335 ElementTypeIs<"res", I16>]> { 336 let arguments = (ins 337 AnyShaped:$x, AnyShaped:$y); 338 let results = (outs AnyShaped:$res); 339} 340 341def OperandsHaveSameElementType : TEST_Op<"operands_have_same_element_type", [ 342 AllElementTypesMatch<["x", "y"]>]> { 343 let arguments = (ins AnyType:$x, AnyType:$y); 344} 345 346def OperandZeroAndResultHaveSameElementType : TEST_Op< 347 "operand0_and_result_have_same_element_type", 348 [AllElementTypesMatch<["x", "res"]>]> { 349 let arguments = (ins AnyType:$x, AnyType:$y); 350 let results = (outs AnyType:$res); 351} 352 353def OperandsHaveSameType : 354 TEST_Op<"operands_have_same_type", [AllTypesMatch<["x", "y"]>]> { 355 let arguments = (ins AnyType:$x, AnyType:$y); 356} 357 358def OperandZeroAndResultHaveSameType : 359 TEST_Op<"operand0_and_result_have_same_type", 360 [AllTypesMatch<["x", "res"]>]> { 361 let arguments = (ins AnyType:$x, AnyType:$y); 362 let results = (outs AnyType:$res); 363} 364 365def OperandsHaveSameRank : 366 TEST_Op<"operands_have_same_rank", [AllRanksMatch<["x", "y"]>]> { 367 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 368} 369 370def OperandZeroAndResultHaveSameRank : 371 TEST_Op<"operand0_and_result_have_same_rank", 372 [AllRanksMatch<["x", "res"]>]> { 373 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 374 let results = (outs AnyShaped:$res); 375} 376 377def OperandZeroAndResultHaveSameShape : 378 TEST_Op<"operand0_and_result_have_same_shape", 379 [AllShapesMatch<["x", "res"]>]> { 380 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 381 let results = (outs AnyShaped:$res); 382} 383 384def OperandZeroAndResultHaveSameElementCount : 385 TEST_Op<"operand0_and_result_have_same_element_count", 386 [AllElementCountsMatch<["x", "res"]>]> { 387 let arguments = (ins AnyShaped:$x, AnyShaped:$y); 388 let results = (outs AnyShaped:$res); 389} 390 391def FourEqualsFive : 392 TEST_Op<"four_equals_five", [AllMatch<["5", "4"], "4 equals 5">]>; 393 394def OperandRankEqualsResultSize : 395 TEST_Op<"operand_rank_equals_result_size", 396 [AllMatch<[Rank<"operand">.result, ElementCount<"result">.result], 397 "operand rank equals result size">]> { 398 let arguments = (ins AnyShaped:$operand); 399 let results = (outs AnyShaped:$result); 400} 401 402def IfFirstOperandIsNoneThenSoIsSecond : 403 TEST_Op<"if_first_operand_is_none_then_so_is_second", [PredOpTrait< 404 "has either both none type operands or first is not none", 405 Or<[ 406 And<[TypeIsPred<"x", NoneType>, TypeIsPred<"y", NoneType>]>, 407 Neg<TypeIsPred<"x", NoneType>>]>>]> { 408 let arguments = (ins AnyType:$x, AnyType:$y); 409} 410 411def BroadcastableOp : TEST_Op<"broadcastable", [ResultsBroadcastableShape]> { 412 let arguments = (ins Variadic<AnyTensor>); 413 let results = (outs AnyTensor); 414} 415 416// There the "HasParent" trait. 417def ParentOp : TEST_Op<"parent">; 418def ChildOp : TEST_Op<"child", [HasParent<"ParentOp">]>; 419 420 421def TerminatorOp : TEST_Op<"finish", [Terminator]>; 422def SingleBlockImplicitTerminatorOp : TEST_Op<"SingleBlockImplicitTerminator", 423 [SingleBlockImplicitTerminator<"TerminatorOp">]> { 424 let regions = (region SizedRegion<1>:$region); 425} 426 427def I32ElementsAttrOp : TEST_Op<"i32ElementsAttr"> { 428 let arguments = (ins I32ElementsAttr:$attr); 429} 430 431def OpWithInferTypeInterfaceOp : TEST_Op<"op_with_infer_type_if", [ 432 DeclareOpInterfaceMethods<InferTypeOpInterface>]> { 433 let arguments = (ins AnyTensor, AnyTensor); 434 let results = (outs AnyTensor); 435} 436 437def InferTensorType : NativeOpTrait<"InferTensorType">; 438def OpWithShapedTypeInferTypeInterfaceOp : TEST_Op<"op_with_shaped_type_infer_type_if", 439 [ 440 // Op implements infer type op interface. 441 InferTypeOpInterface, 442 // The op will have methods implementing the ShapedType type infer interface. 443 DeclareOpInterfaceMethods<InferShapedTypeOpInterface>, 444 // The op produces tensors and will use the ShapedType type infer interface 445 // along with knowledge that it is producing Tensors to infer shape. 446 InferTensorType 447 ]> { 448 let arguments = (ins AnyTensor, AnyTensor); 449 let results = (outs AnyTensor); 450 451 let extraClassDeclaration = [{ 452 LogicalResult reifyReturnTypeShapes(OpBuilder &builder, 453 SmallVectorImpl<Value> &shapes); 454 }]; 455} 456 457def IsNotScalar : Constraint<CPred<"$0.getType().getRank() != 0">>; 458 459def UpdateAttr : Pat<(I32ElementsAttrOp $attr), 460 (I32ElementsAttrOp ConstantAttr<I32ElementsAttr, "0">), 461 [(IsNotScalar $attr)]>; 462 463def TestBranchOp : TEST_Op<"br", 464 [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator]> { 465 let arguments = (ins Variadic<AnyType>:$targetOperands); 466 let successors = (successor AnySuccessor:$target); 467} 468 469def AttrSizedOperandOp : TEST_Op<"attr_sized_operands", 470 [AttrSizedOperandSegments]> { 471 let arguments = (ins 472 Variadic<I32>:$a, 473 Variadic<I32>:$b, 474 I32:$c, 475 Variadic<I32>:$d, 476 I32ElementsAttr:$operand_segment_sizes 477 ); 478} 479 480def AttrSizedResultOp : TEST_Op<"attr_sized_results", 481 [AttrSizedResultSegments]> { 482 let arguments = (ins 483 I32ElementsAttr:$result_segment_sizes 484 ); 485 let results = (outs 486 Variadic<I32>:$a, 487 Variadic<I32>:$b, 488 I32:$c, 489 Variadic<I32>:$d 490 ); 491} 492 493// This is used to test encoding of a string attribute into an SSA name of a 494// pretty printed value name. 495def StringAttrPrettyNameOp 496 : TEST_Op<"string_attr_pretty_name", 497 [DeclareOpInterfaceMethods<OpAsmOpInterface>]> { 498 let arguments = (ins StrArrayAttr:$names); 499 let results = (outs Variadic<I32>:$r); 500 501 let printer = [{ return ::print(p, *this); }]; 502 let parser = [{ return ::parse$cppClass(parser, result); }]; 503} 504 505//===----------------------------------------------------------------------===// 506// Test Locations 507//===----------------------------------------------------------------------===// 508 509def TestLocationSrcOp : TEST_Op<"loc_src"> { 510 let arguments = (ins I32:$input); 511 let results = (outs I32:$output); 512} 513 514def TestLocationDstOp : TEST_Op<"loc_dst", [SameOperandsAndResultType]> { 515 let arguments = (ins I32:$input); 516 let results = (outs I32:$output); 517} 518 519//===----------------------------------------------------------------------===// 520// Test Patterns 521//===----------------------------------------------------------------------===// 522 523def OpA : TEST_Op<"op_a"> { 524 let arguments = (ins I32, I32Attr:$attr); 525 let results = (outs I32); 526} 527 528def OpB : TEST_Op<"op_b"> { 529 let arguments = (ins I32, I32Attr:$attr); 530 let results = (outs I32); 531} 532 533// Test named pattern. 534def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>; 535 536// Test with fused location. 537def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>; 538 539// Test added benefit. 540def OpD : TEST_Op<"op_d">, Arguments<(ins I32)>, Results<(outs I32)>; 541def OpE : TEST_Op<"op_e">, Arguments<(ins I32)>, Results<(outs I32)>; 542def OpF : TEST_Op<"op_f">, Arguments<(ins I32)>, Results<(outs I32)>; 543def OpG : TEST_Op<"op_g">, Arguments<(ins I32)>, Results<(outs I32)>; 544// Verify that bumping benefit results in selecting different op. 545def : Pat<(OpD $input), (OpE $input)>; 546def : Pat<(OpD $input), (OpF $input), [], (addBenefit 10)>; 547// Verify that patterns with more source nodes are selected before those with fewer. 548def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>; 549def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>; 550 551// Test patterns for zero-result op. 552def OpH : TEST_Op<"op_h">, Arguments<(ins I32)>, Results<(outs)>; 553def OpI : TEST_Op<"op_i">, Arguments<(ins I32)>, Results<(outs)>; 554def : Pat<(OpH $input), (OpI $input)>; 555 556// Test patterns for zero-input op. 557def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32)>; 558def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32)>; 559def : Pat<(OpJ), (OpK)>; 560 561// Test `$_` for ignoring op argument match. 562def TestIgnoreArgMatchSrcOp : TEST_Op<"ignore_arg_match_src"> { 563 let arguments = (ins 564 AnyType:$a, AnyType:$b, AnyType:$c, 565 AnyAttr:$d, AnyAttr:$e, AnyAttr:$f); 566} 567def TestIgnoreArgMatchDstOp : TEST_Op<"ignore_arg_match_dst"> { 568 let arguments = (ins AnyType:$b, AnyAttr:$f); 569} 570def : Pat<(TestIgnoreArgMatchSrcOp $_, $b, I32, I64Attr:$_, $_, $f), 571 (TestIgnoreArgMatchDstOp $b, $f)>; 572 573def OpInterleavedOperandAttribute1 : TEST_Op<"interleaved_operand_attr1"> { 574 let arguments = (ins 575 I32:$input1, 576 I64Attr:$attr1, 577 I32:$input2, 578 I64Attr:$attr2 579 ); 580} 581 582def OpInterleavedOperandAttribute2 : TEST_Op<"interleaved_operand_attr2"> { 583 let arguments = (ins 584 I32:$input1, 585 I64Attr:$attr1, 586 I32:$input2, 587 I64Attr:$attr2 588 ); 589} 590 591def ManyArgsOp : TEST_Op<"many_arguments"> { 592 let arguments = (ins 593 I32:$input1, I32:$input2, I32:$input3, I32:$input4, I32:$input5, 594 I32:$input6, I32:$input7, I32:$input8, I32:$input9, 595 I64Attr:$attr1, I64Attr:$attr2, I64Attr:$attr3, I64Attr:$attr4, 596 I64Attr:$attr5, I64Attr:$attr6, I64Attr:$attr7, I64Attr:$attr8, 597 I64Attr:$attr9 598 ); 599} 600 601// Test that DRR does not blow up when seeing lots of arguments. 602def : Pat<(ManyArgsOp 603 $input1, $input2, $input3, $input4, $input5, 604 $input6, $input7, $input8, $input9, 605 ConstantAttr<I64Attr, "42">, 606 $attr2, $attr3, $attr4, $attr5, $attr6, 607 $attr7, $attr8, $attr9), 608 (ManyArgsOp 609 $input1, $input2, $input3, $input4, $input5, 610 $input6, $input7, $input8, $input9, 611 ConstantAttr<I64Attr, "24">, 612 $attr2, $attr3, $attr4, $attr5, $attr6, 613 $attr7, $attr8, $attr9)>; 614 615// Test that we can capture and reference interleaved operands and attributes. 616def : Pat<(OpInterleavedOperandAttribute1 $input1, $attr1, $input2, $attr2), 617 (OpInterleavedOperandAttribute2 $input1, $attr1, $input2, $attr2)>; 618 619// Test NativeCodeCall. 620def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> { 621 let arguments = (ins 622 I32:$input1, I32:$input2, 623 BoolAttr:$choice, 624 I64Attr:$attr1, I64Attr:$attr2 625 ); 626 let results = (outs I32); 627} 628def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> { 629 let arguments = (ins I32:$input, I64ArrayAttr:$attr); 630 let results = (outs I32); 631} 632// Native code call to invoke a C++ function 633def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">; 634// Native code call to invoke a C++ expression 635def CreateArrayAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">; 636// Test that we can use NativeCodeCall to create operand and attribute. 637// This pattern chooses between $input1 and $input2 according to $choice and 638// it combines $attr1 and $attr2 into an array attribute. 639def : Pat<(OpNativeCodeCall1 $input1, $input2, 640 ConstBoolAttrTrue:$choice, $attr1, $attr2), 641 (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice), 642 (CreateArrayAttr $attr1, $attr2))>; 643// Note: the following is just for testing purpose. 644// Should use the replaceWithValue directive instead. 645def UseOpResult: NativeCodeCall<"$0">; 646// Test that we can use NativeCodeCall to create result. 647def : Pat<(OpNativeCodeCall1 $input1, $input2, 648 ConstBoolAttrFalse, $attr1, $attr2), 649 (UseOpResult $input2)>; 650 651def OpNativeCodeCall3 : TEST_Op<"native_code_call3"> { 652 let arguments = (ins I32:$input); 653 let results = (outs I32); 654} 655// Test that NativeCodeCall is not ignored if it is not used to directly 656// replace the matched root op. 657def : Pattern<(OpNativeCodeCall3 $input), 658 [(NativeCodeCall<"createOpI($_builder, $0)"> $input), (OpK)]>; 659 660// Test AllAttrConstraintsOf. 661def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> { 662 let arguments = (ins I64ArrayAttr:$attr); 663 let results = (outs I32); 664} 665def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> { 666 let arguments = (ins I64ArrayAttr:$attr); 667 let results = (outs I32); 668} 669def Constraint0 : AttrConstraint< 670 CPred<"$_self.cast<ArrayAttr>()[0]." 671 "cast<IntegerAttr>().getInt() == 0">, 672 "[0] == 0">; 673def Constraint1 : AttrConstraint< 674 CPred<"$_self.cast<ArrayAttr>()[1].cast<IntegerAttr>().getInt() == 1">, 675 "[1] == 1">; 676def : Pat<(OpAllAttrConstraint1 677 AllAttrConstraintsOf<[Constraint0, Constraint1]>:$attr), 678 (OpAllAttrConstraint2 $attr)>; 679 680// Op for testing RewritePattern removing op with inner ops. 681def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> { 682 let regions = (region SizedRegion<1>:$region); 683 let hasCanonicalizer = 1; 684} 685 686// Op for testing trivial removal via folding of op with inner ops and no uses. 687def TestOpWithRegionFoldNoSideEffect : TEST_Op< 688 "op_with_region_fold_no_side_effect", [NoSideEffect]> { 689 let regions = (region SizedRegion<1>:$region); 690} 691 692// Op for testing folding of outer op with inner ops. 693def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> { 694 let arguments = (ins I32:$operand); 695 let results = (outs I32); 696 let regions = (region SizedRegion<1>:$region); 697 let hasFolder = 1; 698} 699 700def TestOpWithVariadicResultsAndFolder: TEST_Op<"op_with_variadic_results_and_folder"> { 701 let arguments = (ins Variadic<I32>:$operands); 702 let results = (outs Variadic<I32>); 703 let hasFolder = 1; 704} 705 706def TestCommutativeOp : TEST_Op<"op_commutative", [Commutative]> { 707 let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4); 708 let results = (outs I32); 709} 710 711//===----------------------------------------------------------------------===// 712// Test Patterns (Symbol Binding) 713 714// Test symbol binding. 715def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> { 716 let arguments = (ins I32:$operand, I64Attr:$attr); 717 let results = (outs I32); 718} 719def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> { 720 let arguments = (ins I32:$operand); 721 let results = (outs I32); 722 723 let builders = [ 724 OpBuilder< 725 "Builder *builder, OperationState &state, Value operand", 726 [{ 727 state.types.assign({builder->getIntegerType(32)}); 728 state.addOperands({operand}); 729 }]> 730 ]; 731} 732def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> { 733 let arguments = (ins I32:$operand); 734 let results = (outs I32); 735 let builders = OpSymbolBindingB.builders; 736} 737def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> { 738 let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr); 739 let results = (outs I32); 740} 741def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">; 742def : Pattern< 743 // Bind to source pattern op operand/attribute/result 744 (OpSymbolBindingA:$res_a $operand, $attr), [ 745 // Bind to auxiliary op result 746 (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)), 747 748 // Use bound symbols in resultant ops 749 (OpSymbolBindingD $res_b, $res_c, $attr)], 750 // Use bound symbols in additional constraints 751 [(HasOneUse $res_a)]>; 752 753def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> { 754 let arguments = (ins I32:$operand); 755} 756 757// Test that we can bind to an op without results and reference it later. 758def : Pat<(OpSymbolBindingNoResult:$op $operand), 759 (NativeCodeCall<"handleNoResultOp($_builder, $0)"> $op)>; 760 761//===----------------------------------------------------------------------===// 762// Test Patterns (Attributes) 763 764// Test matching against op attributes. 765def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> { 766 let arguments = (ins 767 I32Attr:$required_attr, 768 OptionalAttr<I32Attr>:$optional_attr, 769 DefaultValuedAttr<I32Attr, "42">:$default_valued_attr, 770 I32Attr:$more_attr 771 ); 772 let results = (outs I32); 773} 774def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> { 775 let arguments = OpAttrMatch1.arguments; 776 let results = (outs I32); 777} 778def MoreConstraint : AttrConstraint< 779 CPred<"$_self.cast<IntegerAttr>().getInt() == 4">, "more constraint">; 780def : Pat<(OpAttrMatch1 $required, $optional, $default_valued, 781 MoreConstraint:$more), 782 (OpAttrMatch2 $required, $optional, $default_valued, $more)>; 783 784// Test unit attrs. 785def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> { 786 let arguments = (ins UnitAttr:$attr); 787 let results = (outs I32); 788} 789def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> { 790 let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2); 791 let results = (outs I32); 792} 793def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>; 794 795// Test with constant attr. 796def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>; 797def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>; 798 799// Test string enum attribute in rewrites. 800def : Pat<(StrEnumAttrOp StrCaseA), (StrEnumAttrOp StrCaseB)>; 801// Test integer enum attribute in rewrites. 802def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>; 803def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>; 804 805//===----------------------------------------------------------------------===// 806// Test Patterns (Multi-result Ops) 807 808def MultiResultOpKind1: I64EnumAttrCase<"kind1", 1>; 809def MultiResultOpKind2: I64EnumAttrCase<"kind2", 2>; 810def MultiResultOpKind3: I64EnumAttrCase<"kind3", 3>; 811def MultiResultOpKind4: I64EnumAttrCase<"kind4", 4>; 812def MultiResultOpKind5: I64EnumAttrCase<"kind5", 5>; 813def MultiResultOpKind6: I64EnumAttrCase<"kind6", 6>; 814 815def MultiResultOpEnum: I64EnumAttr< 816 "MultiResultOpEnum", "Multi-result op kinds", [ 817 MultiResultOpKind1, MultiResultOpKind2, MultiResultOpKind3, 818 MultiResultOpKind4, MultiResultOpKind5, MultiResultOpKind6 819 ]>; 820 821def ThreeResultOp : TEST_Op<"three_result"> { 822 let arguments = (ins MultiResultOpEnum:$kind); 823 let results = (outs I32:$result1, F32:$result2, F32:$result3); 824} 825 826def AnotherThreeResultOp : TEST_Op<"another_three_result"> { 827 let arguments = (ins MultiResultOpEnum:$kind); 828 let results = (outs I32:$result1, F32:$result2, F32:$result3); 829} 830 831def TwoResultOp : TEST_Op<"two_result"> { 832 let arguments = (ins MultiResultOpEnum:$kind); 833 let results = (outs I32:$result1, F32:$result2); 834 835 let builders = [ 836 OpBuilder< 837 "Builder *builder, OperationState &state, IntegerAttr kind", 838 [{ 839 auto i32 = builder->getIntegerType(32); 840 auto f32 = builder->getF32Type(); 841 state.types.assign({i32, f32}); 842 state.addAttribute("kind", kind); 843 }]> 844 ]; 845} 846 847def AnotherTwoResultOp : TEST_Op<"another_two_result"> { 848 let arguments = (ins MultiResultOpEnum:$kind); 849 let results = (outs F32:$result1, F32:$result2); 850} 851 852def OneResultOp1 : TEST_Op<"one_result1"> { 853 let arguments = (ins MultiResultOpEnum:$kind); 854 let results = (outs F32:$result1); 855} 856 857def OneResultOp2 : TEST_Op<"one_result2"> { 858 let arguments = (ins MultiResultOpEnum:$kind); 859 let results = (outs I32:$result1); 860} 861 862def OneResultOp3 : TEST_Op<"one_result3"> { 863 let arguments = (ins F32); 864 let results = (outs I32:$result1); 865} 866 867// Test using multi-result op as a whole 868def : Pat<(ThreeResultOp MultiResultOpKind1), 869 (AnotherThreeResultOp MultiResultOpKind1)>; 870 871// Test using multi-result op as a whole for partial replacement 872def : Pattern<(ThreeResultOp MultiResultOpKind2), 873 [(TwoResultOp MultiResultOpKind2), 874 (OneResultOp1 MultiResultOpKind2)]>; 875def : Pattern<(ThreeResultOp MultiResultOpKind3), 876 [(OneResultOp2 MultiResultOpKind3), 877 (AnotherTwoResultOp MultiResultOpKind3)]>; 878 879// Test using results separately in a multi-result op 880def : Pattern<(ThreeResultOp MultiResultOpKind4), 881 [(TwoResultOp:$res1__0 MultiResultOpKind4), 882 (OneResultOp1 MultiResultOpKind4), 883 (TwoResultOp:$res2__1 MultiResultOpKind4)]>; 884 885// Test referencing a single value in the value pack 886// This rule only matches TwoResultOp if its second result has no use. 887def : Pattern<(TwoResultOp:$res MultiResultOpKind5), 888 [(OneResultOp2 MultiResultOpKind5), 889 (OneResultOp1 MultiResultOpKind5)], 890 [(HasNoUseOf:$res__1)]>; 891 892// Test using auxiliary ops for replacing multi-result op 893def : Pattern< 894 (ThreeResultOp MultiResultOpKind6), [ 895 // Auxiliary op generated to help building the final result but not 896 // directly used to replace the source op's results. 897 (TwoResultOp:$interm MultiResultOpKind6), 898 899 (OneResultOp3 $interm__1), 900 (AnotherTwoResultOp MultiResultOpKind6) 901 ]>; 902 903//===----------------------------------------------------------------------===// 904// Test Patterns (Variadic Ops) 905 906def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> { 907 let arguments = (ins Variadic<I32>); 908 let results = (outs Variadic<I32>); 909} 910def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> { 911 let arguments = (ins Variadic<I32>); 912 let results = (outs Variadic<I32>); 913} 914 915// Rewrite an op with one variadic operand and one variadic result to 916// another similar op. 917def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>; 918 919def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1", 920 [SameVariadicOperandSize]> { 921 let arguments = (ins 922 Variadic<I32>:$input1, 923 F32:$input2, 924 Variadic<I32>:$input3 925 ); 926} 927 928def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2", 929 [SameVariadicOperandSize]> { 930 let arguments = (ins 931 Variadic<I32>:$input1, 932 F32:$input2, 933 Variadic<I32>:$input3 934 ); 935} 936 937// Rewrite an op with both variadic operands and normal operands. 938def : Pat<(MixedVOperandOp1 $input1, $input2, $input3), 939 (MixedVOperandOp2 $input1, $input2, $input3)>; 940 941def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> { 942 let results = (outs 943 Variadic<I32>:$output1, 944 F32:$output2, 945 Variadic<I32>:$output3 946 ); 947} 948 949def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> { 950 let results = (outs 951 Variadic<I32>:$output1, 952 F32:$output2, 953 Variadic<I32>:$output3 954 ); 955} 956 957// Rewrite an op with both variadic results and normal results. 958// Note that because we are generating the op with a top-level result pattern, 959// we are able to deduce the correct result types for the generated op using 960// the information from the matched root op. 961def : Pat<(MixedVResultOp1), (MixedVResultOp2)>; 962 963def OneI32ResultOp : TEST_Op<"one_i32_out"> { 964 let results = (outs I32); 965} 966 967def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3", 968 [SameVariadicOperandSize]> { 969 let arguments = (ins 970 I32:$input1, 971 Variadic<I32>:$input2, 972 Variadic<I32>:$input3, 973 I32Attr:$count 974 ); 975 976 let results = (outs I32); 977} 978 979def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3", 980 [SameVariadicResultSize]> { 981 let arguments = (ins I32Attr:$count); 982 983 let results = (outs 984 I32:$output1, 985 Variadic<I32>:$output2, 986 Variadic<I32>:$output3 987 ); 988 989 // We will use this op in a nested result pattern, where we cannot deduce the 990 // result type. So need to provide a builder not requiring result types. 991 let builders = [ 992 OpBuilder< 993 "Builder *builder, OperationState &state, IntegerAttr count", 994 [{ 995 auto i32Type = builder->getIntegerType(32); 996 state.addTypes(i32Type); // $output1 997 SmallVector<Type, 4> types(count.getInt(), i32Type); 998 state.addTypes(types); // $output2 999 state.addTypes(types); // $output3 1000 state.addAttribute("count", count); 1001 }]> 1002 ]; 1003} 1004 1005// Generates an op with variadic results using nested pattern. 1006def : Pat<(OneI32ResultOp), 1007 (MixedVOperandOp3 1008 (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">), 1009 (replaceWithValue $results__1), 1010 (replaceWithValue $results__2), 1011 ConstantAttr<I32Attr, "2">)>; 1012 1013//===----------------------------------------------------------------------===// 1014// Test Patterns (Location) 1015 1016// Test that we can specify locations for generated ops. 1017def : Pat<(TestLocationSrcOp:$res1 1018 (TestLocationSrcOp:$res2 1019 (TestLocationSrcOp:$res3 $input))), 1020 (TestLocationDstOp 1021 (TestLocationDstOp 1022 (TestLocationDstOp $input, (location $res1)), 1023 (location "named")), 1024 (location "fused", $res2, $res3))>; 1025 1026//===----------------------------------------------------------------------===// 1027// Test Legalization 1028//===----------------------------------------------------------------------===// 1029 1030def Test_LegalizerEnum_Success : StrEnumAttrCase<"Success">; 1031def Test_LegalizerEnum_Failure : StrEnumAttrCase<"Failure">; 1032 1033def Test_LegalizerEnum : StrEnumAttr<"Success", "Failure", 1034 [Test_LegalizerEnum_Success, Test_LegalizerEnum_Failure]>; 1035 1036def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>; 1037def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>; 1038def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>; 1039def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>; 1040def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>; 1041def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>; 1042def LegalOpA : TEST_Op<"legal_op_a">, 1043 Arguments<(ins Test_LegalizerEnum:$status)>, Results<(outs I32)>; 1044def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>; 1045 1046// Check that smaller pattern depths are chosen, i.e. prioritize more direct 1047// mappings. 1048def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>; 1049 1050def : Pat<(ILLegalOpA), (ILLegalOpB)>; 1051def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>; 1052 1053// Check that the higher benefit pattern is taken for multiple legalizations 1054// with the same depth. 1055def : Pat<(ILLegalOpC), (ILLegalOpD)>; 1056def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>; 1057 1058def : Pat<(ILLegalOpC), (ILLegalOpE), [], (addBenefit 10)>; 1059def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>; 1060 1061// Check that patterns use the most up-to-date value when being replaced. 1062def TestRewriteOp : TEST_Op<"rewrite">, 1063 Arguments<(ins AnyType)>, Results<(outs AnyType)>; 1064def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>; 1065 1066// Check that patterns can specify bounded recursion when rewriting. 1067def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> { 1068 let arguments = (ins I64Attr:$depth); 1069 let assemblyFormat = "$depth attr-dict"; 1070} 1071 1072//===----------------------------------------------------------------------===// 1073// Test Type Legalization 1074//===----------------------------------------------------------------------===// 1075 1076def TestRegionBuilderOp : TEST_Op<"region_builder">; 1077def TestReturnOp : TEST_Op<"return", [Terminator]>, 1078 Arguments<(ins Variadic<AnyType>)>; 1079def TestCastOp : TEST_Op<"cast">, 1080 Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>; 1081def TestInvalidOp : TEST_Op<"invalid", [Terminator]>, 1082 Arguments<(ins Variadic<AnyType>)>; 1083def TestTypeProducerOp : TEST_Op<"type_producer">, 1084 Results<(outs AnyType)>; 1085def TestTypeConsumerOp : TEST_Op<"type_consumer">, 1086 Arguments<(ins AnyType)>; 1087def TestValidOp : TEST_Op<"valid", [Terminator]>, 1088 Arguments<(ins Variadic<AnyType>)>; 1089 1090//===----------------------------------------------------------------------===// 1091// Test parser. 1092//===----------------------------------------------------------------------===// 1093 1094def WrappedKeywordOp : TEST_Op<"wrapped_keyword"> { 1095 let arguments = (ins StrAttr:$keyword); 1096 let parser = [{ return ::parse$cppClass(parser, result); }]; 1097 let printer = [{ return ::print(p, *this); }]; 1098} 1099 1100//===----------------------------------------------------------------------===// 1101// Test region argument list parsing. 1102 1103def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> { 1104 let summary = "isolated region operation"; 1105 let description = [{ 1106 Test op with an isolated region, to test passthrough region arguments. Each 1107 argument is of index type. 1108 }]; 1109 1110 let arguments = (ins Index); 1111 let regions = (region SizedRegion<1>:$region); 1112 let parser = [{ return ::parse$cppClass(parser, result); }]; 1113 let printer = [{ return ::print(p, *this); }]; 1114} 1115 1116def WrappingRegionOp : TEST_Op<"wrapping_region", 1117 [SingleBlockImplicitTerminator<"TestReturnOp">]> { 1118 let summary = "wrapping region operation"; 1119 let description = [{ 1120 Test op wrapping another op in a region, to test calling 1121 parseGenericOperation from the custom parser. 1122 }]; 1123 1124 let results = (outs Variadic<AnyType>); 1125 let regions = (region SizedRegion<1>:$region); 1126 let parser = [{ return ::parse$cppClass(parser, result); }]; 1127 let printer = [{ return ::print(p, *this); }]; 1128} 1129 1130def PolyForOp : TEST_Op<"polyfor"> 1131{ 1132 let summary = "polyfor operation"; 1133 let description = [{ 1134 Test op with multiple region arguments, each argument of index type. 1135 }]; 1136 1137 let regions = (region SizedRegion<1>:$region); 1138 let parser = [{ return ::parse$cppClass(parser, result); }]; 1139} 1140 1141//===----------------------------------------------------------------------===// 1142// Test OpAsmInterface. 1143 1144def AsmInterfaceOp : TEST_Op<"asm_interface_op"> { 1145 let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results, 1146 AnyType); 1147} 1148 1149def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> { 1150 let results = (outs AnyType); 1151} 1152 1153//===----------------------------------------------------------------------===// 1154// Test Op Asm Format 1155//===----------------------------------------------------------------------===// 1156 1157def FormatLiteralOp : TEST_Op<"format_literal_op"> { 1158 let assemblyFormat = [{ 1159 `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` attr-dict 1160 }]; 1161} 1162 1163// Test that we elide attributes that are within the syntax. 1164def FormatAttrOp : TEST_Op<"format_attr_op"> { 1165 let arguments = (ins I64Attr:$attr); 1166 let assemblyFormat = "$attr attr-dict"; 1167} 1168 1169// Test that we elide attributes that are within the syntax. 1170def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> { 1171 let arguments = (ins I64Attr:$attr); 1172 let assemblyFormat = "attr-dict-with-keyword"; 1173} 1174 1175// Test that we don't need to provide types in the format if they are buildable. 1176def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> { 1177 let arguments = (ins I64:$buildable); 1178 let results = (outs I64:$buildable_res); 1179 let assemblyFormat = "$buildable attr-dict"; 1180} 1181 1182// Test various mixings of result type formatting. 1183class FormatResultBase<string suffix, string fmt> 1184 : TEST_Op<"format_result_" # suffix # "_op"> { 1185 let results = (outs I64:$buildable_res, AnyMemRef:$result); 1186 let assemblyFormat = fmt; 1187} 1188def FormatResultAOp : FormatResultBase<"a", [{ 1189 type($result) attr-dict 1190}]>; 1191def FormatResultBOp : FormatResultBase<"b", [{ 1192 type(results) attr-dict 1193}]>; 1194def FormatResultCOp : FormatResultBase<"c", [{ 1195 functional-type($buildable_res, $result) attr-dict 1196}]>; 1197 1198// Test various mixings of operand type formatting. 1199class FormatOperandBase<string suffix, string fmt> 1200 : TEST_Op<"format_operand_" # suffix # "_op"> { 1201 let arguments = (ins I64:$buildable, AnyMemRef:$operand); 1202 let assemblyFormat = fmt; 1203} 1204 1205def FormatOperandAOp : FormatOperandBase<"a", [{ 1206 operands `:` type(operands) attr-dict 1207}]>; 1208def FormatOperandBOp : FormatOperandBase<"b", [{ 1209 operands `:` type($operand) attr-dict 1210}]>; 1211def FormatOperandCOp : FormatOperandBase<"c", [{ 1212 $buildable `,` $operand `:` type(operands) attr-dict 1213}]>; 1214def FormatOperandDOp : FormatOperandBase<"d", [{ 1215 $buildable `,` $operand `:` type($operand) attr-dict 1216}]>; 1217def FormatOperandEOp : FormatOperandBase<"e", [{ 1218 $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict 1219}]>; 1220 1221def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> { 1222 let successors = (successor VariadicSuccessor<AnySuccessor>:$targets); 1223 let assemblyFormat = "$targets attr-dict"; 1224} 1225 1226// Test various mixings of optional operand and result type formatting. 1227class FormatOptionalOperandResultOpBase<string suffix, string fmt> 1228 : TEST_Op<"format_optional_operand_result_" # suffix # "_op", 1229 [AttrSizedOperandSegments]> { 1230 let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic); 1231 let results = (outs Optional<I64>:$optional_res); 1232 let assemblyFormat = fmt; 1233} 1234 1235def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{ 1236 `(` $optional `:` type($optional) `)` `:` type($optional_res) 1237 (`[` $variadic^ `]`)? attr-dict 1238}]>; 1239 1240def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{ 1241 (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res) 1242 (`[` $variadic^ `]`)? attr-dict 1243}]>; 1244 1245//===----------------------------------------------------------------------===// 1246// Test SideEffects 1247//===----------------------------------------------------------------------===// 1248 1249def SideEffectOp : TEST_Op<"side_effect_op", 1250 [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { 1251 let results = (outs AnyType:$result); 1252} 1253 1254#endif // TEST_OPS 1255