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