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