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