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