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 TestProducingBranchOp : TEST_Op<"producing_br",
621    [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator,
622     AttrSizedOperandSegments]> {
623  let arguments = (ins Variadic<AnyType>:$firstOperands,
624                       Variadic<AnyType>:$secondOperands);
625  let results = (outs I32:$dummy);
626  let successors = (successor AnySuccessor:$first,AnySuccessor:$second);
627}
628
629def AttrSizedOperandOp : TEST_Op<"attr_sized_operands",
630                                 [AttrSizedOperandSegments]> {
631  let arguments = (ins
632    Variadic<I32>:$a,
633    Variadic<I32>:$b,
634    I32:$c,
635    Variadic<I32>:$d,
636    I32ElementsAttr:$operand_segment_sizes
637  );
638}
639
640def AttrSizedResultOp : TEST_Op<"attr_sized_results",
641                                [AttrSizedResultSegments]> {
642  let arguments = (ins
643    I32ElementsAttr:$result_segment_sizes
644  );
645  let results = (outs
646    Variadic<I32>:$a,
647    Variadic<I32>:$b,
648    I32:$c,
649    Variadic<I32>:$d
650  );
651}
652
653// This is used to test that the fallback for a custom op's parser and printer
654// is the dialect parser and printer hooks.
655def CustomFormatFallbackOp : TEST_Op<"dialect_custom_format_fallback">;
656
657// Ops related to OIList primitive
658def OIListTrivial : TEST_Op<"oilist_with_keywords_only"> {
659  let arguments = (ins UnitAttr:$keyword, UnitAttr:$otherKeyword,
660                       UnitAttr:$diffNameUnitAttrKeyword);
661  let assemblyFormat = [{
662    oilist( `keyword` $keyword
663          | `otherKeyword` $otherKeyword
664          | `thirdKeyword` $diffNameUnitAttrKeyword) attr-dict
665  }];
666}
667
668def OIListSimple : TEST_Op<"oilist_with_simple_args", [AttrSizedOperandSegments]> {
669  let arguments = (ins Optional<AnyType>:$arg0,
670                       Optional<AnyType>:$arg1,
671                       Optional<AnyType>:$arg2);
672  let assemblyFormat = [{
673    oilist( `keyword` $arg0 `:` type($arg0)
674          | `otherKeyword` $arg1 `:` type($arg1)
675          | `thirdKeyword` $arg2 `:` type($arg2) ) attr-dict
676  }];
677}
678
679def OIListVariadic : TEST_Op<"oilist_variadic_with_parens", [AttrSizedOperandSegments]> {
680  let arguments = (ins Variadic<AnyType>:$arg0,
681                       Variadic<AnyType>:$arg1,
682                       Variadic<AnyType>:$arg2);
683  let assemblyFormat = [{
684    oilist( `keyword` `(` $arg0 `:` type($arg0) `)`
685          | `otherKeyword` `(` $arg1 `:` type($arg1) `)`
686          | `thirdKeyword` `(` $arg2 `:` type($arg2) `)`) attr-dict
687  }];
688}
689
690def OIListCustom : TEST_Op<"oilist_custom", [AttrSizedOperandSegments]> {
691  let arguments = (ins Variadic<AnyType>:$arg0,
692                       Optional<I32>:$optOperand,
693                       UnitAttr:$nowait);
694  let assemblyFormat = [{
695    oilist( `private` `(` $arg0 `:` type($arg0) `)`
696          | `reduction` custom<CustomOptionalOperand>($optOperand)
697          | `nowait` $nowait
698    ) attr-dict
699  }];
700}
701
702def OIListAllowedLiteral : TEST_Op<"oilist_allowed_literal"> {
703  let assemblyFormat = [{
704    oilist( `foo` | `bar` ) `buzz` attr-dict
705  }];
706}
707
708// This is used to test encoding of a string attribute into an SSA name of a
709// pretty printed value name.
710def StringAttrPrettyNameOp
711 : TEST_Op<"string_attr_pretty_name",
712           [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
713  let arguments = (ins StrArrayAttr:$names);
714  let results = (outs Variadic<I32>:$r);
715  let hasCustomAssemblyFormat = 1;
716}
717
718// This is used to test the OpAsmOpInterface::getDefaultDialect() feature:
719// operations nested in a region under this op will drop the "test." dialect
720// prefix.
721def DefaultDialectOp : TEST_Op<"default_dialect", [OpAsmOpInterface]> {
722 let regions = (region AnyRegion:$body);
723  let extraClassDeclaration = [{
724    static ::llvm::StringRef getDefaultDialect() {
725      return "test";
726    }
727    void getAsmResultNames(::llvm::function_ref<void(::mlir::Value, ::llvm::StringRef)> setNameFn) {}
728  }];
729  let assemblyFormat = "regions attr-dict-with-keyword";
730}
731
732// This is used to test the OpAsmOpInterface::getAsmBlockName() feature:
733// blocks nested in a region under this op will have a name defined by the
734// interface.
735def AsmBlockNameOp : TEST_Op<"block_names", [OpAsmOpInterface]> {
736 let regions = (region AnyRegion:$body);
737  let extraClassDeclaration = [{
738    void getAsmBlockNames(mlir::OpAsmSetBlockNameFn setNameFn) {
739      std::string name;
740      int count = 0;
741      for (::mlir::Block &block : getRegion().getBlocks()) {
742        name = "foo" + std::to_string(count++);
743        setNameFn(&block, name);
744      }
745    }
746  }];
747  let assemblyFormat = "regions attr-dict-with-keyword";
748}
749
750// This operation requires its return type to have the trait 'TestTypeTrait'.
751def ResultTypeWithTraitOp : TEST_Op<"result_type_with_trait", []> {
752  let results = (outs AnyType);
753  let hasVerifier = 1;
754}
755
756// This operation requires its "attr" attribute to have the
757// trait 'TestAttrTrait'.
758def AttrWithTraitOp : TEST_Op<"attr_with_trait", []> {
759  let arguments = (ins AnyAttr:$attr);
760  let hasVerifier = 1;
761}
762
763//===----------------------------------------------------------------------===//
764// Test Locations
765//===----------------------------------------------------------------------===//
766
767def TestLocationSrcOp : TEST_Op<"loc_src"> {
768  let arguments = (ins I32:$input);
769  let results = (outs I32:$output);
770}
771
772def TestLocationDstOp : TEST_Op<"loc_dst", [SameOperandsAndResultType]> {
773  let arguments = (ins I32:$input);
774  let results = (outs I32:$output);
775}
776
777def TestLocationSrcNoResOp : TEST_Op<"loc_src_no_res"> {
778  let arguments = (ins I32:$input);
779  let results = (outs);
780}
781
782def TestLocationDstNoResOp : TEST_Op<"loc_dst_no_res"> {
783  let arguments = (ins I32:$input);
784  let results = (outs);
785}
786
787//===----------------------------------------------------------------------===//
788// Test Patterns
789//===----------------------------------------------------------------------===//
790
791def OpA : TEST_Op<"op_a"> {
792  let arguments = (ins I32, I32Attr:$attr);
793  let results = (outs I32);
794}
795
796def OpB : TEST_Op<"op_b"> {
797  let arguments = (ins I32, I32Attr:$attr);
798  let results = (outs I32);
799}
800
801// Test named pattern.
802def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>;
803
804// Test with fused location.
805def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>;
806
807// Test added benefit.
808def OpD : TEST_Op<"op_d">, Arguments<(ins I32)>, Results<(outs I32)>;
809def OpE : TEST_Op<"op_e">, Arguments<(ins I32)>, Results<(outs I32)>;
810def OpF : TEST_Op<"op_f">, Arguments<(ins I32)>, Results<(outs I32)>;
811def OpG : TEST_Op<"op_g">, Arguments<(ins I32)>, Results<(outs I32)>;
812// Verify that bumping benefit results in selecting different op.
813def : Pat<(OpD $input), (OpE $input)>;
814def : Pat<(OpD $input), (OpF $input), [], (addBenefit 10)>;
815// Verify that patterns with more source nodes are selected before those with fewer.
816def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>;
817def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>;
818
819// Test patterns for zero-result op.
820def OpH : TEST_Op<"op_h">, Arguments<(ins I32)>, Results<(outs)>;
821def OpI : TEST_Op<"op_i">, Arguments<(ins I32)>, Results<(outs)>;
822def : Pat<(OpH $input), (OpI $input)>;
823
824// Test patterns for zero-input op.
825def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32)>;
826def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32)>;
827def : Pat<(OpJ), (OpK)>;
828
829// Test that natives calls are only called once during rewrites.
830def OpM : TEST_Op<"op_m"> {
831  let arguments = (ins I32, OptionalAttr<I32Attr>:$optional_attr);
832  let results = (outs I32);
833}
834
835def OpN : TEST_Op<"op_n"> {
836  let arguments = (ins I32, I32);
837  let results = (outs I32);
838}
839
840def OpO : TEST_Op<"op_o"> {
841  let arguments = (ins I32);
842  let results = (outs I32);
843}
844
845def OpP : TEST_Op<"op_p"> {
846  let arguments = (ins I32, I32, I32, I32, I32, I32);
847  let results = (outs I32);
848}
849
850// Test same operand name enforces equality condition check.
851def TestEqualArgsPattern : Pat<(OpN $a, $a), (OpO $a)>;
852
853// Test when equality is enforced at different depth.
854def TestNestedOpEqualArgsPattern :
855  Pat<(OpN $b, (OpP $a, $b, $c, $d, $e, $f)), (replaceWithValue $b)>;
856
857// Test when equality is enforced on same op and same operand but at different
858// depth. We only bound one of the $x to the second operand of outer OpN and
859// left another be the default value (which is the value of first operand of
860// outer OpN). As a result, it ended up comparing wrong values in some cases.
861def TestNestedSameOpAndSameArgEqualityPattern :
862  Pat<(OpN (OpN $_, $x), $x), (replaceWithValue $x)>;
863
864// Test multiple equal arguments check enforced.
865def TestMultipleEqualArgsPattern :
866  Pat<(OpP $a, $b, $a, $a, $b, $c), (OpN $c, $b)>;
867
868// Test for memrefs normalization of an op with normalizable memrefs.
869def OpNorm : TEST_Op<"op_norm", [MemRefsNormalizable]> {
870  let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y);
871}
872// Test for memrefs normalization of an op without normalizable memrefs.
873def OpNonNorm : TEST_Op<"op_nonnorm"> {
874  let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y);
875}
876// Test for memrefs normalization of an op that has normalizable memref results.
877def OpNormRet : TEST_Op<"op_norm_ret", [MemRefsNormalizable]> {
878  let arguments = (ins AnyMemRef:$X);
879  let results = (outs AnyMemRef:$Y, AnyMemRef:$Z);
880}
881
882// Test for memrefs normalization of an op with a reference to a function
883// symbol.
884def OpFuncRef : TEST_Op<"op_funcref"> {
885  let summary = "Test op with a reference to a function symbol";
886  let description = [{
887    The "test.op_funcref" is a test op with a reference to a function symbol.
888  }];
889  let builders = [OpBuilder<(ins "::mlir::FuncOp":$function)>];
890}
891
892// Pattern add the argument plus a increasing static number hidden in
893// OpMTest function. That value is set into the optional argument.
894// That way, we will know if operations is called once or twice.
895def OpMGetNullAttr : NativeCodeCall<"Attribute()">;
896def OpMAttributeIsNull : Constraint<CPred<"! ($_self)">, "Attribute is null">;
897def OpMVal : NativeCodeCall<"opMTest($_builder, $0)">;
898def : Pat<(OpM $attr, $optAttr), (OpM $attr, (OpMVal $attr) ),
899    [(OpMAttributeIsNull:$optAttr)]>;
900
901// Test `$_` for ignoring op argument match.
902def TestIgnoreArgMatchSrcOp : TEST_Op<"ignore_arg_match_src"> {
903  let arguments = (ins
904    AnyType:$a, AnyType:$b, AnyType:$c,
905    AnyAttr:$d, AnyAttr:$e, AnyAttr:$f);
906}
907def TestIgnoreArgMatchDstOp : TEST_Op<"ignore_arg_match_dst"> {
908  let arguments = (ins AnyType:$b, AnyAttr:$f);
909}
910def : Pat<(TestIgnoreArgMatchSrcOp $_, $b, I32, I64Attr:$_, $_, $f),
911          (TestIgnoreArgMatchDstOp $b, $f)>;
912
913def OpInterleavedOperandAttribute1 : TEST_Op<"interleaved_operand_attr1"> {
914  let arguments = (ins
915    I32:$input1,
916    I64Attr:$attr1,
917    I32:$input2,
918    I64Attr:$attr2
919  );
920}
921
922def OpInterleavedOperandAttribute2 : TEST_Op<"interleaved_operand_attr2"> {
923  let arguments = (ins
924    I32:$input1,
925    I64Attr:$attr1,
926    I32:$input2,
927    I64Attr:$attr2
928  );
929}
930
931def ManyArgsOp : TEST_Op<"many_arguments"> {
932  let arguments = (ins
933    I32:$input1, I32:$input2, I32:$input3, I32:$input4, I32:$input5,
934    I32:$input6, I32:$input7, I32:$input8, I32:$input9,
935    I64Attr:$attr1, I64Attr:$attr2, I64Attr:$attr3, I64Attr:$attr4,
936    I64Attr:$attr5, I64Attr:$attr6, I64Attr:$attr7, I64Attr:$attr8,
937    I64Attr:$attr9
938  );
939}
940
941// Test that DRR does not blow up when seeing lots of arguments.
942def : Pat<(ManyArgsOp
943            $input1, $input2, $input3, $input4, $input5,
944            $input6, $input7, $input8, $input9,
945            ConstantAttr<I64Attr, "42">,
946            $attr2, $attr3, $attr4, $attr5, $attr6,
947            $attr7, $attr8, $attr9),
948          (ManyArgsOp
949            $input1, $input2, $input3, $input4, $input5,
950            $input6, $input7, $input8, $input9,
951            ConstantAttr<I64Attr, "24">,
952            $attr2, $attr3, $attr4, $attr5, $attr6,
953            $attr7, $attr8, $attr9)>;
954
955// Test that we can capture and reference interleaved operands and attributes.
956def : Pat<(OpInterleavedOperandAttribute1 $input1, $attr1, $input2, $attr2),
957          (OpInterleavedOperandAttribute2 $input1, $attr1, $input2, $attr2)>;
958
959// Test NativeCodeCall.
960def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> {
961  let arguments = (ins
962    I32:$input1, I32:$input2,
963    BoolAttr:$choice,
964    I64Attr:$attr1, I64Attr:$attr2
965  );
966  let results = (outs I32);
967}
968def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> {
969  let arguments = (ins I32:$input, I64ArrayAttr:$attr);
970  let results = (outs I32);
971}
972// Native code call to invoke a C++ function
973def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">;
974// Native code call to invoke a C++ expression
975def CreateArrayAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">;
976// Test that we can use NativeCodeCall to create operand and attribute.
977// This pattern chooses between $input1 and $input2 according to $choice and
978// it combines $attr1 and $attr2 into an array attribute.
979def : Pat<(OpNativeCodeCall1 $input1, $input2,
980                             ConstBoolAttrTrue:$choice, $attr1, $attr2),
981          (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice),
982                             (CreateArrayAttr $attr1, $attr2))>;
983// Note: the following is just for testing purpose.
984// Should use the replaceWithValue directive instead.
985def UseOpResult: NativeCodeCall<"$0">;
986// Test that we can use NativeCodeCall to create result.
987def : Pat<(OpNativeCodeCall1 $input1, $input2,
988                             ConstBoolAttrFalse, $attr1, $attr2),
989          (UseOpResult $input2)>;
990
991def OpNativeCodeCall3 : TEST_Op<"native_code_call3"> {
992  let arguments = (ins I32:$input);
993  let results = (outs I32);
994}
995// Test that NativeCodeCall is not ignored if it is not used to directly
996// replace the matched root op.
997def : Pattern<(OpNativeCodeCall3 $input),
998              [(NativeCodeCallVoid<"createOpI($_builder, $_loc, $0)"> $input),
999               (OpK)]>;
1000
1001def OpNativeCodeCall4 : TEST_Op<"native_code_call4"> {
1002  let arguments = (ins AnyType:$input1);
1003  let results = (outs I32:$output1, I32:$output2);
1004}
1005def OpNativeCodeCall5 : TEST_Op<"native_code_call5"> {
1006  let arguments = (ins I32:$input1, I32:$input2);
1007  let results = (outs I32:$output1, I32:$output2);
1008}
1009
1010def GetFirstI32Result : NativeCodeCall<"success(getFirstI32Result($_self, $0))">;
1011def BindNativeCodeCallResult : NativeCodeCall<"bindNativeCodeCallResult($0)">;
1012def : Pat<(OpNativeCodeCall4 (GetFirstI32Result $ret)),
1013          (OpNativeCodeCall5 (BindNativeCodeCallResult:$native $ret), $native)>;
1014
1015def OpNativeCodeCall6 : TEST_Op<"native_code_call6"> {
1016  let arguments = (ins I32:$input1, I32:$input2);
1017  let results = (outs I32:$output1, I32:$output2);
1018}
1019def OpNativeCodeCall7 : TEST_Op<"native_code_call7"> {
1020  let arguments = (ins I32:$input);
1021  let results = (outs I32);
1022}
1023def BindMultipleNativeCodeCallResult : NativeCodeCall<"bindMultipleNativeCodeCallResult($0, $1)", 2>;
1024def : Pattern<(OpNativeCodeCall6 $arg1, $arg2),
1025              [(OpNativeCodeCall7 (BindMultipleNativeCodeCallResult:$native__0 $arg1, $arg2)),
1026               (OpNativeCodeCall7 $native__1)]>;
1027
1028// Test AllAttrConstraintsOf.
1029def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> {
1030  let arguments = (ins I64ArrayAttr:$attr);
1031  let results = (outs I32);
1032}
1033def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> {
1034  let arguments = (ins I64ArrayAttr:$attr);
1035  let results = (outs I32);
1036}
1037def Constraint0 : AttrConstraint<
1038    CPred<"$_self.cast<ArrayAttr>()[0]."
1039          "cast<::mlir::IntegerAttr>().getInt() == 0">,
1040    "[0] == 0">;
1041def Constraint1 : AttrConstraint<
1042    CPred<"$_self.cast<ArrayAttr>()[1].cast<::mlir::IntegerAttr>().getInt() == 1">,
1043    "[1] == 1">;
1044def : Pat<(OpAllAttrConstraint1
1045            AllAttrConstraintsOf<[Constraint0, Constraint1]>:$attr),
1046          (OpAllAttrConstraint2 $attr)>;
1047
1048// Op for testing RewritePattern removing op with inner ops.
1049def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> {
1050  let regions = (region SizedRegion<1>:$region);
1051  let hasCanonicalizer = 1;
1052}
1053
1054def TestOpConstant : TEST_Op<"constant", [ConstantLike, NoSideEffect]> {
1055  let arguments = (ins AnyAttr:$value);
1056  let results = (outs AnyType);
1057
1058  let hasFolder = 1;
1059}
1060
1061def OpR : TEST_Op<"op_r">, Arguments<(ins AnyInteger, AnyInteger)>, Results<(outs AnyInteger)>;
1062def OpS : TEST_Op<"op_s">, Arguments<(ins AnyInteger, AnyAttr:$value)>, Results<(outs AnyInteger)>;
1063
1064def : Pat<(OpR $input1, (ConstantLikeMatcher I32Attr:$input2)),
1065          (OpS:$unused $input1, $input2)>;
1066
1067// Op for testing trivial removal via folding of op with inner ops and no uses.
1068def TestOpWithRegionFoldNoSideEffect : TEST_Op<
1069    "op_with_region_fold_no_side_effect", [NoSideEffect]> {
1070  let regions = (region SizedRegion<1>:$region);
1071}
1072
1073// Op for testing folding of outer op with inner ops.
1074def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> {
1075  let arguments = (ins I32:$operand);
1076  let results = (outs I32);
1077  let regions = (region SizedRegion<1>:$region);
1078  let hasFolder = 1;
1079}
1080
1081def TestOpWithVariadicResultsAndFolder: TEST_Op<"op_with_variadic_results_and_folder"> {
1082  let arguments = (ins Variadic<I32>);
1083  let results = (outs Variadic<I32>);
1084  let hasFolder = 1;
1085}
1086
1087def TestCommutativeOp : TEST_Op<"op_commutative", [Commutative]> {
1088  let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4);
1089  let results = (outs I32);
1090}
1091
1092def TestCommutative2Op : TEST_Op<"op_commutative2", [Commutative]> {
1093  let arguments = (ins I32:$op1, I32:$op2);
1094  let results = (outs I32);
1095}
1096
1097def TestIdempotentTraitOp
1098 : TEST_Op<"op_idempotent_trait",
1099           [SameOperandsAndResultType, NoSideEffect, Idempotent]> {
1100  let arguments = (ins I32:$op1);
1101  let results = (outs I32);
1102}
1103
1104def TestIdempotentTraitBinaryOp
1105    : TEST_Op<"op_idempotent_trait_binary",
1106              [SameOperandsAndResultType, NoSideEffect, Idempotent]> {
1107  let arguments = (ins I32:$op1, I32:$op2);
1108  let results = (outs I32);
1109}
1110
1111def TestInvolutionTraitNoOperationFolderOp
1112 : TEST_Op<"op_involution_trait_no_operation_fold",
1113           [SameOperandsAndResultType, NoSideEffect, Involution]> {
1114  let arguments = (ins I32:$op1);
1115  let results = (outs I32);
1116}
1117
1118def TestInvolutionTraitFailingOperationFolderOp
1119 : TEST_Op<"op_involution_trait_failing_operation_fold",
1120           [SameOperandsAndResultType, NoSideEffect, Involution]> {
1121  let arguments = (ins I32:$op1);
1122  let results = (outs I32);
1123  let hasFolder = 1;
1124}
1125
1126def TestInvolutionTraitSuccesfulOperationFolderOp
1127 : TEST_Op<"op_involution_trait_succesful_operation_fold",
1128           [SameOperandsAndResultType, NoSideEffect, Involution]> {
1129  let arguments = (ins I32:$op1);
1130  let results = (outs I32);
1131  let hasFolder = 1;
1132}
1133
1134def TestOpInPlaceFoldAnchor : TEST_Op<"op_in_place_fold_anchor"> {
1135  let arguments = (ins I32);
1136  let results = (outs I32);
1137}
1138
1139def TestOpInPlaceFold : TEST_Op<"op_in_place_fold"> {
1140  let arguments = (ins I32:$op, I32Attr:$attr);
1141  let results = (outs I32);
1142  let hasFolder = 1;
1143}
1144
1145// An op that always fold itself.
1146def TestPassthroughFold : TEST_Op<"passthrough_fold"> {
1147  let arguments = (ins AnyType:$op);
1148  let results = (outs AnyType);
1149  let hasFolder = 1;
1150}
1151
1152def TestDialectCanonicalizerOp : TEST_Op<"dialect_canonicalizable"> {
1153  let arguments = (ins);
1154  let results = (outs I32);
1155}
1156
1157//===----------------------------------------------------------------------===//
1158// Test Patterns (Symbol Binding)
1159
1160// Test symbol binding.
1161def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> {
1162  let arguments = (ins I32:$operand, I64Attr:$attr);
1163  let results = (outs I32);
1164}
1165def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> {
1166  let arguments = (ins I32:$operand);
1167  let results = (outs I32);
1168}
1169def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> {
1170  let arguments = (ins I32:$operand);
1171  let results = (outs I32);
1172  let builders = OpSymbolBindingB.builders;
1173}
1174def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> {
1175  let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr);
1176  let results = (outs I32);
1177}
1178def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">;
1179def : Pattern<
1180    // Bind to source pattern op operand/attribute/result
1181    (OpSymbolBindingA:$res_a $operand, $attr), [
1182        // Bind to auxiliary op result
1183        (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)),
1184
1185        // Use bound symbols in resultant ops
1186        (OpSymbolBindingD $res_b, $res_c, $attr)],
1187    // Use bound symbols in additional constraints
1188    [(HasOneUse $res_a)]>;
1189
1190def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> {
1191  let arguments = (ins I32:$operand);
1192}
1193
1194// Test that we can bind to an op without results and reference it later.
1195def : Pat<(OpSymbolBindingNoResult:$op $operand),
1196          (NativeCodeCallVoid<"handleNoResultOp($_builder, $0)"> $op)>;
1197
1198//===----------------------------------------------------------------------===//
1199// Test Patterns (Attributes)
1200
1201// Test matching against op attributes.
1202def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> {
1203  let arguments = (ins
1204    I32Attr:$required_attr,
1205    OptionalAttr<I32Attr>:$optional_attr,
1206    DefaultValuedAttr<I32Attr, "42">:$default_valued_attr,
1207    I32Attr:$more_attr
1208  );
1209  let results = (outs I32);
1210}
1211def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> {
1212  let arguments = OpAttrMatch1.arguments;
1213  let results = (outs I32);
1214}
1215def MoreConstraint : AttrConstraint<
1216    CPred<"$_self.cast<IntegerAttr>().getInt() == 4">, "more constraint">;
1217def : Pat<(OpAttrMatch1 $required, $optional, $default_valued,
1218                        MoreConstraint:$more),
1219          (OpAttrMatch2 $required, $optional, $default_valued, $more)>;
1220
1221// Test unit attrs.
1222def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> {
1223  let arguments = (ins UnitAttr:$attr);
1224  let results = (outs I32);
1225}
1226def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> {
1227  let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2);
1228  let results = (outs I32);
1229}
1230def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>;
1231
1232// Test with constant attr.
1233def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>;
1234def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>;
1235
1236// Test string enum attribute in rewrites.
1237def : Pat<(StrEnumAttrOp StrCaseA), (StrEnumAttrOp StrCaseB)>;
1238// Test integer enum attribute in rewrites.
1239def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>;
1240def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>;
1241
1242//===----------------------------------------------------------------------===//
1243// Test Patterns (Multi-result Ops)
1244
1245def MultiResultOpKind1: I64EnumAttrCase<"kind1", 1>;
1246def MultiResultOpKind2: I64EnumAttrCase<"kind2", 2>;
1247def MultiResultOpKind3: I64EnumAttrCase<"kind3", 3>;
1248def MultiResultOpKind4: I64EnumAttrCase<"kind4", 4>;
1249def MultiResultOpKind5: I64EnumAttrCase<"kind5", 5>;
1250def MultiResultOpKind6: I64EnumAttrCase<"kind6", 6>;
1251
1252def MultiResultOpEnum: I64EnumAttr<
1253  "MultiResultOpEnum", "Multi-result op kinds", [
1254    MultiResultOpKind1, MultiResultOpKind2, MultiResultOpKind3,
1255    MultiResultOpKind4, MultiResultOpKind5, MultiResultOpKind6
1256  ]>;
1257
1258def ThreeResultOp : TEST_Op<"three_result"> {
1259  let arguments = (ins MultiResultOpEnum:$kind);
1260  let results = (outs I32:$result1, F32:$result2, F32:$result3);
1261}
1262
1263def AnotherThreeResultOp
1264    : TEST_Op<"another_three_result",
1265              [DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
1266  let arguments = (ins MultiResultOpEnum:$kind);
1267  let results = (outs I32:$result1, F32:$result2, F32:$result3);
1268}
1269
1270def TwoResultOp : TEST_Op<"two_result"> {
1271  let arguments = (ins MultiResultOpEnum:$kind);
1272  let results = (outs I32:$result1, F32:$result2);
1273}
1274
1275def AnotherTwoResultOp : TEST_Op<"another_two_result"> {
1276  let arguments = (ins MultiResultOpEnum:$kind);
1277  let results = (outs F32:$result1, F32:$result2);
1278}
1279
1280def OneResultOp1 : TEST_Op<"one_result1"> {
1281  let arguments = (ins MultiResultOpEnum:$kind);
1282  let results = (outs F32:$result1);
1283}
1284
1285def OneResultOp2 : TEST_Op<"one_result2"> {
1286  let arguments = (ins MultiResultOpEnum:$kind);
1287  let results = (outs I32:$result1);
1288}
1289
1290def OneResultOp3 : TEST_Op<"one_result3"> {
1291  let arguments = (ins F32);
1292  let results = (outs I32:$result1);
1293}
1294
1295// Test using multi-result op as a whole
1296def : Pat<(ThreeResultOp MultiResultOpKind1:$kind),
1297          (AnotherThreeResultOp $kind)>;
1298
1299// Test using multi-result op as a whole for partial replacement
1300def : Pattern<(ThreeResultOp MultiResultOpKind2:$kind),
1301              [(TwoResultOp $kind),
1302               (OneResultOp1 $kind)]>;
1303def : Pattern<(ThreeResultOp MultiResultOpKind3:$kind),
1304              [(OneResultOp2 $kind),
1305               (AnotherTwoResultOp $kind)]>;
1306
1307// Test using results separately in a multi-result op
1308def : Pattern<(ThreeResultOp MultiResultOpKind4:$kind),
1309              [(TwoResultOp:$res1__0 $kind),
1310               (OneResultOp1 $kind),
1311               (TwoResultOp:$res2__1 $kind)]>;
1312
1313// Test referencing a single value in the value pack
1314// This rule only matches TwoResultOp if its second result has no use.
1315def : Pattern<(TwoResultOp:$res MultiResultOpKind5:$kind),
1316              [(OneResultOp2 $kind),
1317               (OneResultOp1 $kind)],
1318              [(HasNoUseOf:$res__1)]>;
1319
1320// Test using auxiliary ops for replacing multi-result op
1321def : Pattern<
1322    (ThreeResultOp MultiResultOpKind6:$kind), [
1323        // Auxiliary op generated to help building the final result but not
1324        // directly used to replace the source op's results.
1325        (TwoResultOp:$interm $kind),
1326
1327        (OneResultOp3 $interm__1),
1328        (AnotherTwoResultOp $kind)
1329    ]>;
1330
1331//===----------------------------------------------------------------------===//
1332// Test Patterns (Variadic Ops)
1333
1334def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> {
1335  let arguments = (ins Variadic<I32>);
1336  let results = (outs Variadic<I32>);
1337}
1338def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> {
1339  let arguments = (ins Variadic<I32>);
1340  let results = (outs Variadic<I32>);
1341}
1342
1343// Rewrite an op with one variadic operand and one variadic result to
1344// another similar op.
1345def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>;
1346
1347def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1",
1348                               [SameVariadicOperandSize]> {
1349  let arguments = (ins
1350    Variadic<I32>:$input1,
1351    F32:$input2,
1352    Variadic<I32>:$input3
1353  );
1354}
1355
1356def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2",
1357                               [SameVariadicOperandSize]> {
1358  let arguments = (ins
1359    Variadic<I32>:$input1,
1360    F32:$input2,
1361    Variadic<I32>:$input3
1362  );
1363}
1364
1365// Rewrite an op with both variadic operands and normal operands.
1366def : Pat<(MixedVOperandOp1 $input1, $input2, $input3),
1367          (MixedVOperandOp2 $input1, $input2, $input3)>;
1368
1369def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> {
1370  let results = (outs
1371    Variadic<I32>:$output1,
1372    F32:$output2,
1373    Variadic<I32>:$output3
1374  );
1375}
1376
1377def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> {
1378  let results = (outs
1379    Variadic<I32>:$output1,
1380    F32:$output2,
1381    Variadic<I32>:$output3
1382  );
1383}
1384
1385// Rewrite an op with both variadic results and normal results.
1386// Note that because we are generating the op with a top-level result pattern,
1387// we are able to deduce the correct result types for the generated op using
1388// the information from the matched root op.
1389def : Pat<(MixedVResultOp1), (MixedVResultOp2)>;
1390
1391def OneI32ResultOp : TEST_Op<"one_i32_out"> {
1392  let results = (outs I32);
1393}
1394
1395def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3",
1396                               [SameVariadicOperandSize]> {
1397  let arguments = (ins
1398    I32:$input1,
1399    Variadic<I32>:$input2,
1400    Variadic<I32>:$input3,
1401    I32Attr:$count
1402  );
1403
1404  let results = (outs I32);
1405}
1406
1407def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3",
1408                               [SameVariadicResultSize]> {
1409  let arguments = (ins I32Attr:$count);
1410
1411  let results = (outs
1412    I32:$output1,
1413    Variadic<I32>:$output2,
1414    Variadic<I32>:$output3
1415  );
1416
1417  // We will use this op in a nested result pattern, where we cannot deduce the
1418  // result type. So need to provide a builder not requiring result types.
1419  let builders = [
1420    OpBuilder<(ins "::mlir::IntegerAttr":$count),
1421    [{
1422      auto i32Type = $_builder.getIntegerType(32);
1423      $_state.addTypes(i32Type); // $output1
1424      SmallVector<Type, 4> types(count.getInt(), i32Type);
1425      $_state.addTypes(types); // $output2
1426      $_state.addTypes(types); // $output3
1427      $_state.addAttribute("count", count);
1428    }]>
1429  ];
1430}
1431
1432// Generates an op with variadic results using nested pattern.
1433def : Pat<(OneI32ResultOp),
1434          (MixedVOperandOp3
1435              (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">),
1436              (replaceWithValue $results__1),
1437              (replaceWithValue $results__2),
1438              ConstantAttr<I32Attr, "2">)>;
1439
1440//===----------------------------------------------------------------------===//
1441// Test Patterns (either)
1442
1443def TestEitherOpA : TEST_Op<"either_op_a"> {
1444  let arguments = (ins AnyInteger:$arg0, AnyInteger:$arg1, AnyInteger:$arg2);
1445  let results = (outs I32:$output);
1446}
1447
1448def TestEitherOpB : TEST_Op<"either_op_b"> {
1449  let arguments = (ins AnyInteger:$arg0);
1450  let results = (outs I32:$output);
1451}
1452
1453def : Pat<(TestEitherOpA (either I32:$arg1, I16:$arg2), $_),
1454          (TestEitherOpB $arg2)>;
1455
1456def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1), I16:$arg2), $_),
1457          (TestEitherOpB $arg2)>;
1458
1459def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1),
1460                                 (TestEitherOpB I16:$arg2)),
1461                          $_),
1462          (TestEitherOpB $arg2)>;
1463
1464//===----------------------------------------------------------------------===//
1465// Test Patterns (Location)
1466
1467// Test that we can specify locations for generated ops.
1468def : Pat<(TestLocationSrcOp:$res1
1469           (TestLocationSrcOp:$res2
1470            (TestLocationSrcOp:$res3 $input))),
1471          (TestLocationDstOp
1472            (TestLocationDstOp
1473              (TestLocationDstOp $input, (location $res1)),
1474              (location "named")),
1475            (location "fused", $res2, $res3))>;
1476
1477// Test that we can use the location of an op without results
1478def : Pat<(TestLocationSrcNoResOp:$loc
1479            (TestLocationSrcOp (TestLocationSrcOp $input))),
1480          (TestLocationDstNoResOp $input, (location $loc))>;
1481
1482//===----------------------------------------------------------------------===//
1483// Test Patterns (Type Builders)
1484
1485def SourceOp : TEST_Op<"source_op"> {
1486  let arguments = (ins AnyInteger:$arg, AnyI32Attr:$tag);
1487  let results = (outs AnyInteger);
1488}
1489
1490// An op without return type deduction.
1491def OpX : TEST_Op<"op_x"> {
1492  let arguments = (ins AnyInteger:$input);
1493  let results = (outs AnyInteger);
1494}
1495
1496// Test that ops without built-in type deduction can be created in the
1497// replacement DAG with an explicitly specified type.
1498def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "11">:$attr),
1499          (OpX (OpX $val, (returnType "$_builder.getI32Type()")))>;
1500// Test NativeCodeCall type builder can accept arguments.
1501def SameTypeAs : NativeCodeCall<"$0.getType()">;
1502
1503def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "22">:$attr),
1504          (OpX (OpX $val, (returnType (SameTypeAs $val))))>;
1505
1506// Test multiple return types.
1507def MakeI64Type : NativeCodeCall<"$_builder.getI64Type()">;
1508def MakeI32Type : NativeCodeCall<"$_builder.getI32Type()">;
1509
1510def OneToTwo : TEST_Op<"one_to_two"> {
1511  let arguments = (ins AnyInteger);
1512  let results = (outs AnyInteger, AnyInteger);
1513}
1514
1515def TwoToOne : TEST_Op<"two_to_one"> {
1516  let arguments = (ins AnyInteger, AnyInteger);
1517  let results = (outs AnyInteger);
1518}
1519
1520def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "33">:$attr),
1521          (TwoToOne (OpX (OneToTwo:$res__0 $val, (returnType (MakeI64Type), (MakeI32Type))), (returnType (MakeI32Type))),
1522                    (OpX $res__1, (returnType (MakeI64Type))))>;
1523
1524// Test copy value return type.
1525def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "44">:$attr),
1526          (OpX (OpX $val, (returnType $val)))>;
1527
1528// Test create multiple return types with different methods.
1529def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "55">:$attr),
1530          (TwoToOne (OneToTwo:$res__0 $val, (returnType $val, "$_builder.getI64Type()")), $res__1)>;
1531
1532//===----------------------------------------------------------------------===//
1533// Test Patterns (Trailing Directives)
1534
1535// Test that we can specify both `location` and `returnType` directives.
1536def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "66">:$attr),
1537          (TwoToOne (OpX $val, (returnType $val), (location "loc1")),
1538                    (OpX $val, (location "loc2"), (returnType $val)))>;
1539
1540//===----------------------------------------------------------------------===//
1541// Test Legalization
1542//===----------------------------------------------------------------------===//
1543
1544def Test_LegalizerEnum_Success : StrEnumAttrCase<"Success">;
1545def Test_LegalizerEnum_Failure : StrEnumAttrCase<"Failure">;
1546
1547def Test_LegalizerEnum : StrEnumAttr<"Success", "Failure",
1548  [Test_LegalizerEnum_Success, Test_LegalizerEnum_Failure]>;
1549
1550def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>;
1551def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>;
1552def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>;
1553def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>;
1554def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>;
1555def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>;
1556def ILLegalOpG : TEST_Op<"illegal_op_g">, Results<(outs I32)>;
1557def LegalOpA : TEST_Op<"legal_op_a">,
1558  Arguments<(ins Test_LegalizerEnum:$status)>, Results<(outs I32)>;
1559def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>;
1560def LegalOpC : TEST_Op<"legal_op_c">,
1561  Arguments<(ins I32)>, Results<(outs I32)>;
1562
1563// Check that the conversion infrastructure can properly undo the creation of
1564// operations where an operation was created before its parent, in this case,
1565// in the parent's builder.
1566def IllegalOpTerminator : TEST_Op<"illegal_op_terminator", [Terminator]>;
1567def IllegalOpWithRegion : TEST_Op<"illegal_op_with_region"> {
1568  let skipDefaultBuilders = 1;
1569  let builders = [OpBuilder<(ins),
1570    [{
1571       Region *bodyRegion = $_state.addRegion();
1572       OpBuilder::InsertionGuard g($_builder);
1573       Block *body = $_builder.createBlock(bodyRegion);
1574       $_builder.setInsertionPointToEnd(body);
1575       $_builder.create<IllegalOpTerminator>($_state.location);
1576    }]>];
1577}
1578def IllegalOpWithRegionAnchor : TEST_Op<"illegal_op_with_region_anchor">;
1579
1580// Check that smaller pattern depths are chosen, i.e. prioritize more direct
1581// mappings.
1582def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>;
1583
1584def : Pat<(ILLegalOpA), (ILLegalOpB)>;
1585def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>;
1586
1587// Check that the higher benefit pattern is taken for multiple legalizations
1588// with the same depth.
1589def : Pat<(ILLegalOpC), (ILLegalOpD)>;
1590def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>;
1591
1592def : Pat<(ILLegalOpC), (ILLegalOpE), [], (addBenefit 10)>;
1593def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>;
1594
1595// Check that patterns use the most up-to-date value when being replaced.
1596def TestRewriteOp : TEST_Op<"rewrite">,
1597  Arguments<(ins AnyType)>, Results<(outs AnyType)>;
1598def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>;
1599
1600// Check that patterns can specify bounded recursion when rewriting.
1601def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> {
1602  let arguments = (ins I64Attr:$depth);
1603  let assemblyFormat = "$depth attr-dict";
1604}
1605
1606// Test legalization pattern: this op will be erase and will also erase the
1607// producer of its operand.
1608def BlackHoleOp : TEST_Op<"blackhole">,
1609  Arguments<(ins AnyType)>;
1610
1611//===----------------------------------------------------------------------===//
1612// Test Type Legalization
1613//===----------------------------------------------------------------------===//
1614
1615def TestRegionBuilderOp : TEST_Op<"region_builder">;
1616def TestReturnOp : TEST_Op<"return", [ReturnLike, Terminator]> {
1617  let arguments = (ins Variadic<AnyType>);
1618  let builders = [OpBuilder<(ins),
1619    [{ build($_builder, $_state, {}); }]>
1620  ];
1621}
1622def TestCastOp : TEST_Op<"cast">,
1623  Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>;
1624def TestInvalidOp : TEST_Op<"invalid", [Terminator]>,
1625  Arguments<(ins Variadic<AnyType>)>;
1626def TestTypeProducerOp : TEST_Op<"type_producer">,
1627  Results<(outs AnyType)>;
1628def TestAnotherTypeProducerOp : TEST_Op<"another_type_producer">,
1629  Results<(outs AnyType)>;
1630def TestTypeConsumerOp : TEST_Op<"type_consumer">,
1631  Arguments<(ins AnyType)>;
1632def TestTypeChangerOp : TEST_Op<"type_changer">,
1633  Arguments<(ins AnyType)>, Results<(outs AnyType)>;
1634def TestValidOp : TEST_Op<"valid", [Terminator]>,
1635  Arguments<(ins Variadic<AnyType>)>;
1636
1637def TestMergeBlocksOp : TEST_Op<"merge_blocks"> {
1638  let summary = "merge_blocks operation";
1639  let description = [{
1640    Test op with multiple blocks that are merged with Dialect Conversion
1641  }];
1642
1643  let regions = (region AnyRegion:$body);
1644  let results = (outs Variadic<AnyType>:$result);
1645}
1646
1647def TestRemappedValueRegionOp : TEST_Op<"remapped_value_region",
1648                                        [SingleBlock]> {
1649  let summary = "remapped_value_region operation";
1650  let description = [{
1651    Test op that remaps values that haven't yet been converted in Dialect
1652    Conversion.
1653  }];
1654
1655  let regions = (region SizedRegion<1>:$body);
1656  let results = (outs Variadic<AnyType>:$result);
1657}
1658
1659def TestSignatureConversionUndoOp : TEST_Op<"signature_conversion_undo"> {
1660  let regions = (region AnyRegion);
1661}
1662
1663def TestSignatureConversionNoConverterOp
1664  : TEST_Op<"signature_conversion_no_converter"> {
1665  let regions = (region AnyRegion);
1666}
1667
1668//===----------------------------------------------------------------------===//
1669// Test parser.
1670//===----------------------------------------------------------------------===//
1671
1672def ParseIntegerLiteralOp : TEST_Op<"parse_integer_literal"> {
1673  let results = (outs Variadic<Index>:$results);
1674  let hasCustomAssemblyFormat = 1;
1675}
1676
1677def ParseWrappedKeywordOp : TEST_Op<"parse_wrapped_keyword"> {
1678  let arguments = (ins StrAttr:$keyword);
1679  let hasCustomAssemblyFormat = 1;
1680}
1681
1682//===----------------------------------------------------------------------===//
1683// Test region argument list parsing.
1684
1685def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> {
1686  let summary =  "isolated region operation";
1687  let description = [{
1688    Test op with an isolated region, to test passthrough region arguments. Each
1689    argument is of index type.
1690  }];
1691
1692  let arguments = (ins Index);
1693  let regions = (region SizedRegion<1>:$region);
1694  let hasCustomAssemblyFormat = 1;
1695}
1696
1697def SSACFGRegionOp : TEST_Op<"ssacfg_region",  [
1698    DeclareOpInterfaceMethods<RegionKindInterface>]> {
1699  let summary =  "operation with an SSACFG region";
1700  let description = [{
1701    Test op that defines an SSACFG region.
1702  }];
1703
1704  let regions = (region VariadicRegion<AnyRegion>:$regions);
1705  let arguments = (ins Variadic<AnyType>);
1706  let results = (outs Variadic<AnyType>);
1707}
1708
1709def GraphRegionOp : TEST_Op<"graph_region",  [
1710    DeclareOpInterfaceMethods<RegionKindInterface>]> {
1711  let summary =  "operation with a graph region";
1712  let description = [{
1713    Test op that defines a graph region.
1714  }];
1715
1716  let regions = (region AnyRegion:$region);
1717  let hasCustomAssemblyFormat = 1;
1718}
1719
1720def AffineScopeOp : TEST_Op<"affine_scope", [AffineScope]> {
1721  let summary =  "affine scope operation";
1722  let description = [{
1723    Test op that defines a new affine scope.
1724  }];
1725
1726  let regions = (region SizedRegion<1>:$region);
1727  let hasCustomAssemblyFormat = 1;
1728}
1729
1730def WrappingRegionOp : TEST_Op<"wrapping_region",
1731    [SingleBlockImplicitTerminator<"TestReturnOp">]> {
1732  let summary =  "wrapping region operation";
1733  let description = [{
1734    Test op wrapping another op in a region, to test calling
1735    parseGenericOperation from the custom parser.
1736  }];
1737
1738  let results = (outs Variadic<AnyType>);
1739  let regions = (region SizedRegion<1>:$region);
1740  let hasCustomAssemblyFormat = 1;
1741}
1742
1743def PrettyPrintedRegionOp : TEST_Op<"pretty_printed_region",
1744    [SingleBlockImplicitTerminator<"TestReturnOp">]> {
1745  let summary =  "pretty_printed_region operation";
1746  let description = [{
1747    Test-op can be printed either in a "pretty" or "non-pretty" way based on
1748    some criteria. The custom parser parsers both the versions while testing
1749    APIs: parseCustomOperationName & parseGenericOperationAfterOpName.
1750  }];
1751  let arguments = (ins
1752    AnyType:$input1,
1753    AnyType:$input2
1754  );
1755
1756  let results = (outs AnyType);
1757  let regions = (region SizedRegion<1>:$region);
1758  let hasCustomAssemblyFormat = 1;
1759}
1760
1761def PolyForOp : TEST_Op<"polyfor", [OpAsmOpInterface]> {
1762  let summary =  "polyfor operation";
1763  let description = [{
1764    Test op with multiple region arguments, each argument of index type.
1765  }];
1766  let extraClassDeclaration = [{
1767    void getAsmBlockArgumentNames(mlir::Region &region,
1768                                  mlir::OpAsmSetValueNameFn setNameFn);
1769  }];
1770  let regions = (region SizedRegion<1>:$region);
1771  let hasCustomAssemblyFormat = 1;
1772}
1773
1774//===----------------------------------------------------------------------===//
1775// Test OpAsmInterface.
1776
1777def AsmInterfaceOp : TEST_Op<"asm_interface_op"> {
1778  let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results,
1779                      AnyType);
1780}
1781
1782def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> {
1783  let results = (outs AnyType);
1784}
1785
1786//===----------------------------------------------------------------------===//
1787// Test Op Asm Format
1788//===----------------------------------------------------------------------===//
1789
1790def FormatLiteralOp : TEST_Op<"format_literal_op"> {
1791  let assemblyFormat = [{
1792    `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` `` `(` ` ` `)`
1793    `?` `+` `*` `{` `\n` `}` attr-dict
1794  }];
1795}
1796
1797// Test that we elide attributes that are within the syntax.
1798def FormatAttrOp : TEST_Op<"format_attr_op"> {
1799  let arguments = (ins I64Attr:$attr);
1800  let assemblyFormat = "$attr attr-dict";
1801}
1802
1803// Test that we elide optional attributes that are within the syntax.
1804def FormatOptAttrAOp : TEST_Op<"format_opt_attr_op_a"> {
1805  let arguments = (ins OptionalAttr<I64Attr>:$opt_attr);
1806  let assemblyFormat = "(`(` $opt_attr^ `)` )? attr-dict";
1807}
1808def FormatOptAttrBOp : TEST_Op<"format_opt_attr_op_b"> {
1809  let arguments = (ins OptionalAttr<I64Attr>:$opt_attr);
1810  let assemblyFormat = "($opt_attr^)? attr-dict";
1811}
1812
1813// Test that we format symbol name attributes properly.
1814def FormatSymbolNameAttrOp : TEST_Op<"format_symbol_name_attr_op"> {
1815  let arguments = (ins SymbolNameAttr:$attr);
1816  let assemblyFormat = "$attr attr-dict";
1817}
1818
1819// Test that we format optional symbol name attributes properly.
1820def FormatOptSymbolNameAttrOp : TEST_Op<"format_opt_symbol_name_attr_op"> {
1821  let arguments = (ins OptionalAttr<SymbolNameAttr>:$opt_attr);
1822  let assemblyFormat = "($opt_attr^)? attr-dict";
1823}
1824
1825// Test that we elide attributes that are within the syntax.
1826def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> {
1827  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$opt_attr);
1828  let assemblyFormat = "attr-dict-with-keyword";
1829}
1830
1831// Test that we don't need to provide types in the format if they are buildable.
1832def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> {
1833  let arguments = (ins I64:$buildable);
1834  let results = (outs I64:$buildable_res);
1835  let assemblyFormat = "$buildable attr-dict";
1836}
1837
1838// Test various mixings of region formatting.
1839class FormatRegionBase<string suffix, string fmt>
1840    : TEST_Op<"format_region_" # suffix # "_op"> {
1841  let regions = (region AnyRegion:$region);
1842  let assemblyFormat = fmt;
1843}
1844def FormatRegionAOp : FormatRegionBase<"a", [{
1845  regions attr-dict
1846}]>;
1847def FormatRegionBOp : FormatRegionBase<"b", [{
1848  $region attr-dict
1849}]>;
1850def FormatRegionCOp : FormatRegionBase<"c", [{
1851  (`region` $region^)? attr-dict
1852}]>;
1853class FormatVariadicRegionBase<string suffix, string fmt>
1854    : TEST_Op<"format_variadic_region_" # suffix # "_op"> {
1855  let regions = (region VariadicRegion<AnyRegion>:$regions);
1856  let assemblyFormat = fmt;
1857}
1858def FormatVariadicRegionAOp : FormatVariadicRegionBase<"a", [{
1859  $regions attr-dict
1860}]>;
1861def FormatVariadicRegionBOp : FormatVariadicRegionBase<"b", [{
1862  ($regions^ `found_regions`)? attr-dict
1863}]>;
1864class FormatRegionImplicitTerminatorBase<string suffix, string fmt>
1865    : TEST_Op<"format_implicit_terminator_region_" # suffix # "_op",
1866              [SingleBlockImplicitTerminator<"TestReturnOp">]> {
1867  let regions = (region AnyRegion:$region);
1868  let assemblyFormat = fmt;
1869}
1870def FormatFormatRegionImplicitTerminatorAOp
1871    : FormatRegionImplicitTerminatorBase<"a", [{
1872  $region attr-dict
1873}]>;
1874
1875// Test various mixings of result type formatting.
1876class FormatResultBase<string suffix, string fmt>
1877    : TEST_Op<"format_result_" # suffix # "_op"> {
1878  let results = (outs I64:$buildable_res, AnyMemRef:$result);
1879  let assemblyFormat = fmt;
1880}
1881def FormatResultAOp : FormatResultBase<"a", [{
1882  type($result) attr-dict
1883}]>;
1884def FormatResultBOp : FormatResultBase<"b", [{
1885  type(results) attr-dict
1886}]>;
1887def FormatResultCOp : FormatResultBase<"c", [{
1888  functional-type($buildable_res, $result) attr-dict
1889}]>;
1890
1891def FormatVariadicResult : TEST_Op<"format_variadic_result"> {
1892  let results = (outs Variadic<I64>:$result);
1893  let assemblyFormat = [{ `:` type($result) attr-dict}];
1894}
1895
1896def FormatMultipleVariadicResults : TEST_Op<"format_multiple_variadic_results",
1897                                            [AttrSizedResultSegments]> {
1898  let results = (outs Variadic<I64>:$result0, Variadic<AnyType>:$result1);
1899  let assemblyFormat = [{
1900    `:` `(` type($result0) `)` `,` `(` type($result1) `)` attr-dict
1901  }];
1902}
1903
1904// Test various mixings of operand type formatting.
1905class FormatOperandBase<string suffix, string fmt>
1906    : TEST_Op<"format_operand_" # suffix # "_op"> {
1907  let arguments = (ins I64:$buildable, AnyMemRef:$operand);
1908  let assemblyFormat = fmt;
1909}
1910
1911def FormatOperandAOp : FormatOperandBase<"a", [{
1912  operands `:` type(operands) attr-dict
1913}]>;
1914def FormatOperandBOp : FormatOperandBase<"b", [{
1915  operands `:` type($operand) attr-dict
1916}]>;
1917def FormatOperandCOp : FormatOperandBase<"c", [{
1918  $buildable `,` $operand `:` type(operands) attr-dict
1919}]>;
1920def FormatOperandDOp : FormatOperandBase<"d", [{
1921  $buildable `,` $operand `:` type($operand) attr-dict
1922}]>;
1923def FormatOperandEOp : FormatOperandBase<"e", [{
1924  $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict
1925}]>;
1926
1927def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> {
1928  let successors = (successor VariadicSuccessor<AnySuccessor>:$targets);
1929  let assemblyFormat = "$targets attr-dict";
1930}
1931
1932def FormatVariadicOperand : TEST_Op<"format_variadic_operand"> {
1933  let arguments = (ins Variadic<I64>:$operand);
1934  let assemblyFormat = [{ $operand `:` type($operand) attr-dict}];
1935}
1936def FormatVariadicOfVariadicOperand
1937   : TEST_Op<"format_variadic_of_variadic_operand"> {
1938  let arguments = (ins
1939    VariadicOfVariadic<I64, "operand_segments">:$operand,
1940    I32ElementsAttr:$operand_segments
1941  );
1942  let assemblyFormat = [{ $operand `:` type($operand) attr-dict}];
1943}
1944
1945def FormatMultipleVariadicOperands :
1946    TEST_Op<"format_multiple_variadic_operands", [AttrSizedOperandSegments]> {
1947  let arguments = (ins Variadic<I64>:$operand0, Variadic<AnyType>:$operand1);
1948  let assemblyFormat = [{
1949    ` ` `(` $operand0 `)` `,` `(` $operand1 `:` type($operand1) `)` attr-dict
1950  }];
1951}
1952
1953// Test various mixings of optional operand and result type formatting.
1954class FormatOptionalOperandResultOpBase<string suffix, string fmt>
1955    : TEST_Op<"format_optional_operand_result_" # suffix # "_op",
1956              [AttrSizedOperandSegments]> {
1957  let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic);
1958  let results = (outs Optional<I64>:$optional_res);
1959  let assemblyFormat = fmt;
1960}
1961
1962def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{
1963  `(` $optional `:` type($optional) `)` `:` type($optional_res)
1964  (`[` $variadic^ `]`)? attr-dict
1965}]>;
1966
1967def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{
1968  (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res)
1969  (`[` $variadic^ `]`)? attr-dict
1970}]>;
1971
1972// Test optional result type formatting.
1973class FormatOptionalResultOpBase<string suffix, string fmt>
1974    : TEST_Op<"format_optional_result_" # suffix # "_op",
1975              [AttrSizedResultSegments]> {
1976  let results = (outs Optional<I64>:$optional, Variadic<I64>:$variadic);
1977  let assemblyFormat = fmt;
1978}
1979def FormatOptionalResultAOp : FormatOptionalResultOpBase<"a", [{
1980  (`:` type($optional)^ `->` type($variadic))? attr-dict
1981}]>;
1982
1983def FormatOptionalResultBOp : FormatOptionalResultOpBase<"b", [{
1984  (`:` type($optional) `->` type($variadic)^)? attr-dict
1985}]>;
1986
1987def FormatOptionalResultCOp : FormatOptionalResultOpBase<"c", [{
1988  (`:` functional-type($optional, $variadic)^)? attr-dict
1989}]>;
1990
1991def FormatOptionalResultDOp
1992  : TEST_Op<"format_optional_result_d_op" > {
1993  let results = (outs Optional<F80>:$optional);
1994  let assemblyFormat = "(`:` type($optional)^)? attr-dict";
1995}
1996
1997def FormatTwoVariadicOperandsNoBuildableTypeOp
1998    : TEST_Op<"format_two_variadic_operands_no_buildable_type_op",
1999              [AttrSizedOperandSegments]> {
2000  let arguments = (ins Variadic<AnyType>:$a,
2001                       Variadic<AnyType>:$b);
2002  let assemblyFormat = [{
2003    `(` $a `:` type($a) `)` `->` `(` $b `:` type($b) `)`  attr-dict
2004  }];
2005}
2006
2007def FormatInferVariadicTypeFromNonVariadic
2008    : TEST_Op<"format_infer_variadic_type_from_non_variadic",
2009              [SameOperandsAndResultType]> {
2010  let arguments = (ins Variadic<AnyType>:$args);
2011  let results = (outs AnyType:$result);
2012  let assemblyFormat = "$args attr-dict `:` type($result)";
2013}
2014
2015def FormatOptionalUnitAttr : TEST_Op<"format_optional_unit_attribute"> {
2016  let arguments = (ins UnitAttr:$is_optional);
2017  let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict";
2018}
2019
2020def FormatOptionalUnitAttrNoElide
2021    : TEST_Op<"format_optional_unit_attribute_no_elide"> {
2022  let arguments = (ins UnitAttr:$is_optional);
2023  let assemblyFormat = "($is_optional^)? attr-dict";
2024}
2025
2026def FormatOptionalEnumAttr : TEST_Op<"format_optional_enum_attr"> {
2027  let arguments = (ins OptionalAttr<SomeI64Enum>:$attr);
2028  let assemblyFormat = "($attr^)? attr-dict";
2029}
2030
2031def FormatOptionalWithElse : TEST_Op<"format_optional_else"> {
2032  let arguments = (ins UnitAttr:$isFirstBranchPresent);
2033  let assemblyFormat = "(`then` $isFirstBranchPresent^):(`else`)? attr-dict";
2034}
2035
2036def FormatCompoundAttr : TEST_Op<"format_compound_attr"> {
2037  let arguments = (ins CompoundAttrA:$compound);
2038  let assemblyFormat = "$compound attr-dict-with-keyword";
2039}
2040
2041def FormatNestedAttr : TEST_Op<"format_nested_attr"> {
2042  let arguments = (ins CompoundAttrNested:$nested);
2043  let assemblyFormat = "$nested attr-dict-with-keyword";
2044}
2045
2046def FormatNestedCompoundAttr : TEST_Op<"format_cpmd_nested_attr"> {
2047  let arguments = (ins CompoundNestedOuter:$nested);
2048  let assemblyFormat = "`nested` $nested attr-dict-with-keyword";
2049}
2050
2051def FormatQualifiedCompoundAttr : TEST_Op<"format_qual_cpmd_nested_attr"> {
2052  let arguments = (ins CompoundNestedOuter:$nested);
2053  let assemblyFormat = "`nested` qualified($nested) attr-dict-with-keyword";
2054}
2055
2056def FormatNestedType : TEST_Op<"format_cpmd_nested_type"> {
2057  let arguments = (ins CompoundNestedOuterType:$nested);
2058  let assemblyFormat = "$nested `nested` type($nested) attr-dict-with-keyword";
2059}
2060
2061def FormatQualifiedNestedType : TEST_Op<"format_qual_cpmd_nested_type"> {
2062  let arguments = (ins CompoundNestedOuterType:$nested);
2063  let assemblyFormat = "$nested `nested` qualified(type($nested)) attr-dict-with-keyword";
2064}
2065
2066//===----------------------------------------------------------------------===//
2067// Custom Directives
2068
2069def FormatCustomDirectiveOperands
2070    : TEST_Op<"format_custom_directive_operands", [AttrSizedOperandSegments]> {
2071  let arguments = (ins I64:$operand, Optional<I64>:$optOperand,
2072                       Variadic<I64>:$varOperands);
2073  let assemblyFormat = [{
2074    custom<CustomDirectiveOperands>(
2075      $operand, $optOperand, $varOperands
2076    )
2077    attr-dict
2078  }];
2079}
2080
2081def FormatCustomDirectiveOperandsAndTypes
2082    : TEST_Op<"format_custom_directive_operands_and_types",
2083              [AttrSizedOperandSegments]> {
2084  let arguments = (ins AnyType:$operand, Optional<AnyType>:$optOperand,
2085                       Variadic<AnyType>:$varOperands);
2086  let assemblyFormat = [{
2087    custom<CustomDirectiveOperandsAndTypes>(
2088      $operand, $optOperand, $varOperands,
2089      type($operand), type($optOperand), type($varOperands)
2090    )
2091    attr-dict
2092  }];
2093}
2094
2095def FormatCustomDirectiveRegions : TEST_Op<"format_custom_directive_regions"> {
2096  let regions = (region AnyRegion:$region, VariadicRegion<AnyRegion>:$other_regions);
2097  let assemblyFormat = [{
2098    custom<CustomDirectiveRegions>(
2099      $region, $other_regions
2100    )
2101    attr-dict
2102  }];
2103}
2104
2105def FormatCustomDirectiveResults
2106    : TEST_Op<"format_custom_directive_results", [AttrSizedResultSegments]> {
2107  let results = (outs AnyType:$result, Optional<AnyType>:$optResult,
2108                      Variadic<AnyType>:$varResults);
2109  let assemblyFormat = [{
2110    custom<CustomDirectiveResults>(
2111      type($result), type($optResult), type($varResults)
2112    )
2113    attr-dict
2114  }];
2115}
2116
2117def FormatCustomDirectiveResultsWithTypeRefs
2118    : TEST_Op<"format_custom_directive_results_with_type_refs",
2119              [AttrSizedResultSegments]> {
2120  let results = (outs AnyType:$result, Optional<AnyType>:$optResult,
2121                      Variadic<AnyType>:$varResults);
2122  let assemblyFormat = [{
2123    custom<CustomDirectiveResults>(
2124      type($result), type($optResult), type($varResults)
2125    )
2126    custom<CustomDirectiveWithTypeRefs>(
2127      ref(type($result)), ref(type($optResult)), ref(type($varResults))
2128    )
2129    attr-dict
2130  }];
2131}
2132
2133def FormatCustomDirectiveWithOptionalOperandRef
2134    : TEST_Op<"format_custom_directive_with_optional_operand_ref"> {
2135  let arguments = (ins Optional<I64>:$optOperand);
2136  let assemblyFormat = [{
2137    ($optOperand^)? `:`
2138    custom<CustomDirectiveOptionalOperandRef>(ref($optOperand))
2139    attr-dict
2140  }];
2141}
2142
2143def FormatCustomDirectiveSuccessors
2144    : TEST_Op<"format_custom_directive_successors", [Terminator]> {
2145  let successors = (successor AnySuccessor:$successor,
2146                              VariadicSuccessor<AnySuccessor>:$successors);
2147  let assemblyFormat = [{
2148    custom<CustomDirectiveSuccessors>(
2149      $successor, $successors
2150    )
2151    attr-dict
2152  }];
2153}
2154
2155def FormatCustomDirectiveAttributes
2156    : TEST_Op<"format_custom_directive_attributes"> {
2157  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr);
2158  let assemblyFormat = [{
2159    custom<CustomDirectiveAttributes>(
2160      $attr, $optAttr
2161    )
2162    attr-dict
2163  }];
2164}
2165
2166def FormatCustomDirectiveAttrDict
2167    : TEST_Op<"format_custom_directive_attrdict"> {
2168  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr);
2169  let assemblyFormat = [{
2170    custom<CustomDirectiveAttrDict>( attr-dict )
2171  }];
2172}
2173
2174//===----------------------------------------------------------------------===//
2175// AllTypesMatch type inference
2176
2177def FormatAllTypesMatchVarOp : TEST_Op<"format_all_types_match_var", [
2178    AllTypesMatch<["value1", "value2", "result"]>
2179  ]> {
2180  let arguments = (ins AnyType:$value1, AnyType:$value2);
2181  let results = (outs AnyType:$result);
2182  let assemblyFormat = "attr-dict $value1 `,` $value2 `:` type($value1)";
2183}
2184
2185def FormatAllTypesMatchAttrOp : TEST_Op<"format_all_types_match_attr", [
2186    AllTypesMatch<["value1", "value2", "result"]>
2187  ]> {
2188  let arguments = (ins AnyAttr:$value1, AnyType:$value2);
2189  let results = (outs AnyType:$result);
2190  let assemblyFormat = "attr-dict $value1 `,` $value2";
2191}
2192
2193//===----------------------------------------------------------------------===//
2194// TypesMatchWith type inference
2195
2196def FormatTypesMatchVarOp : TEST_Op<"format_types_match_var", [
2197    TypesMatchWith<"result type matches operand", "value", "result", "$_self">
2198  ]> {
2199  let arguments = (ins AnyType:$value);
2200  let results = (outs AnyType:$result);
2201  let assemblyFormat = "attr-dict $value `:` type($value)";
2202}
2203
2204def FormatTypesMatchVariadicOp : TEST_Op<"format_types_match_variadic", [
2205    RangedTypesMatchWith<"result type matches operand", "value", "result",
2206                         "llvm::make_range($_self.begin(), $_self.end())">
2207  ]> {
2208  let arguments = (ins Variadic<AnyType>:$value);
2209  let results = (outs Variadic<AnyType>:$result);
2210  let assemblyFormat = "attr-dict $value `:` type($value)";
2211}
2212
2213def FormatTypesMatchAttrOp : TEST_Op<"format_types_match_attr", [
2214    TypesMatchWith<"result type matches constant", "value", "result", "$_self">
2215  ]> {
2216  let arguments = (ins AnyAttr:$value);
2217  let results = (outs AnyType:$result);
2218  let assemblyFormat = "attr-dict $value";
2219}
2220
2221def FormatTypesMatchContextOp : TEST_Op<"format_types_match_context", [
2222    TypesMatchWith<"tuple result type matches operand type", "value", "result",
2223        "::mlir::TupleType::get($_ctxt, $_self)">
2224  ]> {
2225  let arguments = (ins AnyType:$value);
2226  let results = (outs AnyType:$result);
2227  let assemblyFormat = "attr-dict $value `:` type($value)";
2228}
2229
2230//===----------------------------------------------------------------------===//
2231// InferTypeOpInterface type inference in assembly format
2232
2233def FormatInferTypeOp : TEST_Op<"format_infer_type", [InferTypeOpInterface]> {
2234  let results = (outs AnyType);
2235  let assemblyFormat = "attr-dict";
2236
2237  let extraClassDeclaration = [{
2238    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2239          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2240          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2241          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2242      inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)});
2243      return ::mlir::success();
2244    }
2245   }];
2246}
2247
2248// Check that formatget supports DeclareOpInterfaceMethods.
2249def FormatInferType2Op : TEST_Op<"format_infer_type2", [DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
2250  let results = (outs AnyType);
2251  let assemblyFormat = "attr-dict";
2252}
2253
2254// Base class for testing mixing allOperandTypes, allOperands, and
2255// inferResultTypes.
2256class FormatInferAllTypesBaseOp<string mnemonic, list<Trait> traits = []>
2257    : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> {
2258  let arguments = (ins Variadic<AnyType>:$args);
2259  let results = (outs Variadic<AnyType>:$outs);
2260  let extraClassDeclaration = [{
2261    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2262          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2263          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2264          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2265      ::mlir::TypeRange operandTypes = operands.getTypes();
2266      inferredReturnTypes.assign(operandTypes.begin(), operandTypes.end());
2267      return ::mlir::success();
2268    }
2269   }];
2270}
2271
2272// Test inferReturnTypes is called when allOperandTypes and allOperands is true.
2273def FormatInferTypeAllOperandsAndTypesOp
2274    : FormatInferAllTypesBaseOp<"format_infer_type_all_operands_and_types"> {
2275  let assemblyFormat = "`(` operands `)` attr-dict `:` type(operands)";
2276}
2277
2278// Test inferReturnTypes is called when allOperandTypes is true and there is one
2279// ODS operand.
2280def FormatInferTypeAllOperandsAndTypesOneOperandOp
2281    : FormatInferAllTypesBaseOp<"format_infer_type_all_types_one_operand"> {
2282  let assemblyFormat = "`(` $args `)` attr-dict `:` type(operands)";
2283}
2284
2285// Test inferReturnTypes is called when allOperandTypes is true and there are
2286// more than one ODS operands.
2287def FormatInferTypeAllOperandsAndTypesTwoOperandsOp
2288    : FormatInferAllTypesBaseOp<"format_infer_type_all_types_two_operands",
2289                                [SameVariadicOperandSize]> {
2290  let arguments = (ins Variadic<AnyType>:$args0, Variadic<AnyType>:$args1);
2291  let assemblyFormat = "`(` $args0 `)` `(` $args1 `)` attr-dict `:` type(operands)";
2292}
2293
2294// Test inferReturnTypes is called when allOperands is true and operand types
2295// are separately specified.
2296def FormatInferTypeAllTypesOp
2297    : FormatInferAllTypesBaseOp<"format_infer_type_all_types"> {
2298  let assemblyFormat = "`(` operands `)` attr-dict `:` type($args)";
2299}
2300
2301// Test inferReturnTypes coupled with regions.
2302def FormatInferTypeRegionsOp
2303    : TEST_Op<"format_infer_type_regions", [InferTypeOpInterface]> {
2304  let results = (outs Variadic<AnyType>:$outs);
2305  let regions = (region AnyRegion:$region);
2306  let assemblyFormat = "$region attr-dict";
2307  let extraClassDeclaration = [{
2308    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2309          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2310          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2311          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2312      if (regions.empty())
2313        return ::mlir::failure();
2314      auto types = regions.front()->getArgumentTypes();
2315      inferredReturnTypes.assign(types.begin(), types.end());
2316      return ::mlir::success();
2317    }
2318  }];
2319}
2320
2321// Test inferReturnTypes coupled with variadic operands (operand_segment_sizes).
2322def FormatInferTypeVariadicOperandsOp
2323    : TEST_Op<"format_infer_type_variadic_operands",
2324              [InferTypeOpInterface, AttrSizedOperandSegments]> {
2325  let arguments = (ins Variadic<I32>:$a, Variadic<I64>:$b);
2326  let results = (outs Variadic<AnyType>:$outs);
2327  let assemblyFormat = "`(` $a `:` type($a) `)` `(` $b `:` type($b) `)` attr-dict";
2328  let extraClassDeclaration = [{
2329    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2330          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2331          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2332          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2333      FormatInferTypeVariadicOperandsOpAdaptor adaptor(operands, attributes);
2334      auto aTypes = adaptor.getA().getTypes();
2335      auto bTypes = adaptor.getB().getTypes();
2336      inferredReturnTypes.append(aTypes.begin(), aTypes.end());
2337      inferredReturnTypes.append(bTypes.begin(), bTypes.end());
2338      return ::mlir::success();
2339    }
2340  }];
2341}
2342
2343//===----------------------------------------------------------------------===//
2344// Test SideEffects
2345//===----------------------------------------------------------------------===//
2346
2347def SideEffectOp : TEST_Op<"side_effect_op",
2348    [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
2349     DeclareOpInterfaceMethods<TestEffectOpInterface>]> {
2350  let results = (outs AnyType:$result);
2351}
2352
2353//===----------------------------------------------------------------------===//
2354// Test CopyOpInterface
2355//===----------------------------------------------------------------------===//
2356
2357def CopyOp : TEST_Op<"copy", [CopyOpInterface]> {
2358  let description = [{
2359    Represents a copy operation.
2360  }];
2361  let arguments = (ins Res<AnyRankedOrUnrankedMemRef, "", [MemRead]>:$source,
2362                   Res<AnyRankedOrUnrankedMemRef, "", [MemWrite]>:$target);
2363  let assemblyFormat = [{
2364    `(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)`
2365     attr-dict
2366  }];
2367}
2368
2369//===----------------------------------------------------------------------===//
2370// Test Buffer/Tensor
2371//===----------------------------------------------------------------------===//
2372
2373def RegionYieldOp : TEST_Op<"region_yield",
2374      [NoSideEffect, ReturnLike, Terminator]> {
2375  let description = [{
2376    This operation is used in a region and yields the corresponding type for
2377    that operation.
2378  }];
2379  let arguments = (ins AnyType:$result);
2380  let assemblyFormat = [{
2381    $result `:` type($result) attr-dict
2382  }];
2383  let builders = [OpBuilder<(ins),
2384    [{ build($_builder, $_state, {}); }]>
2385  ];
2386}
2387
2388class BufferBasedOpBase<string mnemonic, list<Trait> traits>
2389    : TEST_Op<mnemonic, traits> {
2390  let description = [{
2391    A buffer based operation, that uses memRefs as input and output.
2392  }];
2393  let arguments = (ins AnyRankedOrUnrankedMemRef:$input,
2394                       AnyRankedOrUnrankedMemRef:$output);
2395}
2396
2397def BufferBasedOp : BufferBasedOpBase<"buffer_based", []>{
2398  let assemblyFormat = [{
2399    `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`
2400    attr-dict
2401  }];
2402}
2403
2404def RegionBufferBasedOp : BufferBasedOpBase<"region_buffer_based",
2405      [SingleBlockImplicitTerminator<"RegionYieldOp">]> {
2406  let regions = (region AnyRegion:$region);
2407  let assemblyFormat = [{
2408    `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`
2409    $region attr-dict
2410  }];
2411}
2412
2413def TensorBasedOp : TEST_Op<"tensor_based", []> {
2414  let description = [{
2415    A tensor based operation, that uses a tensor as an input and results in a
2416    tensor again.
2417  }];
2418  let arguments = (ins AnyRankedTensor:$input);
2419  let results = (outs AnyRankedTensor:$result);
2420  let assemblyFormat = [{
2421    `in` `(` $input`:` type($input) `)` `->` type($result) attr-dict
2422  }];
2423}
2424
2425//===----------------------------------------------------------------------===//
2426// Test RegionBranchOpInterface
2427//===----------------------------------------------------------------------===//
2428
2429def RegionIfYieldOp : TEST_Op<"region_if_yield",
2430      [NoSideEffect, ReturnLike, Terminator]> {
2431  let arguments = (ins Variadic<AnyType>:$results);
2432  let assemblyFormat = [{
2433    $results `:` type($results) attr-dict
2434  }];
2435}
2436
2437def RegionIfOp : TEST_Op<"region_if",
2438      [DeclareOpInterfaceMethods<RegionBranchOpInterface,
2439                                 ["getRegionInvocationBounds"]>,
2440       SingleBlockImplicitTerminator<"RegionIfYieldOp">,
2441       RecursiveSideEffects]> {
2442  let description =[{
2443    Represents an abstract if-then-else-join pattern. In this context, the then
2444    and else regions jump to the join region, which finally returns to its
2445    parent op.
2446  }];
2447
2448  let arguments = (ins Variadic<AnyType>);
2449  let results = (outs Variadic<AnyType>:$results);
2450  let regions = (region SizedRegion<1>:$thenRegion,
2451                        AnyRegion:$elseRegion,
2452                        AnyRegion:$joinRegion);
2453  let extraClassDeclaration = [{
2454    ::mlir::Block::BlockArgListType getThenArgs() {
2455      return getBody(0)->getArguments();
2456    }
2457    ::mlir::Block::BlockArgListType getElseArgs() {
2458      return getBody(1)->getArguments();
2459    }
2460    ::mlir::Block::BlockArgListType getJoinArgs() {
2461      return getBody(2)->getArguments();
2462    }
2463    ::mlir::OperandRange getSuccessorEntryOperands(unsigned index);
2464  }];
2465  let hasCustomAssemblyFormat = 1;
2466}
2467
2468def AnyCondOp : TEST_Op<"any_cond",
2469      [DeclareOpInterfaceMethods<RegionBranchOpInterface,
2470                                 ["getRegionInvocationBounds"]>,
2471       RecursiveSideEffects]> {
2472  let results = (outs Variadic<AnyType>:$results);
2473  let regions = (region AnyRegion:$region);
2474}
2475
2476//===----------------------------------------------------------------------===//
2477// Test TableGen generated build() methods
2478//===----------------------------------------------------------------------===//
2479
2480def TableGenConstant : TEST_Op<"tblgen_constant"> {
2481  let results = (outs AnyType);
2482}
2483
2484// No variadic args or results.
2485def TableGenBuildOp0 : TEST_Op<"tblgen_build_0"> {
2486  let arguments = (ins AnyType:$value);
2487  let results = (outs AnyType:$result);
2488}
2489
2490// Sigle variadic arg and single variadic results.
2491def TableGenBuildOp1 : TEST_Op<"tblgen_build_1"> {
2492  let arguments = (ins Variadic<AnyType>:$inputs);
2493  let results = (outs Variadic<AnyType>:$results);
2494}
2495
2496// Single variadic arg and non-variadic results.
2497def TableGenBuildOp2 : TEST_Op<"tblgen_build_2"> {
2498  let arguments = (ins Variadic<AnyType>:$inputs);
2499  let results = (outs AnyType:$result);
2500}
2501
2502// Single variadic arg and multiple variadic results.
2503def TableGenBuildOp3 : TEST_Op<"tblgen_build_3", [SameVariadicResultSize]> {
2504  let arguments = (ins Variadic<AnyType>:$inputs);
2505  let results = (outs Variadic<AnyType>:$resultA, Variadic<AnyType>:$resultB);
2506}
2507
2508// Single variadic arg, non variadic results, with SameOperandsAndResultType.
2509// Tests suppression of ambiguous build methods for operations with
2510// SameOperandsAndResultType trait.
2511def TableGenBuildOp4 : TEST_Op<"tblgen_build_4", [SameOperandsAndResultType]> {
2512  let arguments = (ins Variadic<AnyType>:$inputs);
2513  let results = (outs AnyType:$result);
2514}
2515
2516// Base class for testing `build` methods for ops with
2517// InferReturnTypeOpInterface.
2518class TableGenBuildInferReturnTypeBaseOp<string mnemonic,
2519                                         list<Trait> traits = []>
2520    : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> {
2521  let arguments = (ins Variadic<AnyType>:$inputs);
2522  let results = (outs AnyType:$result);
2523
2524  let extraClassDeclaration = [{
2525    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *,
2526          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2527          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2528          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2529      inferredReturnTypes.assign({operands[0].getType()});
2530      return ::mlir::success();
2531    }
2532   }];
2533}
2534
2535// Single variadic arg with SameOperandsAndResultType and InferTypeOpInterface.
2536// Tests suppression of ambiguous build methods for operations with
2537// SameOperandsAndResultType and InferTypeOpInterface.
2538def TableGenBuildOp5 : TableGenBuildInferReturnTypeBaseOp<
2539    "tblgen_build_5", [SameOperandsAndResultType]>;
2540
2541// Op with InferTypeOpInterface and regions.
2542def TableGenBuildOp6 : TableGenBuildInferReturnTypeBaseOp<
2543    "tblgen_build_6", [InferTypeOpInterface]> {
2544  let regions = (region AnyRegion:$body);
2545}
2546
2547//===----------------------------------------------------------------------===//
2548// Test BufferPlacement
2549//===----------------------------------------------------------------------===//
2550
2551def GetTupleElementOp: TEST_Op<"get_tuple_element"> {
2552  let description = [{
2553    Test op that returns a specified element of the tuple.
2554  }];
2555
2556  let arguments = (ins
2557    TupleOf<[AnyType]>,
2558    I32Attr:$index
2559  );
2560  let results = (outs AnyType);
2561}
2562
2563def MakeTupleOp: TEST_Op<"make_tuple"> {
2564  let description = [{
2565    Test op that creates a tuple value from a list of values.
2566  }];
2567
2568  let arguments = (ins
2569    Variadic<AnyType>:$inputs
2570  );
2571  let results = (outs TupleOf<[AnyType]>);
2572}
2573
2574//===----------------------------------------------------------------------===//
2575// Test Target DataLayout
2576//===----------------------------------------------------------------------===//
2577
2578def OpWithDataLayoutOp : TEST_Op<"op_with_data_layout",
2579                                 [HasDefaultDLTIDataLayout, DataLayoutOpInterface]> {
2580  let summary =
2581      "An op that uses DataLayout implementation from the Target dialect";
2582  let regions = (region VariadicRegion<AnyRegion>:$regions);
2583}
2584
2585def DataLayoutQueryOp : TEST_Op<"data_layout_query"> {
2586  let summary = "A token op recognized by data layout query test pass";
2587  let description = [{
2588    The data layout query pass pattern-matches this op and attaches to it an
2589    array attribute containing the result of data layout query of the result
2590    type of this op.
2591  }];
2592
2593  let results = (outs AnyType:$res);
2594}
2595
2596//===----------------------------------------------------------------------===//
2597// Test Reducer Patterns
2598//===----------------------------------------------------------------------===//
2599
2600def OpCrashLong : TEST_Op<"op_crash_long"> {
2601  let arguments = (ins I32, I32, I32);
2602  let results = (outs I32);
2603}
2604
2605def OpCrashShort : TEST_Op<"op_crash_short"> {
2606  let results = (outs I32);
2607}
2608
2609def : Pat<(OpCrashLong $_, $_, $_), (OpCrashShort)>;
2610
2611//===----------------------------------------------------------------------===//
2612// Test LinalgConvolutionOpInterface.
2613//===----------------------------------------------------------------------===//
2614
2615def TestLinalgConvOpNotLinalgOp : TEST_Op<"conv_op_not_linalg_op", [
2616    LinalgConvolutionOpInterface]> {
2617  let arguments = (ins
2618    AnyType:$image, AnyType:$filter, AnyType:$output);
2619  let results = (outs AnyRankedTensor:$result);
2620}
2621
2622def TestLinalgConvOp :
2623  TEST_Op<"linalg_conv_op", [AttrSizedOperandSegments, SingleBlock,
2624      LinalgStructuredInterface, LinalgConvolutionOpInterface]> {
2625
2626  let arguments = (ins Variadic<AnyType>:$inputs,
2627    Variadic<AnyType>:$outputs);
2628  let results = (outs Variadic<AnyType>:$results);
2629  let regions = (region AnyRegion:$region);
2630
2631  let assemblyFormat = [{
2632    attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?
2633    `outs` `(` $outputs `:` type($outputs) `)`
2634    $region (`->` type($results)^)?
2635  }];
2636
2637  let extraClassDeclaration = [{
2638    bool hasIndexSemantics() { return false; }
2639
2640    static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,
2641                              mlir::ArrayRef<mlir::NamedAttribute> attrs) {
2642      b.create<mlir::linalg::YieldOp>(block.getArguments().back());
2643    }
2644
2645    static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,
2646                              mlir::ArrayRef<mlir::NamedAttribute>)>
2647    getRegionBuilder() {
2648      return &regionBuilder;
2649    }
2650
2651    mlir::ArrayAttr iterator_types() {
2652      return getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");
2653    }
2654
2655    mlir::ArrayAttr indexing_maps() {
2656      return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");
2657    }
2658
2659    std::string getLibraryCallName() {
2660      return "";
2661    }
2662
2663    // To conform with interface requirement on operand naming.
2664    mlir::ValueRange inputs() { return getInputs(); }
2665    mlir::ValueRange outputs() { return getOutputs(); }
2666  }];
2667}
2668
2669//===----------------------------------------------------------------------===//
2670// Test LinalgFillOpInterface.
2671//===----------------------------------------------------------------------===//
2672
2673def TestLinalgFillOpNotLinalgOp : TEST_Op<"fill_op_not_linalg_op", [
2674    LinalgFillOpInterface]> {
2675  let arguments = (ins
2676    AnyType:$value, AnyType:$output);
2677  let results = (outs AnyRankedTensor:$result);
2678}
2679
2680def TestLinalgFillOp :
2681  TEST_Op<"linalg_fill_op", [AttrSizedOperandSegments, SingleBlock,
2682      LinalgStructuredInterface, LinalgFillOpInterface]> {
2683
2684  let arguments = (ins Variadic<AnyType>:$inputs,
2685    Variadic<AnyType>:$outputs);
2686  let results = (outs Variadic<AnyType>:$results);
2687  let regions = (region AnyRegion:$region);
2688
2689  let assemblyFormat = [{
2690    attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?
2691    `outs` `(` $outputs `:` type($outputs) `)`
2692    $region (`->` type($results)^)?
2693  }];
2694
2695  let extraClassDeclaration = [{
2696    bool hasIndexSemantics() { return false; }
2697
2698    static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,
2699                              mlir::ArrayRef<mlir::NamedAttribute> attrs) {
2700      b.create<mlir::linalg::YieldOp>(block.getArguments().back());
2701    }
2702
2703    static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,
2704                              mlir::ArrayRef<mlir::NamedAttribute>)>
2705    getRegionBuilder() {
2706      return &regionBuilder;
2707    }
2708
2709    mlir::ArrayAttr iterator_types() {
2710      return getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");
2711    }
2712
2713    mlir::ArrayAttr indexing_maps() {
2714      return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");
2715    }
2716
2717    std::string getLibraryCallName() {
2718      return "";
2719    }
2720
2721    // To conform with interface requirement on operand naming.
2722    mlir::ValueRange inputs() { return getInputs(); }
2723    mlir::ValueRange outputs() { return getOutputs(); }
2724  }];
2725}
2726
2727//===----------------------------------------------------------------------===//
2728// Test Ops with Default-Valued String Attributes
2729//===----------------------------------------------------------------------===//
2730
2731def TestDefaultStrAttrNoValueOp : TEST_Op<"no_str_value"> {
2732  let arguments = (ins DefaultValuedAttr<StrAttr, "">:$value);
2733  let assemblyFormat = "attr-dict";
2734}
2735
2736def TestDefaultStrAttrHasValueOp : TEST_Op<"has_str_value"> {
2737  let arguments = (ins DefaultValuedStrAttr<StrAttr, "">:$value);
2738  let assemblyFormat = "attr-dict";
2739}
2740
2741def : Pat<(TestDefaultStrAttrNoValueOp $value),
2742          (TestDefaultStrAttrHasValueOp ConstantStrAttr<StrAttr, "foo">)>;
2743
2744//===----------------------------------------------------------------------===//
2745// Test Ops with effects
2746//===----------------------------------------------------------------------===//
2747
2748def TestResource : Resource<"TestResource">;
2749
2750def TestEffectsOpA : TEST_Op<"op_with_effects_a"> {
2751    let arguments = (ins
2752        Arg<Variadic<AnyMemRef>, "", [MemRead]>,
2753        Arg<FlatSymbolRefAttr, "", [MemRead]>:$first,
2754        Arg<SymbolRefAttr, "", [MemWrite]>:$second,
2755        Arg<OptionalAttr<SymbolRefAttr>, "", [MemRead]>:$optional_symbol
2756        );
2757
2758    let results = (outs Res<AnyMemRef, "", [MemAlloc<TestResource>]>);
2759}
2760
2761def TestEffectsOpB : TEST_Op<"op_with_effects_b",
2762    [MemoryEffects<[MemWrite<TestResource>]>]>;
2763
2764def TestEffectsRead : TEST_Op<"op_with_memread",
2765    [MemoryEffects<[MemRead]>]> {
2766  let results = (outs AnyInteger);
2767}
2768
2769def TestEffectsWrite : TEST_Op<"op_with_memwrite",
2770    [MemoryEffects<[MemWrite]>]>;
2771
2772#endif // TEST_OPS
2773