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