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