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