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