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