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