github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/test/lib/TestDialect/TestOps.td (about) 1 //===-- TestOps.td - Test dialect operation definitions ----*- tablegen -*-===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 18 #ifdef TEST_OPS 19 #else 20 #define TEST_OPS 21 22 #ifdef OP_BASE 23 #else 24 include "mlir/IR/OpBase.td" 25 #endif // OP_BASE 26 27 def TEST_Dialect : Dialect { 28 let name = "test"; 29 let cppNamespace = ""; 30 } 31 32 class TEST_Op<string mnemonic, list<OpTrait> traits = []> : 33 Op<TEST_Dialect, mnemonic, traits>; 34 35 //===----------------------------------------------------------------------===// 36 // Test Types 37 //===----------------------------------------------------------------------===// 38 39 def AnyVectorOrTensor: AnyTypeOf<[AnyVector, AnyTensor]>; 40 41 def TupleOp : TEST_Op<"tuple_32_bit"> { 42 let results = (outs TupleOf<[I32, F32]>); 43 } 44 45 def NestedTupleOp : TEST_Op<"nested_tuple_32_bit"> { 46 let results = (outs NestedTupleOf<[I32, F32]>); 47 } 48 49 def TakesStaticMemRefOp : TEST_Op<"takes_static_memref"> { 50 let arguments = (ins AnyStaticShapeMemRef:$x); 51 } 52 53 def NDTensorOfOp : TEST_Op<"nd_tensor_of"> { 54 let arguments = (ins 55 0DTensorOf<[F32]>:$arg0, 56 1DTensorOf<[F32]>:$arg1, 57 2DTensorOf<[I16]>:$arg2, 58 3DTensorOf<[I16]>:$arg3, 59 4DTensorOf<[I16]>:$arg4 60 ); 61 } 62 63 def MultiTensorRankOf : TEST_Op<"multi_tensor_rank_of"> { 64 let arguments = (ins 65 TensorRankOf<[I8, I32, F32], [0, 1]>:$arg0 66 ); 67 } 68 69 //===----------------------------------------------------------------------===// 70 // Test Operands 71 //===----------------------------------------------------------------------===// 72 73 def MixedNormalVariadicOperandOp : TEST_Op< 74 "mixed_normal_variadic_operand", [SameVariadicOperandSize]> { 75 let arguments = (ins 76 Variadic<AnyTensor>:$input1, 77 AnyTensor:$input2, 78 Variadic<AnyTensor>:$input3 79 ); 80 } 81 82 //===----------------------------------------------------------------------===// 83 // Test Results 84 //===----------------------------------------------------------------------===// 85 86 def MixedNormalVariadicResults : TEST_Op< 87 "mixed_normal_variadic_result", [SameVariadicResultSize]> { 88 let results = (outs 89 Variadic<AnyTensor>:$output1, 90 AnyTensor:$output2, 91 Variadic<AnyTensor>:$output3 92 ); 93 } 94 95 //===----------------------------------------------------------------------===// 96 // Test Attributes 97 //===----------------------------------------------------------------------===// 98 99 def NonNegIntAttrOp : TEST_Op<"non_negative_int_attr"> { 100 let arguments = (ins 101 NonNegativeI32Attr:$i32attr, 102 NonNegativeI64Attr:$i64attr 103 ); 104 } 105 106 def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> { 107 let arguments = (ins 108 PositiveI32Attr:$i32attr, 109 PositiveI64Attr:$i64attr 110 ); 111 } 112 113 def TypeArrayAttrOp : TEST_Op<"type_array_attr"> { 114 let arguments = (ins TypeArrayAttr:$attr); 115 } 116 def TypeStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> { 117 let arguments = (ins StrAttr:$attr); 118 let printer = [{ *p << getAttr("attr"); }]; 119 let parser = [{ 120 Attribute attr; 121 Type stringType = OpaqueType::get(Identifier::get("foo", 122 result->getContext()), "string", 123 result->getContext()); 124 return parser->parseAttribute(attr, stringType, "attr", result->attributes); 125 }]; 126 } 127 128 def StrCaseA: StrEnumAttrCase<"A">; 129 def StrCaseB: StrEnumAttrCase<"B">; 130 131 def SomeStrEnum: StrEnumAttr< 132 "SomeStrEnum", "", [StrCaseA, StrCaseB]>; 133 134 def StrEnumAttrOp : TEST_Op<"str_enum_attr"> { 135 let arguments = (ins SomeStrEnum:$attr); 136 let results = (outs I32:$val); 137 } 138 139 def I32Case5: I32EnumAttrCase<"case5", 5>; 140 def I32Case10: I32EnumAttrCase<"case10", 10>; 141 142 def SomeI32Enum: I32EnumAttr< 143 "SomeI32Enum", "", [I32Case5, I32Case10]>; 144 145 def I32EnumAttrOp : TEST_Op<"i32_enum_attr"> { 146 let arguments = (ins SomeI32Enum:$attr); 147 let results = (outs I32:$val); 148 } 149 150 def I64Case5: I64EnumAttrCase<"case5", 5>; 151 def I64Case10: I64EnumAttrCase<"case10", 10>; 152 153 def SomeI64Enum: I64EnumAttr< 154 "SomeI64Enum", "", [I64Case5, I64Case10]>; 155 156 def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> { 157 let arguments = (ins SomeI64Enum:$attr); 158 let results = (outs I32:$val); 159 } 160 161 //===----------------------------------------------------------------------===// 162 // Test Regions 163 //===----------------------------------------------------------------------===// 164 165 def TwoRegionOp : TEST_Op<"two_region_op", []> { 166 let regions = (region AnyRegion, AnyRegion); 167 } 168 169 def SizedRegionOp : TEST_Op<"sized_region_op", []> { 170 let regions = (region SizedRegion<2>:$my_region, SizedRegion<1>); 171 } 172 173 //===----------------------------------------------------------------------===// 174 // Test Traits 175 //===----------------------------------------------------------------------===// 176 177 def SameOperandElementTypeOp : TEST_Op<"same_operand_type", 178 [SameOperandsElementType]> { 179 let arguments = (ins AnyVectorOrTensor:$x, AnyVectorOrTensor:$y); 180 let results = (outs AnyVectorOrTensor:$res); 181 } 182 183 def SameOperandAndResultElementTypeOp : TEST_Op<"same_operand_and_result_type", 184 [SameOperandsAndResultElementType]> { 185 let arguments = (ins AnyVectorOrTensor:$x, AnyVectorOrTensor:$y); 186 let results = (outs AnyVectorOrTensor:$res); 187 } 188 189 def SameOperandShapeOp : TEST_Op<"same_operand_shape", [SameOperandsShape]> { 190 let arguments = (ins AnyVectorOrTensor:$x, AnyVectorOrTensor:$y); 191 let results = (outs AnyVectorOrTensor:$res); 192 } 193 194 def SameOperandAndResultShapeOp : TEST_Op<"same_operand_and_result_shape", 195 [SameOperandsAndResultShape]> { 196 let arguments = (ins AnyVectorOrTensor:$x, AnyVectorOrTensor:$y); 197 let results = (outs AnyVectorOrTensor:$res); 198 } 199 200 def ArgAndResHaveFixedElementTypesOp : 201 TEST_Op<"arg_and_res_have_fixed_element_types", 202 [PredOpTrait<"fixed type combination", 203 Or<[And<[ElementTypeIsPred<"x", I32>, 204 ElementTypeIsPred<"y", F32>]>, 205 ElementTypeIsPred<"attr", I8>]>>, 206 ElementTypeIs<"res", I16>]> { 207 let arguments = (ins 208 AnyVectorOrTensor:$x, AnyVectorOrTensor:$y, AnyAttr:$attr); 209 let results = (outs AnyVectorOrTensor:$res); 210 } 211 212 def OperandsHaveSameElementType : TEST_Op<"operands_have_same_element_type", [ 213 AllElementTypesMatch<["x", "y"]>]> { 214 let arguments = (ins AnyTensor:$x, AnyTensor:$y); 215 } 216 217 def OperandOneAndResultHaveSameElementType : TEST_Op< 218 "operand_one_and_result_have_same_element_type", 219 [AllElementTypesMatch<["x", "res"]>]> { 220 let arguments = (ins AnyTensor:$x, AnyTensor:$y); 221 let results = (outs AnyTensor:$res); 222 } 223 224 def OperandsHaveSameType : 225 TEST_Op<"operands_have_same_type", [AllTypesMatch<["x", "y"]>]> { 226 let arguments = (ins AnyTensor:$x, AnyTensor:$y); 227 } 228 229 def OperandOneAndResultHaveSameType : 230 TEST_Op<"operand_one_and_result_have_same_type", 231 [AllTypesMatch<["x", "res"]>]> { 232 let arguments = (ins AnyTensor:$x, AnyTensor:$y); 233 let results = (outs AnyTensor:$res); 234 } 235 236 def IfFirstOperandIsNoneThenSoIsSecond : 237 TEST_Op<"if_first_operand_is_none_then_so_is_second", [PredOpTrait< 238 "has either both none type operands or first is not none", 239 Or<[ 240 And<[TypeIsPred<"x", NoneType>, TypeIsPred<"y", NoneType>]>, 241 Neg<TypeIsPred<"x", NoneType>>]>>]> { 242 let arguments = (ins AnyType:$x, AnyType:$y); 243 } 244 245 def BroadcastableOp : TEST_Op<"broadcastable", [Broadcastable]> { 246 let arguments = (ins AnyTensor:$x, AnyTensor:$y); 247 let results = (outs AnyTensor:$res); 248 } 249 250 // There the "HasParent" trait. 251 def ParentOp : TEST_Op<"parent">; 252 def ChildOp : TEST_Op<"child", [HasParent<"ParentOp">]>; 253 254 255 def TerminatorOp : TEST_Op<"finish", [Terminator]> { 256 } 257 def SingleBlockImplicitTerminatorOp : TEST_Op<"SingleBlockImplicitTerminator", 258 [SingleBlockImplicitTerminator<"TerminatorOp">]> { 259 let regions = (region SizedRegion<1>:$region); 260 } 261 262 def I32ElementsAttributesOp : TEST_Op<"i32ElementsAttr"> { 263 let arguments = (ins I32ElementsAttr:$attr); 264 } 265 266 //===----------------------------------------------------------------------===// 267 // Test Patterns 268 //===----------------------------------------------------------------------===// 269 270 def OpA : TEST_Op<"op_a"> { 271 let arguments = (ins I32:$operand, I32Attr:$attr); 272 let results = (outs I32:$result); 273 } 274 275 def OpB : TEST_Op<"op_b"> { 276 let arguments = (ins I32:$operand, I32Attr:$attr); 277 let results = (outs I32:$result); 278 } 279 280 // Test named pattern. 281 def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>; 282 283 // Test with fused location. 284 def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>; 285 286 // Test added benefit. 287 def OpD : TEST_Op<"op_d">, Arguments<(ins I32:$arg)>, Results<(outs I32:$res)>; 288 def OpE : TEST_Op<"op_e">, Arguments<(ins I32:$arg)>, Results<(outs I32:$res)>; 289 def OpF : TEST_Op<"op_f">, Arguments<(ins I32:$arg)>, Results<(outs I32:$res)>; 290 def OpG : TEST_Op<"op_g">, Arguments<(ins I32:$arg)>, Results<(outs I32:$res)>; 291 // Verify that bumping benefit results in selecting different op. 292 def : Pat<(OpD $input), (OpE $input)>; 293 def : Pat<(OpD $input), (OpF $input), [], (addBenefit 10)>; 294 // Verify that patterns with more source nodes are selected before those with fewer. 295 def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>; 296 def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>; 297 298 // Test patterns for zero-result op. 299 def OpH : TEST_Op<"op_h">, Arguments<(ins I32:$arg)>, Results<(outs)>; 300 def OpI : TEST_Op<"op_i">, Arguments<(ins I32:$arg)>, Results<(outs)>; 301 def : Pat<(OpH $input), (OpI $input)>; 302 303 // Test patterns for zero-input op. 304 def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32:$res)>; 305 def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32:$res)>; 306 def : Pat<(OpJ), (OpK)>; 307 308 // Test NativeCodeCall. 309 def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> { 310 let arguments = (ins 311 I32:$input1, I32:$input2, 312 BoolAttr:$choice, 313 I64Attr:$attr1, I64Attr:$attr2 314 ); 315 let results = (outs I32:$output); 316 } 317 def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> { 318 let arguments = (ins I32:$input, I64ArrayAttr:$attr); 319 let results = (outs I32:$output); 320 } 321 // Native code call to invoke a C++ function 322 def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">; 323 // Native code call to invoke a C++ expression 324 def CreateArraryAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">; 325 // Test that we can use NativeCodeCall to create operand and attribute. 326 // This pattern chooses between $input1 and $input2 according to $choice and 327 // it combines $attr1 and $attr2 into an array attribute. 328 def : Pat<(OpNativeCodeCall1 $input1, $input2, 329 ConstBoolAttrTrue:$choice, $attr1, $attr2), 330 (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice), 331 (CreateArraryAttr $attr1, $attr2))>; 332 // Note: the following is just for testing purpose. 333 // Should use the replaceWithValue directive instead. 334 def UseOpResult: NativeCodeCall<"$0">; 335 // Test that we can use NativeCodeCall to create result. 336 def : Pat<(OpNativeCodeCall1 $input1, $input2, 337 ConstBoolAttrFalse, $attr1, $attr2), 338 (UseOpResult $input2)>; 339 340 // Test AllAttrConstraintsOf. 341 def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> { 342 let arguments = (ins I64ArrayAttr:$attr); 343 let results = (outs I32:$output); 344 } 345 def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> { 346 let arguments = (ins I64ArrayAttr:$attr); 347 let results = (outs I32:$output); 348 } 349 def Constraint0 : AttrConstraint< 350 CPred<"$_self.cast<ArrayAttr>().getValue()[0]." 351 "cast<IntegerAttr>().getInt() == 0">, 352 "[0] == 0">; 353 def Constraint1 : AttrConstraint< 354 CPred<"$_self.cast<ArrayAttr>().getValue()[1]." 355 "cast<IntegerAttr>().getInt() == 1">, 356 "[1] == 1">; 357 def : Pat<(OpAllAttrConstraint1 358 AllAttrConstraintsOf<[Constraint0, Constraint1]>:$attr), 359 (OpAllAttrConstraint2 $attr)>; 360 361 // Op for testing RewritePattern removing op with inner ops. 362 def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> { 363 let regions = (region SizedRegion<1>:$region); 364 let hasCanonicalizer = 1; 365 } 366 367 // Op for testing trivial removal via folding of op with inner ops and no uses. 368 def TestOpWithRegionFoldNoSideEffect : TEST_Op< 369 "op_with_region_fold_no_side_effect", [NoSideEffect]> { 370 let regions = (region SizedRegion<1>:$region); 371 } 372 373 // Op for testing folding of outer op with inner ops. 374 def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> { 375 let arguments = (ins I32:$operand); 376 let results = (outs I32:$result); 377 let regions = (region SizedRegion<1>:$region); 378 let hasFolder = 1; 379 } 380 381 //===----------------------------------------------------------------------===// 382 // Test Patterns (Symbol Binding) 383 384 // Test symbol binding. 385 def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> { 386 let arguments = (ins I32:$operand, I64Attr:$attr); 387 let results = (outs I32:$result); 388 } 389 def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> { 390 let arguments = (ins I32:$operand); 391 let results = (outs I32:$result); 392 393 let builders = [ 394 OpBuilder< 395 "Builder *builder, OperationState *state, Value *operand", 396 [{ 397 state->types.assign({builder->getIntegerType(32)}); 398 state->addOperands({operand}); 399 }]> 400 ]; 401 } 402 def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> { 403 let arguments = (ins I32:$operand); 404 let results = (outs I32:$result); 405 let builders = OpSymbolBindingB.builders; 406 } 407 def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> { 408 let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr); 409 let results = (outs I32:$result); 410 } 411 def HasOneUse: Constraint<CPred<"$0->hasOneUse()">, "has one use">; 412 def : Pattern< 413 // Bind to source pattern op operand/attribute/result 414 (OpSymbolBindingA:$res_a $operand, $attr), [ 415 // Bind to auxiliary op result 416 (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)), 417 418 // Use bound symbols in resultant ops 419 (OpSymbolBindingD $res_b, $res_c, $attr)], 420 // Use bound symbols in additional constraints 421 [(HasOneUse $res_a)]>; 422 423 //===----------------------------------------------------------------------===// 424 // Test Patterns (Attributes) 425 426 // Test matching against op attributes. 427 def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> { 428 let arguments = (ins 429 I32Attr:$required_attr, 430 OptionalAttr<I32Attr>:$optional_attr, 431 DefaultValuedAttr<I32Attr, "42">:$default_valued_attr, 432 I32Attr:$more_attr 433 ); 434 let results = (outs I32:$output); 435 } 436 def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> { 437 let arguments = OpAttrMatch1.arguments; 438 let results = (outs I32:$output); 439 } 440 def MoreConstraint : AttrConstraint< 441 CPred<"$_self.cast<IntegerAttr>().getInt() == 4">, "more constraint">; 442 def : Pat<(OpAttrMatch1 $required, $optional, $default_valued, 443 MoreConstraint:$more), 444 (OpAttrMatch2 $required, $optional, $default_valued, $more)>; 445 446 // Test unit attrs. 447 def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> { 448 let arguments = (ins UnitAttr:$attr); 449 let results = (outs I32); 450 } 451 def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> { 452 let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2); 453 let results = (outs I32); 454 } 455 def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>; 456 457 // Test with constant attr. 458 def OpC : TEST_Op<"op_c">, Arguments<(ins I32:$arg)>, Results<(outs I32:$res)>; 459 def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>; 460 461 // Test string enum attribute in rewrites. 462 def : Pat<(StrEnumAttrOp StrCaseA), (StrEnumAttrOp StrCaseB)>; 463 // Test integer enum attribute in rewrites. 464 def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>; 465 def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>; 466 467 //===----------------------------------------------------------------------===// 468 // Test Patterns (Multi-result Ops) 469 470 def MultiResultOpKind1: I64EnumAttrCase<"kind1", 1>; 471 def MultiResultOpKind2: I64EnumAttrCase<"kind2", 2>; 472 def MultiResultOpKind3: I64EnumAttrCase<"kind3", 3>; 473 def MultiResultOpKind4: I64EnumAttrCase<"kind4", 4>; 474 def MultiResultOpKind5: I64EnumAttrCase<"kind5", 5>; 475 def MultiResultOpKind6: I64EnumAttrCase<"kind6", 6>; 476 477 def MultiResultOpEnum: I64EnumAttr< 478 "Multi-result op kinds", "", [ 479 MultiResultOpKind1, MultiResultOpKind2, MultiResultOpKind3, 480 MultiResultOpKind4, MultiResultOpKind5, MultiResultOpKind6 481 ]>; 482 483 def ThreeResultOp : TEST_Op<"three_result"> { 484 let arguments = (ins MultiResultOpEnum:$kind); 485 let results = (outs I32:$result1, F32:$result2, F32:$result3); 486 } 487 488 def AnotherThreeResultOp : TEST_Op<"another_three_result"> { 489 let arguments = (ins MultiResultOpEnum:$kind); 490 let results = (outs I32:$result1, F32:$result2, F32:$result3); 491 } 492 493 def TwoResultOp : TEST_Op<"two_result"> { 494 let arguments = (ins MultiResultOpEnum:$kind); 495 let results = (outs I32:$result1, F32:$result2); 496 497 let builders = [ 498 OpBuilder< 499 "Builder *builder, OperationState *state, IntegerAttr kind", 500 [{ 501 auto i32 = builder->getIntegerType(32); 502 auto f32 = builder->getF32Type(); 503 state->types.assign({i32, f32}); 504 state->addAttribute("kind", kind); 505 }]> 506 ]; 507 } 508 509 def AnotherTwoResultOp : TEST_Op<"another_two_result"> { 510 let arguments = (ins MultiResultOpEnum:$kind); 511 let results = (outs F32:$result1, F32:$result2); 512 } 513 514 def OneResultOp1 : TEST_Op<"one_result1"> { 515 let arguments = (ins MultiResultOpEnum:$kind); 516 let results = (outs F32:$result1); 517 } 518 519 def OneResultOp2 : TEST_Op<"one_result2"> { 520 let arguments = (ins MultiResultOpEnum:$kind); 521 let results = (outs I32:$result1); 522 } 523 524 def OneResultOp3 : TEST_Op<"one_result3"> { 525 let arguments = (ins F32:$input); 526 let results = (outs I32:$result1); 527 } 528 529 // Test using multi-result op as a whole 530 def : Pat<(ThreeResultOp MultiResultOpKind1), 531 (AnotherThreeResultOp MultiResultOpKind1)>; 532 533 // Test using multi-result op as a whole for partial replacement 534 def : Pattern<(ThreeResultOp MultiResultOpKind2), 535 [(TwoResultOp MultiResultOpKind2), 536 (OneResultOp1 MultiResultOpKind2)]>; 537 def : Pattern<(ThreeResultOp MultiResultOpKind3), 538 [(OneResultOp2 MultiResultOpKind3), 539 (AnotherTwoResultOp MultiResultOpKind3)]>; 540 541 // Test using results separately in a multi-result op 542 def : Pattern<(ThreeResultOp MultiResultOpKind4), 543 [(TwoResultOp:$res1__0 MultiResultOpKind4), 544 (OneResultOp1 MultiResultOpKind4), 545 (TwoResultOp:$res2__1 MultiResultOpKind4)]>; 546 547 // Test referencing a single value in the value pack 548 // This rule only matches TwoResultOp if its second result has no use. 549 def : Pattern<(TwoResultOp:$res MultiResultOpKind5), 550 [(OneResultOp2 MultiResultOpKind5), 551 (OneResultOp1 MultiResultOpKind5)], 552 [(HasNoUseOf:$res__1)]>; 553 554 // Test using auxiliary ops for replacing multi-result op 555 def : Pattern< 556 (ThreeResultOp MultiResultOpKind6), [ 557 // Auxiliary op generated to help building the final result but not 558 // directly used to replace the source op's results. 559 (TwoResultOp:$interm MultiResultOpKind6), 560 561 (OneResultOp3 $interm__1), 562 (AnotherTwoResultOp MultiResultOpKind6) 563 ]>; 564 565 //===----------------------------------------------------------------------===// 566 // Test Patterns (Variadic Ops) 567 568 def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> { 569 let arguments = (ins Variadic<I32>:$inputs); 570 let results = (outs Variadic<I32>:$outputs); 571 } 572 def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> { 573 let arguments = (ins Variadic<I32>:$inputs); 574 let results = (outs Variadic<I32>:$outputs); 575 } 576 577 // Rewrite an op with one variadic operand and one variadic result to 578 // another similiar op. 579 def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>; 580 581 def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1", 582 [SameVariadicOperandSize]> { 583 let arguments = (ins 584 Variadic<I32>:$input1, 585 F32:$input2, 586 Variadic<I32>:$input3 587 ); 588 } 589 590 def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2", 591 [SameVariadicOperandSize]> { 592 let arguments = (ins 593 Variadic<I32>:$input1, 594 F32:$input2, 595 Variadic<I32>:$input3 596 ); 597 } 598 599 // Rewrite an op with both variadic operands and normal operands. 600 def : Pat<(MixedVOperandOp1 $input1, $input2, $input3), 601 (MixedVOperandOp2 $input1, $input2, $input3)>; 602 603 def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> { 604 let results = (outs 605 Variadic<I32>:$output1, 606 F32:$output2, 607 Variadic<I32>:$output3 608 ); 609 } 610 611 def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> { 612 let results = (outs 613 Variadic<I32>:$output1, 614 F32:$output2, 615 Variadic<I32>:$output3 616 ); 617 } 618 619 // Rewrite an op with both variadic results and normal results. 620 // Note that because we are generating the op with a top-level result pattern, 621 // we are able to deduce the correct result types for the generated op using 622 // the information from the matched root op. 623 def : Pat<(MixedVResultOp1), (MixedVResultOp2)>; 624 625 def OneI32ResultOp : TEST_Op<"one_i32_out"> { 626 let results = (outs I32:$output); 627 } 628 629 def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3", 630 [SameVariadicOperandSize]> { 631 let arguments = (ins 632 I32:$input1, 633 Variadic<I32>:$input2, 634 Variadic<I32>:$input3, 635 I32Attr:$count 636 ); 637 638 let results = (outs I32:$output); 639 } 640 641 def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3", 642 [SameVariadicResultSize]> { 643 let arguments = (ins I32Attr:$count); 644 645 let results = (outs 646 I32:$output1, 647 Variadic<I32>:$output2, 648 Variadic<I32>:$output3 649 ); 650 651 // We will use this op in a nested result pattern, where we cannot deduce the 652 // result type. So need to provide a builder not requiring result types. 653 let builders = [ 654 OpBuilder< 655 "Builder *builder, OperationState *state, IntegerAttr count", 656 [{ 657 auto i32Type = builder->getIntegerType(32); 658 state->addTypes(i32Type); // $ouput1 659 SmallVector<Type, 4> types(count.getInt(), i32Type); 660 state->addTypes(types); // $ouput2 661 state->addTypes(types); // $ouput3 662 state->addAttribute("count", count); 663 }]> 664 ]; 665 } 666 667 // Generates an op with variadic results using nested pattern. 668 def : Pat<(OneI32ResultOp), 669 (MixedVOperandOp3 670 (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">), 671 (replaceWithValue $results__1), 672 (replaceWithValue $results__2), 673 ConstantAttr<I32Attr, "2">)>; 674 675 //===----------------------------------------------------------------------===// 676 // Test Legalization 677 //===----------------------------------------------------------------------===// 678 679 def Test_LegalizerEnum_Success : StrEnumAttrCase<"Success">; 680 def Test_LegalizerEnum_Failure : StrEnumAttrCase<"Failure">; 681 682 def Test_LegalizerEnum : StrEnumAttr<"Success", "Failure", 683 [Test_LegalizerEnum_Success, Test_LegalizerEnum_Failure]>; 684 685 def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32:$res)>; 686 def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32:$res)>; 687 def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32:$res)>; 688 def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32:$res)>; 689 def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32:$res)>; 690 def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32:$res)>; 691 def LegalOpA : TEST_Op<"legal_op_a">, 692 Arguments<(ins Test_LegalizerEnum:$status)>, Results<(outs I32:$res)>; 693 694 // Check that smaller pattern depths are chosen, i.e. prioritize more direct 695 // mappings. 696 def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>; 697 698 def : Pat<(ILLegalOpA), (ILLegalOpB)>; 699 def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>; 700 701 // Check that the higher benefit pattern is taken for multiple legalizations 702 // with the same depth. 703 def : Pat<(ILLegalOpC), (ILLegalOpD)>; 704 def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>; 705 706 def : Pat<(ILLegalOpC), (ILLegalOpE), [], (addBenefit 10)>; 707 def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>; 708 709 // Check that patterns use the most up-to-date value when being replaced. 710 def TestRewriteOp : TEST_Op<"rewrite">, 711 Arguments<(ins AnyType:$input)>, Results<(outs AnyType:$res)>; 712 def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>; 713 714 //===----------------------------------------------------------------------===// 715 // Test Type Legalization 716 //===----------------------------------------------------------------------===// 717 718 def TestRegionBuilderOp : TEST_Op<"region_builder">; 719 def TestReturnOp : TEST_Op<"return", [Terminator]>, 720 Arguments<(ins Variadic<AnyType>:$inputs)>; 721 def TestCastOp : TEST_Op<"cast">, 722 Arguments<(ins Variadic<AnyType>:$inputs)>, Results<(outs AnyType:$res)>; 723 def TestInvalidOp : TEST_Op<"invalid", [Terminator]>, 724 Arguments<(ins Variadic<AnyType>:$inputs)>; 725 def TestValidOp : TEST_Op<"valid", [Terminator]>, 726 Arguments<(ins Variadic<AnyType>:$inputs)>; 727 728 //===----------------------------------------------------------------------===// 729 // Test region argument list parsing. 730 //===----------------------------------------------------------------------===// 731 732 def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> { 733 let summary = "isolated region operation"; 734 let description = [{ 735 Test op with an isolated region, to test passthrough region arguments. Each 736 argument is of index type. 737 }]; 738 739 let arguments = (ins Index:$input); 740 let regions = (region SizedRegion<1>:$region); 741 let parser = [{ return ::parse$cppClass(parser, result); }]; 742 let printer = [{ return ::print(p, *this); }]; 743 } 744 745 def PolyForOp : TEST_Op<"polyfor"> 746 { 747 let summary = "polyfor operation"; 748 let description = [{ 749 Test op with multiple region arguments, each argument of index type. 750 }]; 751 752 let regions = (region SizedRegion<1>:$region); 753 let parser = [{ return ::parse$cppClass(parser, result); }]; 754 } 755 756 #endif // TEST_OPS