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