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