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/Interfaces/SideEffects.td"
15include "mlir/Interfaces/CallInterfaces.td"
16include "mlir/Interfaces/ControlFlowInterfaces.td"
17include "mlir/Interfaces/InferTypeOpInterface.td"
18include "mlir/Interfaces/SideEffects.td"
19
20def Test_Dialect : Dialect {
21  let name = "test";
22  let cppNamespace = "";
23  let hasOperationAttrVerify = 1;
24  let hasRegionArgAttrVerify = 1;
25  let hasRegionResultAttrVerify = 1;
26}
27
28class TEST_Op<string mnemonic, list<OpTrait> traits = []> :
29    Op<Test_Dialect, mnemonic, traits>;
30
31//===----------------------------------------------------------------------===//
32// Test Types
33//===----------------------------------------------------------------------===//
34
35def IntTypesOp : TEST_Op<"int_types"> {
36  let results = (outs
37    AnyI16:$any_i16,
38    SI32:$si32,
39    UI64:$ui64,
40    AnyInteger:$any_int
41  );
42}
43
44def ComplexF64 : Complex<F64>;
45def ComplexOp : TEST_Op<"complex_f64"> {
46  let results = (outs ComplexF64);
47}
48
49def ComplexTensorOp : TEST_Op<"complex_f64_tensor"> {
50  let results = (outs TensorOf<[ComplexF64]>);
51}
52
53def AnyShaped: ShapedContainerType<[AnyType], IsShapedTypePred, "shaped">;
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
91//===----------------------------------------------------------------------===//
92// Test Symbols
93//===----------------------------------------------------------------------===//
94
95def SymbolOp : TEST_Op<"symbol", [Symbol]> {
96  let summary =  "operation which defines a new symbol";
97  let arguments = (ins StrAttr:$sym_name,
98                       OptionalAttr<StrAttr>:$sym_visibility);
99}
100
101def SymbolScopeOp : TEST_Op<"symbol_scope",
102    [SymbolTable, SingleBlockImplicitTerminator<"TerminatorOp">]> {
103  let summary =  "operation which defines a new symbol table";
104  let regions = (region SizedRegion<1>:$region);
105}
106
107def SymbolTableRegionOp : TEST_Op<"symbol_table_region", [SymbolTable]> {
108  let summary =  "operation which defines a new symbol table without a "
109                 "restriction on a terminator";
110  let regions = (region SizedRegion<1>:$region);
111}
112
113//===----------------------------------------------------------------------===//
114// Test Operands
115//===----------------------------------------------------------------------===//
116
117def MixedNormalVariadicOperandOp : TEST_Op<
118    "mixed_normal_variadic_operand", [SameVariadicOperandSize]> {
119  let arguments = (ins
120    Variadic<AnyTensor>:$input1,
121    AnyTensor:$input2,
122    Variadic<AnyTensor>:$input3
123  );
124}
125
126//===----------------------------------------------------------------------===//
127// Test Results
128//===----------------------------------------------------------------------===//
129
130def MixedNormalVariadicResults : TEST_Op<
131    "mixed_normal_variadic_result", [SameVariadicResultSize]> {
132  let results = (outs
133    Variadic<AnyTensor>:$output1,
134    AnyTensor:$output2,
135    Variadic<AnyTensor>:$output3
136  );
137}
138
139//===----------------------------------------------------------------------===//
140// Test Attributes
141//===----------------------------------------------------------------------===//
142
143def NonNegIntAttrOp : TEST_Op<"non_negative_int_attr"> {
144  let arguments = (ins
145      Confined<I32Attr, [IntNonNegative]>:$i32attr,
146      Confined<I64Attr, [IntNonNegative]>:$i64attr
147  );
148}
149
150def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> {
151  let arguments = (ins
152      Confined<I32Attr, [IntPositive]>:$i32attr,
153      Confined<I64Attr, [IntPositive]>:$i64attr
154  );
155}
156
157def TypeArrayAttrOp : TEST_Op<"type_array_attr"> {
158  let arguments = (ins TypeArrayAttr:$attr);
159}
160def TypeStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> {
161  let arguments = (ins TypedStrAttr<AnyType>:$attr);
162  let assemblyFormat = "$attr attr-dict";
163}
164
165def StrCaseA: StrEnumAttrCase<"A">;
166def StrCaseB: StrEnumAttrCase<"B">;
167
168def SomeStrEnum: StrEnumAttr<
169  "SomeStrEnum", "", [StrCaseA, StrCaseB]>;
170
171def StrEnumAttrOp : TEST_Op<"str_enum_attr"> {
172  let arguments = (ins SomeStrEnum:$attr);
173  let results = (outs I32:$val);
174}
175
176def I32Case5:  I32EnumAttrCase<"case5", 5>;
177def I32Case10: I32EnumAttrCase<"case10", 10>;
178
179def SomeI32Enum: I32EnumAttr<
180  "SomeI32Enum", "", [I32Case5, I32Case10]>;
181
182def I32EnumAttrOp : TEST_Op<"i32_enum_attr"> {
183  let arguments = (ins SomeI32Enum:$attr);
184  let results = (outs I32:$val);
185}
186
187def I64Case5:  I64EnumAttrCase<"case5", 5>;
188def I64Case10: I64EnumAttrCase<"case10", 10>;
189
190def SomeI64Enum: I64EnumAttr<
191  "SomeI64Enum", "", [I64Case5, I64Case10]>;
192
193def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> {
194  let arguments = (ins SomeI64Enum:$attr);
195  let results = (outs I32:$val);
196}
197
198
199def IntAttrOp : TEST_Op<"int_attrs"> {
200  let arguments = (ins
201    AnyI32Attr:$any_i32_attr,
202    IndexAttr:$index_attr,
203    UI32Attr:$ui32_attr,
204    SI32Attr:$si32_attr
205  );
206}
207
208def FloatElementsAttrOp : TEST_Op<"float_elements_attr"> {
209  let arguments = (ins
210      RankedF32ElementsAttr<[2]>:$scalar_f32_attr,
211      RankedF64ElementsAttr<[4, 8]>:$tensor_f64_attr
212  );
213}
214
215// A pattern that updates dense<[3.0, 4.0]> to dense<[5.0, 6.0]>.
216// This tests both matching and generating float elements attributes.
217def UpdateFloatElementsAttr : Pat<
218  (FloatElementsAttrOp
219    ConstantAttr<RankedF32ElementsAttr<[2]>, "{3.0f, 4.0f}">:$f32attr,
220    $f64attr),
221  (FloatElementsAttrOp
222    ConstantAttr<RankedF32ElementsAttr<[2]>, "{5.0f, 6.0f}">:$f32attr,
223    $f64attr)>;
224
225def IntElementsAttrOp : TEST_Op<"int_elements_attr"> {
226  let arguments = (ins
227      AnyI32ElementsAttr:$any_i32_attr,
228      I32ElementsAttr:$i32_attr
229  );
230}
231
232def RankedIntElementsAttrOp : TEST_Op<"ranked_int_elements_attr"> {
233  let arguments = (ins
234      RankedI32ElementsAttr<[2]>:$vector_i32_attr,
235      RankedI64ElementsAttr<[4, 8]>:$matrix_i64_attr
236  );
237}
238
239//===----------------------------------------------------------------------===//
240// Test Attribute Constraints
241//===----------------------------------------------------------------------===//
242
243def SymbolRefOp : TEST_Op<"symbol_ref_attr"> {
244  let arguments = (ins
245    Confined<FlatSymbolRefAttr, [ReferToOp<"FuncOp">]>:$symbol
246  );
247}
248
249//===----------------------------------------------------------------------===//
250// Test Regions
251//===----------------------------------------------------------------------===//
252
253def OneRegionOp : TEST_Op<"one_region_op", []> {
254  let regions = (region AnyRegion);
255}
256
257def TwoRegionOp : TEST_Op<"two_region_op", []> {
258  let regions = (region AnyRegion, AnyRegion);
259}
260
261def SizedRegionOp : TEST_Op<"sized_region_op", []> {
262  let regions = (region SizedRegion<2>:$my_region, SizedRegion<1>);
263}
264
265//===----------------------------------------------------------------------===//
266// Test Call Interfaces
267//===----------------------------------------------------------------------===//
268
269def ConversionCallOp : TEST_Op<"conversion_call_op",
270    [CallOpInterface]> {
271  let arguments = (ins Variadic<AnyType>:$inputs, SymbolRefAttr:$callee);
272  let results = (outs Variadic<AnyType>);
273
274  let extraClassDeclaration = [{
275    /// Get the argument operands to the called function.
276    operand_range getArgOperands() { return inputs(); }
277
278    /// Return the callee of this operation.
279    CallInterfaceCallable getCallableForCallee() {
280      return getAttrOfType<SymbolRefAttr>("callee");
281    }
282  }];
283}
284
285def FunctionalRegionOp : TEST_Op<"functional_region_op",
286    [CallableOpInterface]> {
287  let regions = (region AnyRegion:$body);
288  let results = (outs FunctionType);
289
290  let extraClassDeclaration = [{
291    Region *getCallableRegion() { return &body(); }
292    ArrayRef<Type> getCallableResults() {
293      return getType().cast<FunctionType>().getResults();
294    }
295  }];
296}
297
298//===----------------------------------------------------------------------===//
299// Test Traits
300//===----------------------------------------------------------------------===//
301
302def SameOperandElementTypeOp : TEST_Op<"same_operand_element_type",
303    [SameOperandsElementType]> {
304  let arguments = (ins AnyType, AnyType);
305  let results = (outs AnyType);
306}
307
308def SameOperandAndResultElementTypeOp : TEST_Op<"same_operand_and_result_element_type",
309    [SameOperandsAndResultElementType]> {
310  let arguments = (ins Variadic<AnyType>);
311  let results = (outs Variadic<AnyType>);
312}
313
314def SameOperandShapeOp : TEST_Op<"same_operand_shape", [SameOperandsShape]> {
315  let arguments = (ins Variadic<AnyShaped>);
316}
317
318def SameOperandAndResultShapeOp : TEST_Op<"same_operand_and_result_shape",
319    [SameOperandsAndResultShape]> {
320  let arguments = (ins Variadic<AnyShaped>);
321  let results = (outs Variadic<AnyShaped>);
322}
323
324def SameOperandAndResultTypeOp : TEST_Op<"same_operand_and_result_type",
325    [SameOperandsAndResultType]> {
326  let arguments = (ins Variadic<AnyType>);
327  let results = (outs Variadic<AnyType>);
328}
329
330def ArgAndResHaveFixedElementTypesOp :
331    TEST_Op<"arg_and_res_have_fixed_element_types",
332      [PredOpTrait<"fixed type combination",
333         And<[ElementTypeIsPred<"x", I32>,
334              ElementTypeIsPred<"y", F32>]>>,
335      ElementTypeIs<"res", I16>]> {
336  let arguments = (ins
337    AnyShaped:$x, AnyShaped:$y);
338  let results = (outs AnyShaped:$res);
339}
340
341def OperandsHaveSameElementType : TEST_Op<"operands_have_same_element_type", [
342    AllElementTypesMatch<["x", "y"]>]> {
343  let arguments = (ins AnyType:$x, AnyType:$y);
344}
345
346def OperandZeroAndResultHaveSameElementType : TEST_Op<
347    "operand0_and_result_have_same_element_type",
348    [AllElementTypesMatch<["x", "res"]>]> {
349  let arguments = (ins AnyType:$x, AnyType:$y);
350  let results = (outs AnyType:$res);
351}
352
353def OperandsHaveSameType :
354    TEST_Op<"operands_have_same_type", [AllTypesMatch<["x", "y"]>]> {
355  let arguments = (ins AnyType:$x, AnyType:$y);
356}
357
358def OperandZeroAndResultHaveSameType :
359    TEST_Op<"operand0_and_result_have_same_type",
360            [AllTypesMatch<["x", "res"]>]> {
361  let arguments = (ins AnyType:$x, AnyType:$y);
362  let results = (outs AnyType:$res);
363}
364
365def OperandsHaveSameRank :
366    TEST_Op<"operands_have_same_rank", [AllRanksMatch<["x", "y"]>]> {
367  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
368}
369
370def OperandZeroAndResultHaveSameRank :
371    TEST_Op<"operand0_and_result_have_same_rank",
372            [AllRanksMatch<["x", "res"]>]> {
373  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
374  let results = (outs AnyShaped:$res);
375}
376
377def OperandZeroAndResultHaveSameShape :
378    TEST_Op<"operand0_and_result_have_same_shape",
379            [AllShapesMatch<["x", "res"]>]> {
380  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
381  let results = (outs AnyShaped:$res);
382}
383
384def OperandZeroAndResultHaveSameElementCount :
385    TEST_Op<"operand0_and_result_have_same_element_count",
386            [AllElementCountsMatch<["x", "res"]>]> {
387  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
388  let results = (outs AnyShaped:$res);
389}
390
391def FourEqualsFive :
392    TEST_Op<"four_equals_five", [AllMatch<["5", "4"], "4 equals 5">]>;
393
394def OperandRankEqualsResultSize :
395    TEST_Op<"operand_rank_equals_result_size",
396            [AllMatch<[Rank<"operand">.result, ElementCount<"result">.result],
397                      "operand rank equals result size">]> {
398  let arguments = (ins AnyShaped:$operand);
399  let results = (outs AnyShaped:$result);
400}
401
402def IfFirstOperandIsNoneThenSoIsSecond :
403    TEST_Op<"if_first_operand_is_none_then_so_is_second", [PredOpTrait<
404    "has either both none type operands or first is not none",
405     Or<[
406        And<[TypeIsPred<"x", NoneType>, TypeIsPred<"y", NoneType>]>,
407        Neg<TypeIsPred<"x", NoneType>>]>>]> {
408  let arguments = (ins AnyType:$x, AnyType:$y);
409}
410
411def BroadcastableOp : TEST_Op<"broadcastable", [ResultsBroadcastableShape]> {
412  let arguments = (ins Variadic<AnyTensor>);
413  let results = (outs AnyTensor);
414}
415
416// There the "HasParent" trait.
417def ParentOp : TEST_Op<"parent">;
418def ChildOp : TEST_Op<"child", [HasParent<"ParentOp">]>;
419
420
421def TerminatorOp : TEST_Op<"finish", [Terminator]>;
422def SingleBlockImplicitTerminatorOp : TEST_Op<"SingleBlockImplicitTerminator",
423    [SingleBlockImplicitTerminator<"TerminatorOp">]> {
424  let regions = (region SizedRegion<1>:$region);
425}
426
427def I32ElementsAttrOp : TEST_Op<"i32ElementsAttr"> {
428  let arguments = (ins I32ElementsAttr:$attr);
429}
430
431def OpWithInferTypeInterfaceOp : TEST_Op<"op_with_infer_type_if", [
432    DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
433  let arguments = (ins AnyTensor, AnyTensor);
434  let results = (outs AnyTensor);
435}
436
437def InferTensorType : NativeOpTrait<"InferTensorType">;
438def OpWithShapedTypeInferTypeInterfaceOp : TEST_Op<"op_with_shaped_type_infer_type_if",
439  [
440     // Op implements infer type op interface.
441     InferTypeOpInterface,
442     // The op will have methods implementing the ShapedType type infer interface.
443     DeclareOpInterfaceMethods<InferShapedTypeOpInterface>,
444     // The op produces tensors and will use the ShapedType type infer interface
445     // along with knowledge that it is producing Tensors to infer shape.
446     InferTensorType
447   ]> {
448  let arguments = (ins AnyTensor, AnyTensor);
449  let results = (outs AnyTensor);
450
451  let extraClassDeclaration = [{
452    LogicalResult reifyReturnTypeShapes(OpBuilder &builder,
453                                        SmallVectorImpl<Value> &shapes);
454  }];
455}
456
457def IsNotScalar : Constraint<CPred<"$0.getType().getRank() != 0">>;
458
459def UpdateAttr : Pat<(I32ElementsAttrOp $attr),
460                     (I32ElementsAttrOp ConstantAttr<I32ElementsAttr, "0">),
461                     [(IsNotScalar $attr)]>;
462
463def TestBranchOp : TEST_Op<"br",
464    [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator]> {
465  let arguments = (ins Variadic<AnyType>:$targetOperands);
466  let successors = (successor AnySuccessor:$target);
467}
468
469def AttrSizedOperandOp : TEST_Op<"attr_sized_operands",
470                                 [AttrSizedOperandSegments]> {
471  let arguments = (ins
472    Variadic<I32>:$a,
473    Variadic<I32>:$b,
474    I32:$c,
475    Variadic<I32>:$d,
476    I32ElementsAttr:$operand_segment_sizes
477  );
478}
479
480def AttrSizedResultOp : TEST_Op<"attr_sized_results",
481                                [AttrSizedResultSegments]> {
482  let arguments = (ins
483    I32ElementsAttr:$result_segment_sizes
484  );
485  let results = (outs
486    Variadic<I32>:$a,
487    Variadic<I32>:$b,
488    I32:$c,
489    Variadic<I32>:$d
490  );
491}
492
493// This is used to test encoding of a string attribute into an SSA name of a
494// pretty printed value name.
495def StringAttrPrettyNameOp
496 : TEST_Op<"string_attr_pretty_name",
497           [DeclareOpInterfaceMethods<OpAsmOpInterface>]> {
498  let arguments = (ins StrArrayAttr:$names);
499  let results = (outs Variadic<I32>:$r);
500
501  let printer = [{ return ::print(p, *this); }];
502  let parser = [{ return ::parse$cppClass(parser, result); }];
503}
504
505//===----------------------------------------------------------------------===//
506// Test Locations
507//===----------------------------------------------------------------------===//
508
509def TestLocationSrcOp : TEST_Op<"loc_src"> {
510  let arguments = (ins I32:$input);
511  let results = (outs I32:$output);
512}
513
514def TestLocationDstOp : TEST_Op<"loc_dst", [SameOperandsAndResultType]> {
515  let arguments = (ins I32:$input);
516  let results = (outs I32:$output);
517}
518
519//===----------------------------------------------------------------------===//
520// Test Patterns
521//===----------------------------------------------------------------------===//
522
523def OpA : TEST_Op<"op_a"> {
524  let arguments = (ins I32, I32Attr:$attr);
525  let results = (outs I32);
526}
527
528def OpB : TEST_Op<"op_b"> {
529  let arguments = (ins I32, I32Attr:$attr);
530  let results = (outs I32);
531}
532
533// Test named pattern.
534def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>;
535
536// Test with fused location.
537def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>;
538
539// Test added benefit.
540def OpD : TEST_Op<"op_d">, Arguments<(ins I32)>, Results<(outs I32)>;
541def OpE : TEST_Op<"op_e">, Arguments<(ins I32)>, Results<(outs I32)>;
542def OpF : TEST_Op<"op_f">, Arguments<(ins I32)>, Results<(outs I32)>;
543def OpG : TEST_Op<"op_g">, Arguments<(ins I32)>, Results<(outs I32)>;
544// Verify that bumping benefit results in selecting different op.
545def : Pat<(OpD $input), (OpE $input)>;
546def : Pat<(OpD $input), (OpF $input), [], (addBenefit 10)>;
547// Verify that patterns with more source nodes are selected before those with fewer.
548def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>;
549def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>;
550
551// Test patterns for zero-result op.
552def OpH : TEST_Op<"op_h">, Arguments<(ins I32)>, Results<(outs)>;
553def OpI : TEST_Op<"op_i">, Arguments<(ins I32)>, Results<(outs)>;
554def : Pat<(OpH $input), (OpI $input)>;
555
556// Test patterns for zero-input op.
557def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32)>;
558def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32)>;
559def : Pat<(OpJ), (OpK)>;
560
561// Test `$_` for ignoring op argument match.
562def TestIgnoreArgMatchSrcOp : TEST_Op<"ignore_arg_match_src"> {
563  let arguments = (ins
564    AnyType:$a, AnyType:$b, AnyType:$c,
565    AnyAttr:$d, AnyAttr:$e, AnyAttr:$f);
566}
567def TestIgnoreArgMatchDstOp : TEST_Op<"ignore_arg_match_dst"> {
568  let arguments = (ins AnyType:$b, AnyAttr:$f);
569}
570def : Pat<(TestIgnoreArgMatchSrcOp $_, $b, I32, I64Attr:$_, $_, $f),
571          (TestIgnoreArgMatchDstOp $b, $f)>;
572
573def OpInterleavedOperandAttribute1 : TEST_Op<"interleaved_operand_attr1"> {
574  let arguments = (ins
575    I32:$input1,
576    I64Attr:$attr1,
577    I32:$input2,
578    I64Attr:$attr2
579  );
580}
581
582def OpInterleavedOperandAttribute2 : TEST_Op<"interleaved_operand_attr2"> {
583  let arguments = (ins
584    I32:$input1,
585    I64Attr:$attr1,
586    I32:$input2,
587    I64Attr:$attr2
588  );
589}
590
591def ManyArgsOp : TEST_Op<"many_arguments"> {
592  let arguments = (ins
593    I32:$input1, I32:$input2, I32:$input3, I32:$input4, I32:$input5,
594    I32:$input6, I32:$input7, I32:$input8, I32:$input9,
595    I64Attr:$attr1, I64Attr:$attr2, I64Attr:$attr3, I64Attr:$attr4,
596    I64Attr:$attr5, I64Attr:$attr6, I64Attr:$attr7, I64Attr:$attr8,
597    I64Attr:$attr9
598  );
599}
600
601// Test that DRR does not blow up when seeing lots of arguments.
602def : Pat<(ManyArgsOp
603            $input1, $input2, $input3, $input4, $input5,
604            $input6, $input7, $input8, $input9,
605            ConstantAttr<I64Attr, "42">,
606            $attr2, $attr3, $attr4, $attr5, $attr6,
607            $attr7, $attr8, $attr9),
608          (ManyArgsOp
609            $input1, $input2, $input3, $input4, $input5,
610            $input6, $input7, $input8, $input9,
611            ConstantAttr<I64Attr, "24">,
612            $attr2, $attr3, $attr4, $attr5, $attr6,
613            $attr7, $attr8, $attr9)>;
614
615// Test that we can capture and reference interleaved operands and attributes.
616def : Pat<(OpInterleavedOperandAttribute1 $input1, $attr1, $input2, $attr2),
617          (OpInterleavedOperandAttribute2 $input1, $attr1, $input2, $attr2)>;
618
619// Test NativeCodeCall.
620def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> {
621  let arguments = (ins
622    I32:$input1, I32:$input2,
623    BoolAttr:$choice,
624    I64Attr:$attr1, I64Attr:$attr2
625  );
626  let results = (outs I32);
627}
628def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> {
629  let arguments = (ins I32:$input, I64ArrayAttr:$attr);
630  let results = (outs I32);
631}
632// Native code call to invoke a C++ function
633def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">;
634// Native code call to invoke a C++ expression
635def CreateArrayAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">;
636// Test that we can use NativeCodeCall to create operand and attribute.
637// This pattern chooses between $input1 and $input2 according to $choice and
638// it combines $attr1 and $attr2 into an array attribute.
639def : Pat<(OpNativeCodeCall1 $input1, $input2,
640                             ConstBoolAttrTrue:$choice, $attr1, $attr2),
641          (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice),
642                             (CreateArrayAttr $attr1, $attr2))>;
643// Note: the following is just for testing purpose.
644// Should use the replaceWithValue directive instead.
645def UseOpResult: NativeCodeCall<"$0">;
646// Test that we can use NativeCodeCall to create result.
647def : Pat<(OpNativeCodeCall1 $input1, $input2,
648                             ConstBoolAttrFalse, $attr1, $attr2),
649          (UseOpResult $input2)>;
650
651def OpNativeCodeCall3 : TEST_Op<"native_code_call3"> {
652  let arguments = (ins I32:$input);
653  let results = (outs I32);
654}
655// Test that NativeCodeCall is not ignored if it is not used to directly
656// replace the matched root op.
657def : Pattern<(OpNativeCodeCall3 $input),
658              [(NativeCodeCall<"createOpI($_builder, $0)"> $input), (OpK)]>;
659
660// Test AllAttrConstraintsOf.
661def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> {
662  let arguments = (ins I64ArrayAttr:$attr);
663  let results = (outs I32);
664}
665def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> {
666  let arguments = (ins I64ArrayAttr:$attr);
667  let results = (outs I32);
668}
669def Constraint0 : AttrConstraint<
670    CPred<"$_self.cast<ArrayAttr>()[0]."
671          "cast<IntegerAttr>().getInt() == 0">,
672    "[0] == 0">;
673def Constraint1 : AttrConstraint<
674    CPred<"$_self.cast<ArrayAttr>()[1].cast<IntegerAttr>().getInt() == 1">,
675    "[1] == 1">;
676def : Pat<(OpAllAttrConstraint1
677            AllAttrConstraintsOf<[Constraint0, Constraint1]>:$attr),
678          (OpAllAttrConstraint2 $attr)>;
679
680// Op for testing RewritePattern removing op with inner ops.
681def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> {
682  let regions = (region SizedRegion<1>:$region);
683  let hasCanonicalizer = 1;
684}
685
686// Op for testing trivial removal via folding of op with inner ops and no uses.
687def TestOpWithRegionFoldNoSideEffect : TEST_Op<
688    "op_with_region_fold_no_side_effect", [NoSideEffect]> {
689  let regions = (region SizedRegion<1>:$region);
690}
691
692// Op for testing folding of outer op with inner ops.
693def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> {
694  let arguments = (ins I32:$operand);
695  let results = (outs I32);
696  let regions = (region SizedRegion<1>:$region);
697  let hasFolder = 1;
698}
699
700def TestOpWithVariadicResultsAndFolder: TEST_Op<"op_with_variadic_results_and_folder"> {
701  let arguments = (ins Variadic<I32>:$operands);
702  let results = (outs Variadic<I32>);
703  let hasFolder = 1;
704}
705
706def TestCommutativeOp : TEST_Op<"op_commutative", [Commutative]> {
707  let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4);
708  let results = (outs I32);
709}
710
711//===----------------------------------------------------------------------===//
712// Test Patterns (Symbol Binding)
713
714// Test symbol binding.
715def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> {
716  let arguments = (ins I32:$operand, I64Attr:$attr);
717  let results = (outs I32);
718}
719def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> {
720  let arguments = (ins I32:$operand);
721  let results = (outs I32);
722
723  let builders = [
724    OpBuilder<
725      "Builder *builder, OperationState &state, Value operand",
726      [{
727        state.types.assign({builder->getIntegerType(32)});
728        state.addOperands({operand});
729      }]>
730  ];
731}
732def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> {
733  let arguments = (ins I32:$operand);
734  let results = (outs I32);
735  let builders = OpSymbolBindingB.builders;
736}
737def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> {
738  let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr);
739  let results = (outs I32);
740}
741def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">;
742def : Pattern<
743    // Bind to source pattern op operand/attribute/result
744    (OpSymbolBindingA:$res_a $operand, $attr), [
745        // Bind to auxiliary op result
746        (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)),
747
748        // Use bound symbols in resultant ops
749        (OpSymbolBindingD $res_b, $res_c, $attr)],
750    // Use bound symbols in additional constraints
751    [(HasOneUse $res_a)]>;
752
753def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> {
754  let arguments = (ins I32:$operand);
755}
756
757// Test that we can bind to an op without results and reference it later.
758def : Pat<(OpSymbolBindingNoResult:$op $operand),
759          (NativeCodeCall<"handleNoResultOp($_builder, $0)"> $op)>;
760
761//===----------------------------------------------------------------------===//
762// Test Patterns (Attributes)
763
764// Test matching against op attributes.
765def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> {
766  let arguments = (ins
767    I32Attr:$required_attr,
768    OptionalAttr<I32Attr>:$optional_attr,
769    DefaultValuedAttr<I32Attr, "42">:$default_valued_attr,
770    I32Attr:$more_attr
771  );
772  let results = (outs I32);
773}
774def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> {
775  let arguments = OpAttrMatch1.arguments;
776  let results = (outs I32);
777}
778def MoreConstraint : AttrConstraint<
779    CPred<"$_self.cast<IntegerAttr>().getInt() == 4">, "more constraint">;
780def : Pat<(OpAttrMatch1 $required, $optional, $default_valued,
781                        MoreConstraint:$more),
782          (OpAttrMatch2 $required, $optional, $default_valued, $more)>;
783
784// Test unit attrs.
785def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> {
786  let arguments = (ins UnitAttr:$attr);
787  let results = (outs I32);
788}
789def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> {
790  let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2);
791  let results = (outs I32);
792}
793def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>;
794
795// Test with constant attr.
796def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>;
797def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>;
798
799// Test string enum attribute in rewrites.
800def : Pat<(StrEnumAttrOp StrCaseA), (StrEnumAttrOp StrCaseB)>;
801// Test integer enum attribute in rewrites.
802def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>;
803def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>;
804
805//===----------------------------------------------------------------------===//
806// Test Patterns (Multi-result Ops)
807
808def MultiResultOpKind1: I64EnumAttrCase<"kind1", 1>;
809def MultiResultOpKind2: I64EnumAttrCase<"kind2", 2>;
810def MultiResultOpKind3: I64EnumAttrCase<"kind3", 3>;
811def MultiResultOpKind4: I64EnumAttrCase<"kind4", 4>;
812def MultiResultOpKind5: I64EnumAttrCase<"kind5", 5>;
813def MultiResultOpKind6: I64EnumAttrCase<"kind6", 6>;
814
815def MultiResultOpEnum: I64EnumAttr<
816  "MultiResultOpEnum", "Multi-result op kinds", [
817    MultiResultOpKind1, MultiResultOpKind2, MultiResultOpKind3,
818    MultiResultOpKind4, MultiResultOpKind5, MultiResultOpKind6
819  ]>;
820
821def ThreeResultOp : TEST_Op<"three_result"> {
822  let arguments = (ins MultiResultOpEnum:$kind);
823  let results = (outs I32:$result1, F32:$result2, F32:$result3);
824}
825
826def AnotherThreeResultOp : TEST_Op<"another_three_result"> {
827  let arguments = (ins MultiResultOpEnum:$kind);
828  let results = (outs I32:$result1, F32:$result2, F32:$result3);
829}
830
831def TwoResultOp : TEST_Op<"two_result"> {
832  let arguments = (ins MultiResultOpEnum:$kind);
833  let results = (outs I32:$result1, F32:$result2);
834
835  let builders = [
836    OpBuilder<
837      "Builder *builder, OperationState &state, IntegerAttr kind",
838      [{
839        auto i32 = builder->getIntegerType(32);
840        auto f32 = builder->getF32Type();
841        state.types.assign({i32, f32});
842        state.addAttribute("kind", kind);
843      }]>
844  ];
845}
846
847def AnotherTwoResultOp : TEST_Op<"another_two_result"> {
848  let arguments = (ins MultiResultOpEnum:$kind);
849  let results = (outs F32:$result1, F32:$result2);
850}
851
852def OneResultOp1 : TEST_Op<"one_result1"> {
853  let arguments = (ins MultiResultOpEnum:$kind);
854  let results = (outs F32:$result1);
855}
856
857def OneResultOp2 : TEST_Op<"one_result2"> {
858  let arguments = (ins MultiResultOpEnum:$kind);
859  let results = (outs I32:$result1);
860}
861
862def OneResultOp3 : TEST_Op<"one_result3"> {
863  let arguments = (ins F32);
864  let results = (outs I32:$result1);
865}
866
867// Test using multi-result op as a whole
868def : Pat<(ThreeResultOp MultiResultOpKind1),
869          (AnotherThreeResultOp MultiResultOpKind1)>;
870
871// Test using multi-result op as a whole for partial replacement
872def : Pattern<(ThreeResultOp MultiResultOpKind2),
873              [(TwoResultOp MultiResultOpKind2),
874               (OneResultOp1 MultiResultOpKind2)]>;
875def : Pattern<(ThreeResultOp MultiResultOpKind3),
876              [(OneResultOp2 MultiResultOpKind3),
877               (AnotherTwoResultOp MultiResultOpKind3)]>;
878
879// Test using results separately in a multi-result op
880def : Pattern<(ThreeResultOp MultiResultOpKind4),
881              [(TwoResultOp:$res1__0 MultiResultOpKind4),
882               (OneResultOp1 MultiResultOpKind4),
883               (TwoResultOp:$res2__1 MultiResultOpKind4)]>;
884
885// Test referencing a single value in the value pack
886// This rule only matches TwoResultOp if its second result has no use.
887def : Pattern<(TwoResultOp:$res MultiResultOpKind5),
888              [(OneResultOp2 MultiResultOpKind5),
889               (OneResultOp1 MultiResultOpKind5)],
890              [(HasNoUseOf:$res__1)]>;
891
892// Test using auxiliary ops for replacing multi-result op
893def : Pattern<
894    (ThreeResultOp MultiResultOpKind6), [
895        // Auxiliary op generated to help building the final result but not
896        // directly used to replace the source op's results.
897        (TwoResultOp:$interm MultiResultOpKind6),
898
899        (OneResultOp3 $interm__1),
900        (AnotherTwoResultOp MultiResultOpKind6)
901    ]>;
902
903//===----------------------------------------------------------------------===//
904// Test Patterns (Variadic Ops)
905
906def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> {
907  let arguments = (ins Variadic<I32>);
908  let results = (outs Variadic<I32>);
909}
910def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> {
911  let arguments = (ins Variadic<I32>);
912  let results = (outs Variadic<I32>);
913}
914
915// Rewrite an op with one variadic operand and one variadic result to
916// another similar op.
917def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>;
918
919def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1",
920                               [SameVariadicOperandSize]> {
921  let arguments = (ins
922    Variadic<I32>:$input1,
923    F32:$input2,
924    Variadic<I32>:$input3
925  );
926}
927
928def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2",
929                               [SameVariadicOperandSize]> {
930  let arguments = (ins
931    Variadic<I32>:$input1,
932    F32:$input2,
933    Variadic<I32>:$input3
934  );
935}
936
937// Rewrite an op with both variadic operands and normal operands.
938def : Pat<(MixedVOperandOp1 $input1, $input2, $input3),
939          (MixedVOperandOp2 $input1, $input2, $input3)>;
940
941def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> {
942  let results = (outs
943    Variadic<I32>:$output1,
944    F32:$output2,
945    Variadic<I32>:$output3
946  );
947}
948
949def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> {
950  let results = (outs
951    Variadic<I32>:$output1,
952    F32:$output2,
953    Variadic<I32>:$output3
954  );
955}
956
957// Rewrite an op with both variadic results and normal results.
958// Note that because we are generating the op with a top-level result pattern,
959// we are able to deduce the correct result types for the generated op using
960// the information from the matched root op.
961def : Pat<(MixedVResultOp1), (MixedVResultOp2)>;
962
963def OneI32ResultOp : TEST_Op<"one_i32_out"> {
964  let results = (outs I32);
965}
966
967def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3",
968                               [SameVariadicOperandSize]> {
969  let arguments = (ins
970    I32:$input1,
971    Variadic<I32>:$input2,
972    Variadic<I32>:$input3,
973    I32Attr:$count
974  );
975
976  let results = (outs I32);
977}
978
979def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3",
980                               [SameVariadicResultSize]> {
981  let arguments = (ins I32Attr:$count);
982
983  let results = (outs
984    I32:$output1,
985    Variadic<I32>:$output2,
986    Variadic<I32>:$output3
987  );
988
989  // We will use this op in a nested result pattern, where we cannot deduce the
990  // result type. So need to provide a builder not requiring result types.
991  let builders = [
992    OpBuilder<
993      "Builder *builder, OperationState &state, IntegerAttr count",
994      [{
995        auto i32Type = builder->getIntegerType(32);
996        state.addTypes(i32Type); // $output1
997        SmallVector<Type, 4> types(count.getInt(), i32Type);
998        state.addTypes(types); // $output2
999        state.addTypes(types); // $output3
1000        state.addAttribute("count", count);
1001      }]>
1002  ];
1003}
1004
1005// Generates an op with variadic results using nested pattern.
1006def : Pat<(OneI32ResultOp),
1007          (MixedVOperandOp3
1008              (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">),
1009              (replaceWithValue $results__1),
1010              (replaceWithValue $results__2),
1011              ConstantAttr<I32Attr, "2">)>;
1012
1013//===----------------------------------------------------------------------===//
1014// Test Patterns (Location)
1015
1016// Test that we can specify locations for generated ops.
1017def : Pat<(TestLocationSrcOp:$res1
1018           (TestLocationSrcOp:$res2
1019            (TestLocationSrcOp:$res3 $input))),
1020          (TestLocationDstOp
1021            (TestLocationDstOp
1022              (TestLocationDstOp $input, (location $res1)),
1023              (location "named")),
1024            (location "fused", $res2, $res3))>;
1025
1026//===----------------------------------------------------------------------===//
1027// Test Legalization
1028//===----------------------------------------------------------------------===//
1029
1030def Test_LegalizerEnum_Success : StrEnumAttrCase<"Success">;
1031def Test_LegalizerEnum_Failure : StrEnumAttrCase<"Failure">;
1032
1033def Test_LegalizerEnum : StrEnumAttr<"Success", "Failure",
1034  [Test_LegalizerEnum_Success, Test_LegalizerEnum_Failure]>;
1035
1036def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>;
1037def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>;
1038def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>;
1039def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>;
1040def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>;
1041def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>;
1042def LegalOpA : TEST_Op<"legal_op_a">,
1043  Arguments<(ins Test_LegalizerEnum:$status)>, Results<(outs I32)>;
1044def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>;
1045
1046// Check that smaller pattern depths are chosen, i.e. prioritize more direct
1047// mappings.
1048def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>;
1049
1050def : Pat<(ILLegalOpA), (ILLegalOpB)>;
1051def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>;
1052
1053// Check that the higher benefit pattern is taken for multiple legalizations
1054// with the same depth.
1055def : Pat<(ILLegalOpC), (ILLegalOpD)>;
1056def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>;
1057
1058def : Pat<(ILLegalOpC), (ILLegalOpE), [], (addBenefit 10)>;
1059def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>;
1060
1061// Check that patterns use the most up-to-date value when being replaced.
1062def TestRewriteOp : TEST_Op<"rewrite">,
1063  Arguments<(ins AnyType)>, Results<(outs AnyType)>;
1064def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>;
1065
1066// Check that patterns can specify bounded recursion when rewriting.
1067def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> {
1068  let arguments = (ins I64Attr:$depth);
1069  let assemblyFormat = "$depth attr-dict";
1070}
1071
1072//===----------------------------------------------------------------------===//
1073// Test Type Legalization
1074//===----------------------------------------------------------------------===//
1075
1076def TestRegionBuilderOp : TEST_Op<"region_builder">;
1077def TestReturnOp : TEST_Op<"return", [Terminator]>,
1078  Arguments<(ins Variadic<AnyType>)>;
1079def TestCastOp : TEST_Op<"cast">,
1080  Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>;
1081def TestInvalidOp : TEST_Op<"invalid", [Terminator]>,
1082  Arguments<(ins Variadic<AnyType>)>;
1083def TestTypeProducerOp : TEST_Op<"type_producer">,
1084  Results<(outs AnyType)>;
1085def TestTypeConsumerOp : TEST_Op<"type_consumer">,
1086  Arguments<(ins AnyType)>;
1087def TestValidOp : TEST_Op<"valid", [Terminator]>,
1088  Arguments<(ins Variadic<AnyType>)>;
1089
1090//===----------------------------------------------------------------------===//
1091// Test parser.
1092//===----------------------------------------------------------------------===//
1093
1094def WrappedKeywordOp : TEST_Op<"wrapped_keyword"> {
1095  let arguments = (ins StrAttr:$keyword);
1096  let parser = [{ return ::parse$cppClass(parser, result); }];
1097  let printer = [{ return ::print(p, *this); }];
1098}
1099
1100//===----------------------------------------------------------------------===//
1101// Test region argument list parsing.
1102
1103def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> {
1104  let summary =  "isolated region operation";
1105  let description = [{
1106    Test op with an isolated region, to test passthrough region arguments. Each
1107    argument is of index type.
1108  }];
1109
1110  let arguments = (ins Index);
1111  let regions = (region SizedRegion<1>:$region);
1112  let parser = [{ return ::parse$cppClass(parser, result); }];
1113  let printer = [{ return ::print(p, *this); }];
1114}
1115
1116def WrappingRegionOp : TEST_Op<"wrapping_region",
1117    [SingleBlockImplicitTerminator<"TestReturnOp">]> {
1118  let summary =  "wrapping region operation";
1119  let description = [{
1120    Test op wrapping another op in a region, to test calling
1121    parseGenericOperation from the custom parser.
1122  }];
1123
1124  let results = (outs Variadic<AnyType>);
1125  let regions = (region SizedRegion<1>:$region);
1126  let parser = [{ return ::parse$cppClass(parser, result); }];
1127  let printer = [{ return ::print(p, *this); }];
1128}
1129
1130def PolyForOp : TEST_Op<"polyfor">
1131{
1132  let summary =  "polyfor operation";
1133  let description = [{
1134    Test op with multiple region arguments, each argument of index type.
1135  }];
1136
1137  let regions = (region SizedRegion<1>:$region);
1138  let parser = [{ return ::parse$cppClass(parser, result); }];
1139}
1140
1141//===----------------------------------------------------------------------===//
1142// Test OpAsmInterface.
1143
1144def AsmInterfaceOp : TEST_Op<"asm_interface_op"> {
1145  let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results,
1146                      AnyType);
1147}
1148
1149def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> {
1150  let results = (outs AnyType);
1151}
1152
1153//===----------------------------------------------------------------------===//
1154// Test Op Asm Format
1155//===----------------------------------------------------------------------===//
1156
1157def FormatLiteralOp : TEST_Op<"format_literal_op"> {
1158  let assemblyFormat = [{
1159    `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` attr-dict
1160  }];
1161}
1162
1163// Test that we elide attributes that are within the syntax.
1164def FormatAttrOp : TEST_Op<"format_attr_op"> {
1165  let arguments = (ins I64Attr:$attr);
1166  let assemblyFormat = "$attr attr-dict";
1167}
1168
1169// Test that we elide attributes that are within the syntax.
1170def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> {
1171  let arguments = (ins I64Attr:$attr);
1172  let assemblyFormat = "attr-dict-with-keyword";
1173}
1174
1175// Test that we don't need to provide types in the format if they are buildable.
1176def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> {
1177  let arguments = (ins I64:$buildable);
1178  let results = (outs I64:$buildable_res);
1179  let assemblyFormat = "$buildable attr-dict";
1180}
1181
1182// Test various mixings of result type formatting.
1183class FormatResultBase<string suffix, string fmt>
1184    : TEST_Op<"format_result_" # suffix # "_op"> {
1185  let results = (outs I64:$buildable_res, AnyMemRef:$result);
1186  let assemblyFormat = fmt;
1187}
1188def FormatResultAOp : FormatResultBase<"a", [{
1189  type($result) attr-dict
1190}]>;
1191def FormatResultBOp : FormatResultBase<"b", [{
1192  type(results) attr-dict
1193}]>;
1194def FormatResultCOp : FormatResultBase<"c", [{
1195  functional-type($buildable_res, $result) attr-dict
1196}]>;
1197
1198// Test various mixings of operand type formatting.
1199class FormatOperandBase<string suffix, string fmt>
1200    : TEST_Op<"format_operand_" # suffix # "_op"> {
1201  let arguments = (ins I64:$buildable, AnyMemRef:$operand);
1202  let assemblyFormat = fmt;
1203}
1204
1205def FormatOperandAOp : FormatOperandBase<"a", [{
1206  operands `:` type(operands) attr-dict
1207}]>;
1208def FormatOperandBOp : FormatOperandBase<"b", [{
1209  operands `:` type($operand) attr-dict
1210}]>;
1211def FormatOperandCOp : FormatOperandBase<"c", [{
1212  $buildable `,` $operand `:` type(operands) attr-dict
1213}]>;
1214def FormatOperandDOp : FormatOperandBase<"d", [{
1215  $buildable `,` $operand `:` type($operand) attr-dict
1216}]>;
1217def FormatOperandEOp : FormatOperandBase<"e", [{
1218  $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict
1219}]>;
1220
1221def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> {
1222  let successors = (successor VariadicSuccessor<AnySuccessor>:$targets);
1223  let assemblyFormat = "$targets attr-dict";
1224}
1225
1226// Test various mixings of optional operand and result type formatting.
1227class FormatOptionalOperandResultOpBase<string suffix, string fmt>
1228    : TEST_Op<"format_optional_operand_result_" # suffix # "_op",
1229              [AttrSizedOperandSegments]> {
1230  let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic);
1231  let results = (outs Optional<I64>:$optional_res);
1232  let assemblyFormat = fmt;
1233}
1234
1235def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{
1236  `(` $optional `:` type($optional) `)` `:` type($optional_res)
1237  (`[` $variadic^ `]`)? attr-dict
1238}]>;
1239
1240def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{
1241  (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res)
1242  (`[` $variadic^ `]`)? attr-dict
1243}]>;
1244
1245//===----------------------------------------------------------------------===//
1246// Test SideEffects
1247//===----------------------------------------------------------------------===//
1248
1249def SideEffectOp : TEST_Op<"side_effect_op",
1250    [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
1251  let results = (outs AnyType:$result);
1252}
1253
1254#endif // TEST_OPS
1255