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