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