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// Test op that simply returns success.
1248def TestOpInPlaceFoldSuccess : TEST_Op<"op_in_place_fold_success"> {
1249  let results = (outs Variadic<I1>);
1250  let hasFolder = 1;
1251  let extraClassDefinition = [{
1252    ::mlir::LogicalResult $cppClass::fold(ArrayRef<Attribute> operands,
1253        SmallVectorImpl<OpFoldResult> &results) {
1254      return success();
1255    }
1256  }];
1257}
1258
1259// An op that always fold itself.
1260def TestPassthroughFold : TEST_Op<"passthrough_fold"> {
1261  let arguments = (ins AnyType:$op);
1262  let results = (outs AnyType);
1263  let hasFolder = 1;
1264}
1265
1266def TestDialectCanonicalizerOp : TEST_Op<"dialect_canonicalizable"> {
1267  let arguments = (ins);
1268  let results = (outs I32);
1269}
1270
1271//===----------------------------------------------------------------------===//
1272// Test Patterns (Symbol Binding)
1273
1274// Test symbol binding.
1275def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> {
1276  let arguments = (ins I32:$operand, I64Attr:$attr);
1277  let results = (outs I32);
1278}
1279def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> {
1280  let arguments = (ins I32:$operand);
1281  let results = (outs I32);
1282}
1283def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> {
1284  let arguments = (ins I32:$operand);
1285  let results = (outs I32);
1286  let builders = OpSymbolBindingB.builders;
1287}
1288def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> {
1289  let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr);
1290  let results = (outs I32);
1291}
1292def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">;
1293def : Pattern<
1294    // Bind to source pattern op operand/attribute/result
1295    (OpSymbolBindingA:$res_a $operand, $attr), [
1296        // Bind to auxiliary op result
1297        (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)),
1298
1299        // Use bound symbols in resultant ops
1300        (OpSymbolBindingD $res_b, $res_c, $attr)],
1301    // Use bound symbols in additional constraints
1302    [(HasOneUse $res_a)]>;
1303
1304def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> {
1305  let arguments = (ins I32:$operand);
1306}
1307
1308// Test that we can bind to an op without results and reference it later.
1309def : Pat<(OpSymbolBindingNoResult:$op $operand),
1310          (NativeCodeCallVoid<"handleNoResultOp($_builder, $0)"> $op)>;
1311
1312//===----------------------------------------------------------------------===//
1313// Test Patterns (Attributes)
1314
1315// Test matching against op attributes.
1316def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> {
1317  let arguments = (ins
1318    I32Attr:$required_attr,
1319    OptionalAttr<I32Attr>:$optional_attr,
1320    DefaultValuedAttr<I32Attr, "42">:$default_valued_attr,
1321    I32Attr:$more_attr
1322  );
1323  let results = (outs I32);
1324}
1325def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> {
1326  let arguments = OpAttrMatch1.arguments;
1327  let results = (outs I32);
1328}
1329def MoreConstraint : AttrConstraint<
1330    CPred<"$_self.cast<IntegerAttr>().getInt() == 4">, "more constraint">;
1331def : Pat<(OpAttrMatch1 $required, $optional, $default_valued,
1332                        MoreConstraint:$more),
1333          (OpAttrMatch2 $required, $optional, $default_valued, $more)>;
1334
1335// Test unit attrs.
1336def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> {
1337  let arguments = (ins UnitAttr:$attr);
1338  let results = (outs I32);
1339}
1340def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> {
1341  let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2);
1342  let results = (outs I32);
1343}
1344def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>;
1345
1346// Test with constant attr.
1347def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>;
1348def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>;
1349
1350// Test integer enum attribute in rewrites.
1351def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>;
1352def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>;
1353
1354//===----------------------------------------------------------------------===//
1355// Test Patterns (Multi-result Ops)
1356
1357def MultiResultOpKind1: I64EnumAttrCase<"kind1", 1>;
1358def MultiResultOpKind2: I64EnumAttrCase<"kind2", 2>;
1359def MultiResultOpKind3: I64EnumAttrCase<"kind3", 3>;
1360def MultiResultOpKind4: I64EnumAttrCase<"kind4", 4>;
1361def MultiResultOpKind5: I64EnumAttrCase<"kind5", 5>;
1362def MultiResultOpKind6: I64EnumAttrCase<"kind6", 6>;
1363
1364def MultiResultOpEnum: I64EnumAttr<
1365  "MultiResultOpEnum", "Multi-result op kinds", [
1366    MultiResultOpKind1, MultiResultOpKind2, MultiResultOpKind3,
1367    MultiResultOpKind4, MultiResultOpKind5, MultiResultOpKind6
1368  ]>;
1369
1370def ThreeResultOp : TEST_Op<"three_result"> {
1371  let arguments = (ins MultiResultOpEnum:$kind);
1372  let results = (outs I32:$result1, F32:$result2, F32:$result3);
1373}
1374
1375def AnotherThreeResultOp
1376    : TEST_Op<"another_three_result",
1377              [DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
1378  let arguments = (ins MultiResultOpEnum:$kind);
1379  let results = (outs I32:$result1, F32:$result2, F32:$result3);
1380}
1381
1382def TwoResultOp : TEST_Op<"two_result"> {
1383  let arguments = (ins MultiResultOpEnum:$kind);
1384  let results = (outs I32:$result1, F32:$result2);
1385}
1386
1387def AnotherTwoResultOp : TEST_Op<"another_two_result"> {
1388  let arguments = (ins MultiResultOpEnum:$kind);
1389  let results = (outs F32:$result1, F32:$result2);
1390}
1391
1392def OneResultOp1 : TEST_Op<"one_result1"> {
1393  let arguments = (ins MultiResultOpEnum:$kind);
1394  let results = (outs F32:$result1);
1395}
1396
1397def OneResultOp2 : TEST_Op<"one_result2"> {
1398  let arguments = (ins MultiResultOpEnum:$kind);
1399  let results = (outs I32:$result1);
1400}
1401
1402def OneResultOp3 : TEST_Op<"one_result3"> {
1403  let arguments = (ins F32);
1404  let results = (outs I32:$result1);
1405}
1406
1407// Test using multi-result op as a whole
1408def : Pat<(ThreeResultOp MultiResultOpKind1:$kind),
1409          (AnotherThreeResultOp $kind)>;
1410
1411// Test using multi-result op as a whole for partial replacement
1412def : Pattern<(ThreeResultOp MultiResultOpKind2:$kind),
1413              [(TwoResultOp $kind),
1414               (OneResultOp1 $kind)]>;
1415def : Pattern<(ThreeResultOp MultiResultOpKind3:$kind),
1416              [(OneResultOp2 $kind),
1417               (AnotherTwoResultOp $kind)]>;
1418
1419// Test using results separately in a multi-result op
1420def : Pattern<(ThreeResultOp MultiResultOpKind4:$kind),
1421              [(TwoResultOp:$res1__0 $kind),
1422               (OneResultOp1 $kind),
1423               (TwoResultOp:$res2__1 $kind)]>;
1424
1425// Test referencing a single value in the value pack
1426// This rule only matches TwoResultOp if its second result has no use.
1427def : Pattern<(TwoResultOp:$res MultiResultOpKind5:$kind),
1428              [(OneResultOp2 $kind),
1429               (OneResultOp1 $kind)],
1430              [(HasNoUseOf:$res__1)]>;
1431
1432// Test using auxiliary ops for replacing multi-result op
1433def : Pattern<
1434    (ThreeResultOp MultiResultOpKind6:$kind), [
1435        // Auxiliary op generated to help building the final result but not
1436        // directly used to replace the source op's results.
1437        (TwoResultOp:$interm $kind),
1438
1439        (OneResultOp3 $interm__1),
1440        (AnotherTwoResultOp $kind)
1441    ]>;
1442
1443//===----------------------------------------------------------------------===//
1444// Test Patterns (Variadic Ops)
1445
1446def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> {
1447  let arguments = (ins Variadic<I32>);
1448  let results = (outs Variadic<I32>);
1449}
1450def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> {
1451  let arguments = (ins Variadic<I32>);
1452  let results = (outs Variadic<I32>);
1453}
1454
1455// Rewrite an op with one variadic operand and one variadic result to
1456// another similar op.
1457def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>;
1458
1459def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1",
1460                               [SameVariadicOperandSize]> {
1461  let arguments = (ins
1462    Variadic<I32>:$input1,
1463    F32:$input2,
1464    Variadic<I32>:$input3
1465  );
1466}
1467
1468def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2",
1469                               [SameVariadicOperandSize]> {
1470  let arguments = (ins
1471    Variadic<I32>:$input1,
1472    F32:$input2,
1473    Variadic<I32>:$input3
1474  );
1475}
1476
1477// Rewrite an op with both variadic operands and normal operands.
1478def : Pat<(MixedVOperandOp1 $input1, $input2, $input3),
1479          (MixedVOperandOp2 $input1, $input2, $input3)>;
1480
1481def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> {
1482  let results = (outs
1483    Variadic<I32>:$output1,
1484    F32:$output2,
1485    Variadic<I32>:$output3
1486  );
1487}
1488
1489def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> {
1490  let results = (outs
1491    Variadic<I32>:$output1,
1492    F32:$output2,
1493    Variadic<I32>:$output3
1494  );
1495}
1496
1497// Rewrite an op with both variadic results and normal results.
1498// Note that because we are generating the op with a top-level result pattern,
1499// we are able to deduce the correct result types for the generated op using
1500// the information from the matched root op.
1501def : Pat<(MixedVResultOp1), (MixedVResultOp2)>;
1502
1503def OneI32ResultOp : TEST_Op<"one_i32_out"> {
1504  let results = (outs I32);
1505}
1506
1507def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3",
1508                               [SameVariadicOperandSize]> {
1509  let arguments = (ins
1510    I32:$input1,
1511    Variadic<I32>:$input2,
1512    Variadic<I32>:$input3,
1513    I32Attr:$count
1514  );
1515
1516  let results = (outs I32);
1517}
1518
1519def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3",
1520                               [SameVariadicResultSize]> {
1521  let arguments = (ins I32Attr:$count);
1522
1523  let results = (outs
1524    I32:$output1,
1525    Variadic<I32>:$output2,
1526    Variadic<I32>:$output3
1527  );
1528
1529  // We will use this op in a nested result pattern, where we cannot deduce the
1530  // result type. So need to provide a builder not requiring result types.
1531  let builders = [
1532    OpBuilder<(ins "::mlir::IntegerAttr":$count),
1533    [{
1534      auto i32Type = $_builder.getIntegerType(32);
1535      $_state.addTypes(i32Type); // $output1
1536      SmallVector<Type, 4> types(count.getInt(), i32Type);
1537      $_state.addTypes(types); // $output2
1538      $_state.addTypes(types); // $output3
1539      $_state.addAttribute("count", count);
1540    }]>
1541  ];
1542}
1543
1544// Generates an op with variadic results using nested pattern.
1545def : Pat<(OneI32ResultOp),
1546          (MixedVOperandOp3
1547              (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">),
1548              (replaceWithValue $results__1),
1549              (replaceWithValue $results__2),
1550              ConstantAttr<I32Attr, "2">)>;
1551
1552//===----------------------------------------------------------------------===//
1553// Test Patterns (either)
1554
1555def TestEitherOpA : TEST_Op<"either_op_a"> {
1556  let arguments = (ins AnyInteger:$arg0, AnyInteger:$arg1, AnyInteger:$arg2);
1557  let results = (outs I32:$output);
1558}
1559
1560def TestEitherOpB : TEST_Op<"either_op_b"> {
1561  let arguments = (ins AnyInteger:$arg0);
1562  let results = (outs I32:$output);
1563}
1564
1565def : Pat<(TestEitherOpA (either I32:$arg1, I16:$arg2), $_),
1566          (TestEitherOpB $arg2)>;
1567
1568def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1), I16:$arg2), $_),
1569          (TestEitherOpB $arg2)>;
1570
1571def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1),
1572                                 (TestEitherOpB I16:$arg2)),
1573                          $_),
1574          (TestEitherOpB $arg2)>;
1575
1576//===----------------------------------------------------------------------===//
1577// Test Patterns (Location)
1578
1579// Test that we can specify locations for generated ops.
1580def : Pat<(TestLocationSrcOp:$res1
1581           (TestLocationSrcOp:$res2
1582            (TestLocationSrcOp:$res3 $input))),
1583          (TestLocationDstOp
1584            (TestLocationDstOp
1585              (TestLocationDstOp $input, (location $res1)),
1586              (location "named")),
1587            (location "fused", $res2, $res3))>;
1588
1589// Test that we can use the location of an op without results
1590def : Pat<(TestLocationSrcNoResOp:$loc
1591            (TestLocationSrcOp (TestLocationSrcOp $input))),
1592          (TestLocationDstNoResOp $input, (location $loc))>;
1593
1594//===----------------------------------------------------------------------===//
1595// Test Patterns (Type Builders)
1596
1597def SourceOp : TEST_Op<"source_op"> {
1598  let arguments = (ins AnyInteger:$arg, AnyI32Attr:$tag);
1599  let results = (outs AnyInteger);
1600}
1601
1602// An op without return type deduction.
1603def OpX : TEST_Op<"op_x"> {
1604  let arguments = (ins AnyInteger:$input);
1605  let results = (outs AnyInteger);
1606}
1607
1608// Test that ops without built-in type deduction can be created in the
1609// replacement DAG with an explicitly specified type.
1610def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "11">:$attr),
1611          (OpX (OpX $val, (returnType "$_builder.getI32Type()")))>;
1612// Test NativeCodeCall type builder can accept arguments.
1613def SameTypeAs : NativeCodeCall<"$0.getType()">;
1614
1615def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "22">:$attr),
1616          (OpX (OpX $val, (returnType (SameTypeAs $val))))>;
1617
1618// Test multiple return types.
1619def MakeI64Type : NativeCodeCall<"$_builder.getI64Type()">;
1620def MakeI32Type : NativeCodeCall<"$_builder.getI32Type()">;
1621
1622def OneToTwo : TEST_Op<"one_to_two"> {
1623  let arguments = (ins AnyInteger);
1624  let results = (outs AnyInteger, AnyInteger);
1625}
1626
1627def TwoToOne : TEST_Op<"two_to_one"> {
1628  let arguments = (ins AnyInteger, AnyInteger);
1629  let results = (outs AnyInteger);
1630}
1631
1632def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "33">:$attr),
1633          (TwoToOne (OpX (OneToTwo:$res__0 $val, (returnType (MakeI64Type), (MakeI32Type))), (returnType (MakeI32Type))),
1634                    (OpX $res__1, (returnType (MakeI64Type))))>;
1635
1636// Test copy value return type.
1637def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "44">:$attr),
1638          (OpX (OpX $val, (returnType $val)))>;
1639
1640// Test create multiple return types with different methods.
1641def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "55">:$attr),
1642          (TwoToOne (OneToTwo:$res__0 $val, (returnType $val, "$_builder.getI64Type()")), $res__1)>;
1643
1644//===----------------------------------------------------------------------===//
1645// Test Patterns (Trailing Directives)
1646
1647// Test that we can specify both `location` and `returnType` directives.
1648def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "66">:$attr),
1649          (TwoToOne (OpX $val, (returnType $val), (location "loc1")),
1650                    (OpX $val, (location "loc2"), (returnType $val)))>;
1651
1652//===----------------------------------------------------------------------===//
1653// Test Legalization
1654//===----------------------------------------------------------------------===//
1655
1656def Test_LegalizerEnum_Success : ConstantStrAttr<StrAttr, "Success">;
1657def Test_LegalizerEnum_Failure : ConstantStrAttr<StrAttr, "Failure">;
1658
1659def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>;
1660def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>;
1661def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>;
1662def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>;
1663def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>;
1664def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>;
1665def ILLegalOpG : TEST_Op<"illegal_op_g">, Results<(outs I32)>;
1666def LegalOpA : TEST_Op<"legal_op_a">,
1667  Arguments<(ins StrAttr:$status)>, Results<(outs I32)>;
1668def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>;
1669def LegalOpC : TEST_Op<"legal_op_c">,
1670  Arguments<(ins I32)>, Results<(outs I32)>;
1671
1672// Check that the conversion infrastructure can properly undo the creation of
1673// operations where an operation was created before its parent, in this case,
1674// in the parent's builder.
1675def IllegalOpTerminator : TEST_Op<"illegal_op_terminator", [Terminator]>;
1676def IllegalOpWithRegion : TEST_Op<"illegal_op_with_region"> {
1677  let skipDefaultBuilders = 1;
1678  let builders = [OpBuilder<(ins),
1679    [{
1680       Region *bodyRegion = $_state.addRegion();
1681       OpBuilder::InsertionGuard g($_builder);
1682       Block *body = $_builder.createBlock(bodyRegion);
1683       $_builder.setInsertionPointToEnd(body);
1684       $_builder.create<IllegalOpTerminator>($_state.location);
1685    }]>];
1686}
1687def IllegalOpWithRegionAnchor : TEST_Op<"illegal_op_with_region_anchor">;
1688
1689// Check that smaller pattern depths are chosen, i.e. prioritize more direct
1690// mappings.
1691def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>;
1692
1693def : Pat<(ILLegalOpA), (ILLegalOpB)>;
1694def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>;
1695
1696// Check that the higher benefit pattern is taken for multiple legalizations
1697// with the same depth.
1698def : Pat<(ILLegalOpC), (ILLegalOpD)>;
1699def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>;
1700
1701def : Pat<(ILLegalOpC), (ILLegalOpE), [], (addBenefit 10)>;
1702def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>;
1703
1704// Check that patterns use the most up-to-date value when being replaced.
1705def TestRewriteOp : TEST_Op<"rewrite">,
1706  Arguments<(ins AnyType)>, Results<(outs AnyType)>;
1707def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>;
1708
1709// Check that patterns can specify bounded recursion when rewriting.
1710def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> {
1711  let arguments = (ins I64Attr:$depth);
1712  let assemblyFormat = "$depth attr-dict";
1713}
1714
1715// Test legalization pattern: this op will be erase and will also erase the
1716// producer of its operand.
1717def BlackHoleOp : TEST_Op<"blackhole">,
1718  Arguments<(ins AnyType)>;
1719
1720//===----------------------------------------------------------------------===//
1721// Test Type Legalization
1722//===----------------------------------------------------------------------===//
1723
1724def TestRegionBuilderOp : TEST_Op<"region_builder">;
1725def TestReturnOp : TEST_Op<"return", [ReturnLike, Terminator]> {
1726  let arguments = (ins Variadic<AnyType>);
1727  let builders = [OpBuilder<(ins),
1728    [{ build($_builder, $_state, {}); }]>
1729  ];
1730}
1731def TestCastOp : TEST_Op<"cast">,
1732  Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>;
1733def TestInvalidOp : TEST_Op<"invalid", [Terminator]>,
1734  Arguments<(ins Variadic<AnyType>)>;
1735def TestTypeProducerOp : TEST_Op<"type_producer">,
1736  Results<(outs AnyType)>;
1737def TestAnotherTypeProducerOp : TEST_Op<"another_type_producer">,
1738  Results<(outs AnyType)>;
1739def TestTypeConsumerOp : TEST_Op<"type_consumer">,
1740  Arguments<(ins AnyType)>;
1741def TestTypeChangerOp : TEST_Op<"type_changer">,
1742  Arguments<(ins AnyType)>, Results<(outs AnyType)>;
1743def TestValidOp : TEST_Op<"valid", [Terminator]>,
1744  Arguments<(ins Variadic<AnyType>)>;
1745
1746def TestMergeBlocksOp : TEST_Op<"merge_blocks"> {
1747  let summary = "merge_blocks operation";
1748  let description = [{
1749    Test op with multiple blocks that are merged with Dialect Conversion
1750  }];
1751
1752  let regions = (region AnyRegion:$body);
1753  let results = (outs Variadic<AnyType>:$result);
1754}
1755
1756def TestRemappedValueRegionOp : TEST_Op<"remapped_value_region",
1757                                        [SingleBlock]> {
1758  let summary = "remapped_value_region operation";
1759  let description = [{
1760    Test op that remaps values that haven't yet been converted in Dialect
1761    Conversion.
1762  }];
1763
1764  let regions = (region SizedRegion<1>:$body);
1765  let results = (outs Variadic<AnyType>:$result);
1766}
1767
1768def TestSignatureConversionUndoOp : TEST_Op<"signature_conversion_undo"> {
1769  let regions = (region AnyRegion);
1770}
1771
1772def TestSignatureConversionNoConverterOp
1773  : TEST_Op<"signature_conversion_no_converter"> {
1774  let regions = (region AnyRegion);
1775}
1776
1777//===----------------------------------------------------------------------===//
1778// Test parser.
1779//===----------------------------------------------------------------------===//
1780
1781def ParseIntegerLiteralOp : TEST_Op<"parse_integer_literal"> {
1782  let results = (outs Variadic<Index>:$results);
1783  let hasCustomAssemblyFormat = 1;
1784}
1785
1786def ParseWrappedKeywordOp : TEST_Op<"parse_wrapped_keyword"> {
1787  let arguments = (ins StrAttr:$keyword);
1788  let hasCustomAssemblyFormat = 1;
1789}
1790
1791//===----------------------------------------------------------------------===//
1792// Test region argument list parsing.
1793
1794def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> {
1795  let summary =  "isolated region operation";
1796  let description = [{
1797    Test op with an isolated region, to test passthrough region arguments. Each
1798    argument is of index type.
1799  }];
1800
1801  let arguments = (ins Index);
1802  let regions = (region SizedRegion<1>:$region);
1803  let hasCustomAssemblyFormat = 1;
1804}
1805
1806def SSACFGRegionOp : TEST_Op<"ssacfg_region",  [
1807    DeclareOpInterfaceMethods<RegionKindInterface>]> {
1808  let summary =  "operation with an SSACFG region";
1809  let description = [{
1810    Test op that defines an SSACFG region.
1811  }];
1812
1813  let regions = (region VariadicRegion<AnyRegion>:$regions);
1814  let arguments = (ins Variadic<AnyType>);
1815  let results = (outs Variadic<AnyType>);
1816}
1817
1818def GraphRegionOp : TEST_Op<"graph_region",  [
1819    DeclareOpInterfaceMethods<RegionKindInterface>]> {
1820  let summary =  "operation with a graph region";
1821  let description = [{
1822    Test op that defines a graph region.
1823  }];
1824
1825  let regions = (region AnyRegion:$region);
1826  let assemblyFormat = "attr-dict-with-keyword $region";
1827}
1828
1829def AffineScopeOp : TEST_Op<"affine_scope", [AffineScope]> {
1830  let summary =  "affine scope operation";
1831  let description = [{
1832    Test op that defines a new affine scope.
1833  }];
1834
1835  let regions = (region SizedRegion<1>:$region);
1836  let hasCustomAssemblyFormat = 1;
1837}
1838
1839def WrappingRegionOp : TEST_Op<"wrapping_region",
1840    [SingleBlockImplicitTerminator<"TestReturnOp">]> {
1841  let summary =  "wrapping region operation";
1842  let description = [{
1843    Test op wrapping another op in a region, to test calling
1844    parseGenericOperation from the custom parser.
1845  }];
1846
1847  let results = (outs Variadic<AnyType>);
1848  let regions = (region SizedRegion<1>:$region);
1849  let hasCustomAssemblyFormat = 1;
1850}
1851
1852def PrettyPrintedRegionOp : TEST_Op<"pretty_printed_region",
1853    [SingleBlockImplicitTerminator<"TestReturnOp">]> {
1854  let summary =  "pretty_printed_region operation";
1855  let description = [{
1856    Test-op can be printed either in a "pretty" or "non-pretty" way based on
1857    some criteria. The custom parser parsers both the versions while testing
1858    APIs: parseCustomOperationName & parseGenericOperationAfterOpName.
1859  }];
1860  let arguments = (ins
1861    AnyType:$input1,
1862    AnyType:$input2
1863  );
1864
1865  let results = (outs AnyType);
1866  let regions = (region SizedRegion<1>:$region);
1867  let hasCustomAssemblyFormat = 1;
1868}
1869
1870def PolyForOp : TEST_Op<"polyfor", [OpAsmOpInterface]> {
1871  let summary =  "polyfor operation";
1872  let description = [{
1873    Test op with multiple region arguments, each argument of index type.
1874  }];
1875  let extraClassDeclaration = [{
1876    void getAsmBlockArgumentNames(mlir::Region &region,
1877                                  mlir::OpAsmSetValueNameFn setNameFn);
1878  }];
1879  let regions = (region SizedRegion<1>:$region);
1880  let hasCustomAssemblyFormat = 1;
1881}
1882
1883//===----------------------------------------------------------------------===//
1884// Test OpAsmInterface.
1885
1886def AsmInterfaceOp : TEST_Op<"asm_interface_op"> {
1887  let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results,
1888                      AnyType);
1889}
1890
1891def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> {
1892  let results = (outs AnyType);
1893}
1894
1895//===----------------------------------------------------------------------===//
1896// Test Op Asm Format
1897//===----------------------------------------------------------------------===//
1898
1899def FormatLiteralOp : TEST_Op<"format_literal_op"> {
1900  let assemblyFormat = [{
1901    `keyword_$.` `->` `:` `,` `=` `<` `>` `(` `)` `[` `]` `` `(` ` ` `)`
1902    `?` `+` `*` `{` `\n` `}` attr-dict
1903  }];
1904}
1905
1906// Test that we elide attributes that are within the syntax.
1907def FormatAttrOp : TEST_Op<"format_attr_op"> {
1908  let arguments = (ins I64Attr:$attr);
1909  let assemblyFormat = "$attr attr-dict";
1910}
1911
1912// Test that we elide optional attributes that are within the syntax.
1913def FormatOptAttrAOp : TEST_Op<"format_opt_attr_op_a"> {
1914  let arguments = (ins OptionalAttr<I64Attr>:$opt_attr);
1915  let assemblyFormat = "(`(` $opt_attr^ `)` )? attr-dict";
1916}
1917def FormatOptAttrBOp : TEST_Op<"format_opt_attr_op_b"> {
1918  let arguments = (ins OptionalAttr<I64Attr>:$opt_attr);
1919  let assemblyFormat = "($opt_attr^)? attr-dict";
1920}
1921
1922// Test that we format symbol name attributes properly.
1923def FormatSymbolNameAttrOp : TEST_Op<"format_symbol_name_attr_op"> {
1924  let arguments = (ins SymbolNameAttr:$attr);
1925  let assemblyFormat = "$attr attr-dict";
1926}
1927
1928// Test that we format optional symbol name attributes properly.
1929def FormatOptSymbolNameAttrOp : TEST_Op<"format_opt_symbol_name_attr_op"> {
1930  let arguments = (ins OptionalAttr<SymbolNameAttr>:$opt_attr);
1931  let assemblyFormat = "($opt_attr^)? attr-dict";
1932}
1933
1934// Test that we elide attributes that are within the syntax.
1935def FormatAttrDictWithKeywordOp : TEST_Op<"format_attr_dict_w_keyword"> {
1936  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$opt_attr);
1937  let assemblyFormat = "attr-dict-with-keyword";
1938}
1939
1940// Test that we don't need to provide types in the format if they are buildable.
1941def FormatBuildableTypeOp : TEST_Op<"format_buildable_type_op"> {
1942  let arguments = (ins I64:$buildable);
1943  let results = (outs I64:$buildable_res);
1944  let assemblyFormat = "$buildable attr-dict";
1945}
1946
1947// Test various mixings of region formatting.
1948class FormatRegionBase<string suffix, string fmt>
1949    : TEST_Op<"format_region_" # suffix # "_op"> {
1950  let regions = (region AnyRegion:$region);
1951  let assemblyFormat = fmt;
1952}
1953def FormatRegionAOp : FormatRegionBase<"a", [{
1954  regions attr-dict
1955}]>;
1956def FormatRegionBOp : FormatRegionBase<"b", [{
1957  $region attr-dict
1958}]>;
1959def FormatRegionCOp : FormatRegionBase<"c", [{
1960  (`region` $region^)? attr-dict
1961}]>;
1962class FormatVariadicRegionBase<string suffix, string fmt>
1963    : TEST_Op<"format_variadic_region_" # suffix # "_op"> {
1964  let regions = (region VariadicRegion<AnyRegion>:$regions);
1965  let assemblyFormat = fmt;
1966}
1967def FormatVariadicRegionAOp : FormatVariadicRegionBase<"a", [{
1968  $regions attr-dict
1969}]>;
1970def FormatVariadicRegionBOp : FormatVariadicRegionBase<"b", [{
1971  ($regions^ `found_regions`)? attr-dict
1972}]>;
1973class FormatRegionImplicitTerminatorBase<string suffix, string fmt>
1974    : TEST_Op<"format_implicit_terminator_region_" # suffix # "_op",
1975              [SingleBlockImplicitTerminator<"TestReturnOp">]> {
1976  let regions = (region AnyRegion:$region);
1977  let assemblyFormat = fmt;
1978}
1979def FormatFormatRegionImplicitTerminatorAOp
1980    : FormatRegionImplicitTerminatorBase<"a", [{
1981  $region attr-dict
1982}]>;
1983
1984// Test various mixings of result type formatting.
1985class FormatResultBase<string suffix, string fmt>
1986    : TEST_Op<"format_result_" # suffix # "_op"> {
1987  let results = (outs I64:$buildable_res, AnyMemRef:$result);
1988  let assemblyFormat = fmt;
1989}
1990def FormatResultAOp : FormatResultBase<"a", [{
1991  type($result) attr-dict
1992}]>;
1993def FormatResultBOp : FormatResultBase<"b", [{
1994  type(results) attr-dict
1995}]>;
1996def FormatResultCOp : FormatResultBase<"c", [{
1997  functional-type($buildable_res, $result) attr-dict
1998}]>;
1999
2000def FormatVariadicResult : TEST_Op<"format_variadic_result"> {
2001  let results = (outs Variadic<I64>:$result);
2002  let assemblyFormat = [{ `:` type($result) attr-dict}];
2003}
2004
2005def FormatMultipleVariadicResults : TEST_Op<"format_multiple_variadic_results",
2006                                            [AttrSizedResultSegments]> {
2007  let results = (outs Variadic<I64>:$result0, Variadic<AnyType>:$result1);
2008  let assemblyFormat = [{
2009    `:` `(` type($result0) `)` `,` `(` type($result1) `)` attr-dict
2010  }];
2011}
2012
2013// Test various mixings of operand type formatting.
2014class FormatOperandBase<string suffix, string fmt>
2015    : TEST_Op<"format_operand_" # suffix # "_op"> {
2016  let arguments = (ins I64:$buildable, AnyMemRef:$operand);
2017  let assemblyFormat = fmt;
2018}
2019
2020def FormatOperandAOp : FormatOperandBase<"a", [{
2021  operands `:` type(operands) attr-dict
2022}]>;
2023def FormatOperandBOp : FormatOperandBase<"b", [{
2024  operands `:` type($operand) attr-dict
2025}]>;
2026def FormatOperandCOp : FormatOperandBase<"c", [{
2027  $buildable `,` $operand `:` type(operands) attr-dict
2028}]>;
2029def FormatOperandDOp : FormatOperandBase<"d", [{
2030  $buildable `,` $operand `:` type($operand) attr-dict
2031}]>;
2032def FormatOperandEOp : FormatOperandBase<"e", [{
2033  $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict
2034}]>;
2035
2036def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> {
2037  let successors = (successor VariadicSuccessor<AnySuccessor>:$targets);
2038  let assemblyFormat = "$targets attr-dict";
2039}
2040
2041def FormatVariadicOperand : TEST_Op<"format_variadic_operand"> {
2042  let arguments = (ins Variadic<I64>:$operand);
2043  let assemblyFormat = [{ $operand `:` type($operand) attr-dict}];
2044}
2045def FormatVariadicOfVariadicOperand
2046   : TEST_Op<"format_variadic_of_variadic_operand"> {
2047  let arguments = (ins
2048    VariadicOfVariadic<I64, "operand_segments">:$operand,
2049    I32ElementsAttr:$operand_segments
2050  );
2051  let assemblyFormat = [{ $operand `:` type($operand) attr-dict}];
2052}
2053
2054def FormatMultipleVariadicOperands :
2055    TEST_Op<"format_multiple_variadic_operands", [AttrSizedOperandSegments]> {
2056  let arguments = (ins Variadic<I64>:$operand0, Variadic<AnyType>:$operand1);
2057  let assemblyFormat = [{
2058    ` ` `(` $operand0 `)` `,` `(` $operand1 `:` type($operand1) `)` attr-dict
2059  }];
2060}
2061
2062// Test various mixings of optional operand and result type formatting.
2063class FormatOptionalOperandResultOpBase<string suffix, string fmt>
2064    : TEST_Op<"format_optional_operand_result_" # suffix # "_op",
2065              [AttrSizedOperandSegments]> {
2066  let arguments = (ins Optional<I64>:$optional, Variadic<I64>:$variadic);
2067  let results = (outs Optional<I64>:$optional_res);
2068  let assemblyFormat = fmt;
2069}
2070
2071def FormatOptionalOperandResultAOp : FormatOptionalOperandResultOpBase<"a", [{
2072  `(` $optional `:` type($optional) `)` `:` type($optional_res)
2073  (`[` $variadic^ `]`)? attr-dict
2074}]>;
2075
2076def FormatOptionalOperandResultBOp : FormatOptionalOperandResultOpBase<"b", [{
2077  (`(` $optional^ `:` type($optional) `)`)? `:` type($optional_res)
2078  (`[` $variadic^ `]`)? attr-dict
2079}]>;
2080
2081// Test optional result type formatting.
2082class FormatOptionalResultOpBase<string suffix, string fmt>
2083    : TEST_Op<"format_optional_result_" # suffix # "_op",
2084              [AttrSizedResultSegments]> {
2085  let results = (outs Optional<I64>:$optional, Variadic<I64>:$variadic);
2086  let assemblyFormat = fmt;
2087}
2088def FormatOptionalResultAOp : FormatOptionalResultOpBase<"a", [{
2089  (`:` type($optional)^ `->` type($variadic))? attr-dict
2090}]>;
2091
2092def FormatOptionalResultBOp : FormatOptionalResultOpBase<"b", [{
2093  (`:` type($optional) `->` type($variadic)^)? attr-dict
2094}]>;
2095
2096def FormatOptionalResultCOp : FormatOptionalResultOpBase<"c", [{
2097  (`:` functional-type($optional, $variadic)^)? attr-dict
2098}]>;
2099
2100def FormatOptionalResultDOp
2101  : TEST_Op<"format_optional_result_d_op" > {
2102  let results = (outs Optional<F80>:$optional);
2103  let assemblyFormat = "(`:` type($optional)^)? attr-dict";
2104}
2105
2106def FormatTwoVariadicOperandsNoBuildableTypeOp
2107    : TEST_Op<"format_two_variadic_operands_no_buildable_type_op",
2108              [AttrSizedOperandSegments]> {
2109  let arguments = (ins Variadic<AnyType>:$a,
2110                       Variadic<AnyType>:$b);
2111  let assemblyFormat = [{
2112    `(` $a `:` type($a) `)` `->` `(` $b `:` type($b) `)`  attr-dict
2113  }];
2114}
2115
2116def FormatInferVariadicTypeFromNonVariadic
2117    : TEST_Op<"format_infer_variadic_type_from_non_variadic",
2118              [SameOperandsAndResultType]> {
2119  let arguments = (ins Variadic<AnyType>:$args);
2120  let results = (outs AnyType:$result);
2121  let assemblyFormat = "$args attr-dict `:` type($result)";
2122}
2123
2124def FormatOptionalUnitAttr : TEST_Op<"format_optional_unit_attribute"> {
2125  let arguments = (ins UnitAttr:$is_optional);
2126  let assemblyFormat = "(`is_optional` $is_optional^)? attr-dict";
2127}
2128
2129def FormatOptionalUnitAttrNoElide
2130    : TEST_Op<"format_optional_unit_attribute_no_elide"> {
2131  let arguments = (ins UnitAttr:$is_optional);
2132  let assemblyFormat = "($is_optional^)? attr-dict";
2133}
2134
2135def FormatOptionalEnumAttr : TEST_Op<"format_optional_enum_attr"> {
2136  let arguments = (ins OptionalAttr<SomeI64Enum>:$attr);
2137  let assemblyFormat = "($attr^)? attr-dict";
2138}
2139
2140def FormatOptionalWithElse : TEST_Op<"format_optional_else"> {
2141  let arguments = (ins UnitAttr:$isFirstBranchPresent);
2142  let assemblyFormat = "(`then` $isFirstBranchPresent^):(`else`)? attr-dict";
2143}
2144
2145def FormatCompoundAttr : TEST_Op<"format_compound_attr"> {
2146  let arguments = (ins CompoundAttrA:$compound);
2147  let assemblyFormat = "$compound attr-dict-with-keyword";
2148}
2149
2150def FormatNestedAttr : TEST_Op<"format_nested_attr"> {
2151  let arguments = (ins CompoundAttrNested:$nested);
2152  let assemblyFormat = "$nested attr-dict-with-keyword";
2153}
2154
2155def FormatNestedCompoundAttr : TEST_Op<"format_cpmd_nested_attr"> {
2156  let arguments = (ins CompoundNestedOuter:$nested);
2157  let assemblyFormat = "`nested` $nested attr-dict-with-keyword";
2158}
2159
2160def FormatQualifiedCompoundAttr : TEST_Op<"format_qual_cpmd_nested_attr"> {
2161  let arguments = (ins CompoundNestedOuter:$nested);
2162  let assemblyFormat = "`nested` qualified($nested) attr-dict-with-keyword";
2163}
2164
2165def FormatNestedType : TEST_Op<"format_cpmd_nested_type"> {
2166  let arguments = (ins CompoundNestedOuterType:$nested);
2167  let assemblyFormat = "$nested `nested` type($nested) attr-dict-with-keyword";
2168}
2169
2170def FormatQualifiedNestedType : TEST_Op<"format_qual_cpmd_nested_type"> {
2171  let arguments = (ins CompoundNestedOuterType:$nested);
2172  let assemblyFormat = "$nested `nested` qualified(type($nested)) attr-dict-with-keyword";
2173}
2174
2175//===----------------------------------------------------------------------===//
2176// Custom Directives
2177
2178def FormatCustomDirectiveOperands
2179    : TEST_Op<"format_custom_directive_operands", [AttrSizedOperandSegments]> {
2180  let arguments = (ins I64:$operand, Optional<I64>:$optOperand,
2181                       Variadic<I64>:$varOperands);
2182  let assemblyFormat = [{
2183    custom<CustomDirectiveOperands>(
2184      $operand, $optOperand, $varOperands
2185    )
2186    attr-dict
2187  }];
2188}
2189
2190def FormatCustomDirectiveOperandsAndTypes
2191    : TEST_Op<"format_custom_directive_operands_and_types",
2192              [AttrSizedOperandSegments]> {
2193  let arguments = (ins AnyType:$operand, Optional<AnyType>:$optOperand,
2194                       Variadic<AnyType>:$varOperands);
2195  let assemblyFormat = [{
2196    custom<CustomDirectiveOperandsAndTypes>(
2197      $operand, $optOperand, $varOperands,
2198      type($operand), type($optOperand), type($varOperands)
2199    )
2200    attr-dict
2201  }];
2202}
2203
2204def FormatCustomDirectiveRegions : TEST_Op<"format_custom_directive_regions"> {
2205  let regions = (region AnyRegion:$region, VariadicRegion<AnyRegion>:$other_regions);
2206  let assemblyFormat = [{
2207    custom<CustomDirectiveRegions>(
2208      $region, $other_regions
2209    )
2210    attr-dict
2211  }];
2212}
2213
2214def FormatCustomDirectiveResults
2215    : TEST_Op<"format_custom_directive_results", [AttrSizedResultSegments]> {
2216  let results = (outs AnyType:$result, Optional<AnyType>:$optResult,
2217                      Variadic<AnyType>:$varResults);
2218  let assemblyFormat = [{
2219    custom<CustomDirectiveResults>(
2220      type($result), type($optResult), type($varResults)
2221    )
2222    attr-dict
2223  }];
2224}
2225
2226def FormatCustomDirectiveResultsWithTypeRefs
2227    : TEST_Op<"format_custom_directive_results_with_type_refs",
2228              [AttrSizedResultSegments]> {
2229  let results = (outs AnyType:$result, Optional<AnyType>:$optResult,
2230                      Variadic<AnyType>:$varResults);
2231  let assemblyFormat = [{
2232    custom<CustomDirectiveResults>(
2233      type($result), type($optResult), type($varResults)
2234    )
2235    custom<CustomDirectiveWithTypeRefs>(
2236      ref(type($result)), ref(type($optResult)), ref(type($varResults))
2237    )
2238    attr-dict
2239  }];
2240}
2241
2242def FormatCustomDirectiveWithOptionalOperandRef
2243    : TEST_Op<"format_custom_directive_with_optional_operand_ref"> {
2244  let arguments = (ins Optional<I64>:$optOperand);
2245  let assemblyFormat = [{
2246    ($optOperand^)? `:`
2247    custom<CustomDirectiveOptionalOperandRef>(ref($optOperand))
2248    attr-dict
2249  }];
2250}
2251
2252def FormatCustomDirectiveSuccessors
2253    : TEST_Op<"format_custom_directive_successors", [Terminator]> {
2254  let successors = (successor AnySuccessor:$successor,
2255                              VariadicSuccessor<AnySuccessor>:$successors);
2256  let assemblyFormat = [{
2257    custom<CustomDirectiveSuccessors>(
2258      $successor, $successors
2259    )
2260    attr-dict
2261  }];
2262}
2263
2264def FormatCustomDirectiveAttributes
2265    : TEST_Op<"format_custom_directive_attributes"> {
2266  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr);
2267  let assemblyFormat = [{
2268    custom<CustomDirectiveAttributes>(
2269      $attr, $optAttr
2270    )
2271    attr-dict
2272  }];
2273}
2274
2275def FormatCustomDirectiveAttrDict
2276    : TEST_Op<"format_custom_directive_attrdict"> {
2277  let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr);
2278  let assemblyFormat = [{
2279    custom<CustomDirectiveAttrDict>( attr-dict )
2280  }];
2281}
2282
2283def FormatLiteralFollowingOptionalGroup
2284    : TEST_Op<"format_literal_following_optional_group"> {
2285  let arguments = (ins TypeAttr:$type, OptionalAttr<AnyAttr>:$value);
2286  let assemblyFormat = "(`(` $value^ `)`)? `:` $type attr-dict";
2287}
2288
2289//===----------------------------------------------------------------------===//
2290// AllTypesMatch type inference
2291
2292def FormatAllTypesMatchVarOp : TEST_Op<"format_all_types_match_var", [
2293    AllTypesMatch<["value1", "value2", "result"]>
2294  ]> {
2295  let arguments = (ins AnyType:$value1, AnyType:$value2);
2296  let results = (outs AnyType:$result);
2297  let assemblyFormat = "attr-dict $value1 `,` $value2 `:` type($value1)";
2298}
2299
2300def FormatAllTypesMatchAttrOp : TEST_Op<"format_all_types_match_attr", [
2301    AllTypesMatch<["value1", "value2", "result"]>
2302  ]> {
2303  let arguments = (ins AnyAttr:$value1, AnyType:$value2);
2304  let results = (outs AnyType:$result);
2305  let assemblyFormat = "attr-dict $value1 `,` $value2";
2306}
2307
2308//===----------------------------------------------------------------------===//
2309// TypesMatchWith type inference
2310
2311def FormatTypesMatchVarOp : TEST_Op<"format_types_match_var", [
2312    TypesMatchWith<"result type matches operand", "value", "result", "$_self">
2313  ]> {
2314  let arguments = (ins AnyType:$value);
2315  let results = (outs AnyType:$result);
2316  let assemblyFormat = "attr-dict $value `:` type($value)";
2317}
2318
2319def FormatTypesMatchVariadicOp : TEST_Op<"format_types_match_variadic", [
2320    RangedTypesMatchWith<"result type matches operand", "value", "result",
2321                         "llvm::make_range($_self.begin(), $_self.end())">
2322  ]> {
2323  let arguments = (ins Variadic<AnyType>:$value);
2324  let results = (outs Variadic<AnyType>:$result);
2325  let assemblyFormat = "attr-dict $value `:` type($value)";
2326}
2327
2328def FormatTypesMatchAttrOp : TEST_Op<"format_types_match_attr", [
2329    TypesMatchWith<"result type matches constant", "value", "result", "$_self">
2330  ]> {
2331  let arguments = (ins AnyAttr:$value);
2332  let results = (outs AnyType:$result);
2333  let assemblyFormat = "attr-dict $value";
2334}
2335
2336def FormatTypesMatchContextOp : TEST_Op<"format_types_match_context", [
2337    TypesMatchWith<"tuple result type matches operand type", "value", "result",
2338        "::mlir::TupleType::get($_ctxt, $_self)">
2339  ]> {
2340  let arguments = (ins AnyType:$value);
2341  let results = (outs AnyType:$result);
2342  let assemblyFormat = "attr-dict $value `:` type($value)";
2343}
2344
2345//===----------------------------------------------------------------------===//
2346// InferTypeOpInterface type inference in assembly format
2347
2348def FormatInferTypeOp : TEST_Op<"format_infer_type", [InferTypeOpInterface]> {
2349  let results = (outs AnyType);
2350  let assemblyFormat = "attr-dict";
2351
2352  let extraClassDeclaration = [{
2353    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2354          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2355          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2356          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2357      inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)});
2358      return ::mlir::success();
2359    }
2360   }];
2361}
2362
2363// Check that formatget supports DeclareOpInterfaceMethods.
2364def FormatInferType2Op : TEST_Op<"format_infer_type2", [DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
2365  let results = (outs AnyType);
2366  let assemblyFormat = "attr-dict";
2367}
2368
2369// Base class for testing mixing allOperandTypes, allOperands, and
2370// inferResultTypes.
2371class FormatInferAllTypesBaseOp<string mnemonic, list<Trait> traits = []>
2372    : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> {
2373  let arguments = (ins Variadic<AnyType>:$args);
2374  let results = (outs Variadic<AnyType>:$outs);
2375  let extraClassDeclaration = [{
2376    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2377          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2378          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2379          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2380      ::mlir::TypeRange operandTypes = operands.getTypes();
2381      inferredReturnTypes.assign(operandTypes.begin(), operandTypes.end());
2382      return ::mlir::success();
2383    }
2384   }];
2385}
2386
2387// Test inferReturnTypes is called when allOperandTypes and allOperands is true.
2388def FormatInferTypeAllOperandsAndTypesOp
2389    : FormatInferAllTypesBaseOp<"format_infer_type_all_operands_and_types"> {
2390  let assemblyFormat = "`(` operands `)` attr-dict `:` type(operands)";
2391}
2392
2393// Test inferReturnTypes is called when allOperandTypes is true and there is one
2394// ODS operand.
2395def FormatInferTypeAllOperandsAndTypesOneOperandOp
2396    : FormatInferAllTypesBaseOp<"format_infer_type_all_types_one_operand"> {
2397  let assemblyFormat = "`(` $args `)` attr-dict `:` type(operands)";
2398}
2399
2400// Test inferReturnTypes is called when allOperandTypes is true and there are
2401// more than one ODS operands.
2402def FormatInferTypeAllOperandsAndTypesTwoOperandsOp
2403    : FormatInferAllTypesBaseOp<"format_infer_type_all_types_two_operands",
2404                                [SameVariadicOperandSize]> {
2405  let arguments = (ins Variadic<AnyType>:$args0, Variadic<AnyType>:$args1);
2406  let assemblyFormat = "`(` $args0 `)` `(` $args1 `)` attr-dict `:` type(operands)";
2407}
2408
2409// Test inferReturnTypes is called when allOperands is true and operand types
2410// are separately specified.
2411def FormatInferTypeAllTypesOp
2412    : FormatInferAllTypesBaseOp<"format_infer_type_all_types"> {
2413  let assemblyFormat = "`(` operands `)` attr-dict `:` type($args)";
2414}
2415
2416// Test inferReturnTypes coupled with regions.
2417def FormatInferTypeRegionsOp
2418    : TEST_Op<"format_infer_type_regions", [InferTypeOpInterface]> {
2419  let results = (outs Variadic<AnyType>:$outs);
2420  let regions = (region AnyRegion:$region);
2421  let assemblyFormat = "$region attr-dict";
2422  let extraClassDeclaration = [{
2423    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2424          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2425          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2426          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2427      if (regions.empty())
2428        return ::mlir::failure();
2429      auto types = regions.front()->getArgumentTypes();
2430      inferredReturnTypes.assign(types.begin(), types.end());
2431      return ::mlir::success();
2432    }
2433  }];
2434}
2435
2436// Test inferReturnTypes coupled with variadic operands (operand_segment_sizes).
2437def FormatInferTypeVariadicOperandsOp
2438    : TEST_Op<"format_infer_type_variadic_operands",
2439              [InferTypeOpInterface, AttrSizedOperandSegments]> {
2440  let arguments = (ins Variadic<I32>:$a, Variadic<I64>:$b);
2441  let results = (outs Variadic<AnyType>:$outs);
2442  let assemblyFormat = "`(` $a `:` type($a) `)` `(` $b `:` type($b) `)` attr-dict";
2443  let extraClassDeclaration = [{
2444    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
2445          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2446          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2447          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2448      FormatInferTypeVariadicOperandsOpAdaptor adaptor(operands, attributes);
2449      auto aTypes = adaptor.getA().getTypes();
2450      auto bTypes = adaptor.getB().getTypes();
2451      inferredReturnTypes.append(aTypes.begin(), aTypes.end());
2452      inferredReturnTypes.append(bTypes.begin(), bTypes.end());
2453      return ::mlir::success();
2454    }
2455  }];
2456}
2457
2458//===----------------------------------------------------------------------===//
2459// Test SideEffects
2460//===----------------------------------------------------------------------===//
2461
2462def SideEffectOp : TEST_Op<"side_effect_op",
2463    [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
2464     DeclareOpInterfaceMethods<TestEffectOpInterface>]> {
2465  let results = (outs AnyType:$result);
2466}
2467
2468//===----------------------------------------------------------------------===//
2469// Test CopyOpInterface
2470//===----------------------------------------------------------------------===//
2471
2472def CopyOp : TEST_Op<"copy", [CopyOpInterface]> {
2473  let description = [{
2474    Represents a copy operation.
2475  }];
2476  let arguments = (ins Res<AnyRankedOrUnrankedMemRef, "", [MemRead]>:$source,
2477                   Res<AnyRankedOrUnrankedMemRef, "", [MemWrite]>:$target);
2478  let assemblyFormat = [{
2479    `(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)`
2480     attr-dict
2481  }];
2482}
2483
2484//===----------------------------------------------------------------------===//
2485// Test Buffer/Tensor
2486//===----------------------------------------------------------------------===//
2487
2488def RegionYieldOp : TEST_Op<"region_yield",
2489      [NoSideEffect, ReturnLike, Terminator]> {
2490  let description = [{
2491    This operation is used in a region and yields the corresponding type for
2492    that operation.
2493  }];
2494  let arguments = (ins AnyType:$result);
2495  let assemblyFormat = [{
2496    $result `:` type($result) attr-dict
2497  }];
2498  let builders = [OpBuilder<(ins),
2499    [{ build($_builder, $_state, {}); }]>
2500  ];
2501}
2502
2503class BufferBasedOpBase<string mnemonic, list<Trait> traits>
2504    : TEST_Op<mnemonic, traits> {
2505  let description = [{
2506    A buffer based operation, that uses memRefs as input and output.
2507  }];
2508  let arguments = (ins AnyRankedOrUnrankedMemRef:$input,
2509                       AnyRankedOrUnrankedMemRef:$output);
2510}
2511
2512def BufferBasedOp : BufferBasedOpBase<"buffer_based", []>{
2513  let assemblyFormat = [{
2514    `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`
2515    attr-dict
2516  }];
2517}
2518
2519def RegionBufferBasedOp : BufferBasedOpBase<"region_buffer_based",
2520      [SingleBlockImplicitTerminator<"RegionYieldOp">]> {
2521  let regions = (region AnyRegion:$region);
2522  let assemblyFormat = [{
2523    `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`
2524    $region attr-dict
2525  }];
2526}
2527
2528def TensorBasedOp : TEST_Op<"tensor_based", []> {
2529  let description = [{
2530    A tensor based operation, that uses a tensor as an input and results in a
2531    tensor again.
2532  }];
2533  let arguments = (ins AnyRankedTensor:$input);
2534  let results = (outs AnyRankedTensor:$result);
2535  let assemblyFormat = [{
2536    `in` `(` $input`:` type($input) `)` `->` type($result) attr-dict
2537  }];
2538}
2539
2540//===----------------------------------------------------------------------===//
2541// Test RegionBranchOpInterface
2542//===----------------------------------------------------------------------===//
2543
2544def RegionIfYieldOp : TEST_Op<"region_if_yield",
2545      [NoSideEffect, ReturnLike, Terminator]> {
2546  let arguments = (ins Variadic<AnyType>:$results);
2547  let assemblyFormat = [{
2548    $results `:` type($results) attr-dict
2549  }];
2550}
2551
2552def RegionIfOp : TEST_Op<"region_if",
2553      [DeclareOpInterfaceMethods<RegionBranchOpInterface,
2554                                 ["getRegionInvocationBounds"]>,
2555       SingleBlockImplicitTerminator<"RegionIfYieldOp">,
2556       RecursiveSideEffects]> {
2557  let description =[{
2558    Represents an abstract if-then-else-join pattern. In this context, the then
2559    and else regions jump to the join region, which finally returns to its
2560    parent op.
2561  }];
2562
2563  let arguments = (ins Variadic<AnyType>);
2564  let results = (outs Variadic<AnyType>:$results);
2565  let regions = (region SizedRegion<1>:$thenRegion,
2566                        AnyRegion:$elseRegion,
2567                        AnyRegion:$joinRegion);
2568  let extraClassDeclaration = [{
2569    ::mlir::Block::BlockArgListType getThenArgs() {
2570      return getBody(0)->getArguments();
2571    }
2572    ::mlir::Block::BlockArgListType getElseArgs() {
2573      return getBody(1)->getArguments();
2574    }
2575    ::mlir::Block::BlockArgListType getJoinArgs() {
2576      return getBody(2)->getArguments();
2577    }
2578    ::mlir::OperandRange getSuccessorEntryOperands(
2579        ::llvm::Optional<unsigned> index);
2580  }];
2581  let hasCustomAssemblyFormat = 1;
2582}
2583
2584def AnyCondOp : TEST_Op<"any_cond",
2585      [DeclareOpInterfaceMethods<RegionBranchOpInterface,
2586                                 ["getRegionInvocationBounds"]>,
2587       RecursiveSideEffects]> {
2588  let results = (outs Variadic<AnyType>:$results);
2589  let regions = (region AnyRegion:$region);
2590}
2591
2592//===----------------------------------------------------------------------===//
2593// Test TableGen generated build() methods
2594//===----------------------------------------------------------------------===//
2595
2596def TableGenConstant : TEST_Op<"tblgen_constant"> {
2597  let results = (outs AnyType);
2598}
2599
2600// No variadic args or results.
2601def TableGenBuildOp0 : TEST_Op<"tblgen_build_0"> {
2602  let arguments = (ins AnyType:$value);
2603  let results = (outs AnyType:$result);
2604}
2605
2606// Sigle variadic arg and single variadic results.
2607def TableGenBuildOp1 : TEST_Op<"tblgen_build_1"> {
2608  let arguments = (ins Variadic<AnyType>:$inputs);
2609  let results = (outs Variadic<AnyType>:$results);
2610}
2611
2612// Single variadic arg and non-variadic results.
2613def TableGenBuildOp2 : TEST_Op<"tblgen_build_2"> {
2614  let arguments = (ins Variadic<AnyType>:$inputs);
2615  let results = (outs AnyType:$result);
2616}
2617
2618// Single variadic arg and multiple variadic results.
2619def TableGenBuildOp3 : TEST_Op<"tblgen_build_3", [SameVariadicResultSize]> {
2620  let arguments = (ins Variadic<AnyType>:$inputs);
2621  let results = (outs Variadic<AnyType>:$resultA, Variadic<AnyType>:$resultB);
2622}
2623
2624// Single variadic arg, non variadic results, with SameOperandsAndResultType.
2625// Tests suppression of ambiguous build methods for operations with
2626// SameOperandsAndResultType trait.
2627def TableGenBuildOp4 : TEST_Op<"tblgen_build_4", [SameOperandsAndResultType]> {
2628  let arguments = (ins Variadic<AnyType>:$inputs);
2629  let results = (outs AnyType:$result);
2630}
2631
2632// Base class for testing `build` methods for ops with
2633// InferReturnTypeOpInterface.
2634class TableGenBuildInferReturnTypeBaseOp<string mnemonic,
2635                                         list<Trait> traits = []>
2636    : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> {
2637  let arguments = (ins Variadic<AnyType>:$inputs);
2638  let results = (outs AnyType:$result);
2639
2640  let extraClassDeclaration = [{
2641    static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *,
2642          ::llvm::Optional<::mlir::Location> location, ::mlir::ValueRange operands,
2643          ::mlir::DictionaryAttr attributes, ::mlir::RegionRange regions,
2644          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2645      inferredReturnTypes.assign({operands[0].getType()});
2646      return ::mlir::success();
2647    }
2648   }];
2649}
2650
2651// Op with InferTypeOpInterface and regions.
2652def TableGenBuildOp5 : TableGenBuildInferReturnTypeBaseOp<
2653    "tblgen_build_5", [InferTypeOpInterface]> {
2654  let regions = (region AnyRegion:$body);
2655}
2656
2657//===----------------------------------------------------------------------===//
2658// Test BufferPlacement
2659//===----------------------------------------------------------------------===//
2660
2661def GetTupleElementOp: TEST_Op<"get_tuple_element"> {
2662  let description = [{
2663    Test op that returns a specified element of the tuple.
2664  }];
2665
2666  let arguments = (ins
2667    TupleOf<[AnyType]>,
2668    I32Attr:$index
2669  );
2670  let results = (outs AnyType);
2671}
2672
2673def MakeTupleOp: TEST_Op<"make_tuple"> {
2674  let description = [{
2675    Test op that creates a tuple value from a list of values.
2676  }];
2677
2678  let arguments = (ins
2679    Variadic<AnyType>:$inputs
2680  );
2681  let results = (outs TupleOf<[AnyType]>);
2682}
2683
2684//===----------------------------------------------------------------------===//
2685// Test Target DataLayout
2686//===----------------------------------------------------------------------===//
2687
2688def OpWithDataLayoutOp : TEST_Op<"op_with_data_layout",
2689                                 [HasDefaultDLTIDataLayout, DataLayoutOpInterface]> {
2690  let summary =
2691      "An op that uses DataLayout implementation from the Target dialect";
2692  let regions = (region VariadicRegion<AnyRegion>:$regions);
2693}
2694
2695def DataLayoutQueryOp : TEST_Op<"data_layout_query"> {
2696  let summary = "A token op recognized by data layout query test pass";
2697  let description = [{
2698    The data layout query pass pattern-matches this op and attaches to it an
2699    array attribute containing the result of data layout query of the result
2700    type of this op.
2701  }];
2702
2703  let results = (outs AnyType:$res);
2704}
2705
2706//===----------------------------------------------------------------------===//
2707// Test Reducer Patterns
2708//===----------------------------------------------------------------------===//
2709
2710def OpCrashLong : TEST_Op<"op_crash_long"> {
2711  let arguments = (ins I32, I32, I32);
2712  let results = (outs I32);
2713}
2714
2715def OpCrashShort : TEST_Op<"op_crash_short"> {
2716  let results = (outs I32);
2717}
2718
2719def : Pat<(OpCrashLong $_, $_, $_), (OpCrashShort)>;
2720
2721//===----------------------------------------------------------------------===//
2722// Test LinalgConvolutionOpInterface.
2723//===----------------------------------------------------------------------===//
2724
2725def TestLinalgConvOpNotLinalgOp : TEST_Op<"conv_op_not_linalg_op", [
2726    LinalgConvolutionOpInterface]> {
2727  let arguments = (ins
2728    AnyType:$image, AnyType:$filter, AnyType:$output);
2729  let results = (outs AnyRankedTensor:$result);
2730}
2731
2732def TestLinalgConvOp :
2733  TEST_Op<"linalg_conv_op", [AttrSizedOperandSegments, SingleBlock,
2734      LinalgStructuredInterface, LinalgConvolutionOpInterface]> {
2735
2736  let arguments = (ins Variadic<AnyType>:$inputs,
2737    Variadic<AnyType>:$outputs);
2738  let results = (outs Variadic<AnyType>:$results);
2739  let regions = (region AnyRegion:$region);
2740
2741  let assemblyFormat = [{
2742    attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?
2743    `outs` `(` $outputs `:` type($outputs) `)`
2744    $region (`->` type($results)^)?
2745  }];
2746
2747  let extraClassDeclaration = [{
2748    bool hasIndexSemantics() { return false; }
2749
2750    static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,
2751                              mlir::ArrayRef<mlir::NamedAttribute> attrs) {
2752      b.create<mlir::linalg::YieldOp>(block.getArguments().back());
2753    }
2754
2755    static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,
2756                              mlir::ArrayRef<mlir::NamedAttribute>)>
2757    getRegionBuilder() {
2758      return &regionBuilder;
2759    }
2760
2761    mlir::ArrayAttr iterator_types() {
2762      return getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");
2763    }
2764
2765    mlir::ArrayAttr getIndexingMaps() {
2766      return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");
2767    }
2768
2769    std::string getLibraryCallName() {
2770      return "";
2771    }
2772
2773    // To conform with interface requirement on operand naming.
2774    mlir::ValueRange inputs() { return getInputs(); }
2775    mlir::ValueRange outputs() { return getOutputs(); }
2776  }];
2777}
2778
2779//===----------------------------------------------------------------------===//
2780// Test LinalgFillOpInterface.
2781//===----------------------------------------------------------------------===//
2782
2783def TestLinalgFillOpNotLinalgOp : TEST_Op<"fill_op_not_linalg_op", [
2784    LinalgFillOpInterface]> {
2785  let arguments = (ins
2786    AnyType:$value, AnyType:$output);
2787  let results = (outs AnyRankedTensor:$result);
2788}
2789
2790def TestLinalgFillOp :
2791  TEST_Op<"linalg_fill_op", [AttrSizedOperandSegments, SingleBlock,
2792      LinalgStructuredInterface, LinalgFillOpInterface]> {
2793
2794  let arguments = (ins Variadic<AnyType>:$inputs,
2795    Variadic<AnyType>:$outputs);
2796  let results = (outs Variadic<AnyType>:$results);
2797  let regions = (region AnyRegion:$region);
2798
2799  let assemblyFormat = [{
2800    attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?
2801    `outs` `(` $outputs `:` type($outputs) `)`
2802    $region (`->` type($results)^)?
2803  }];
2804
2805  let extraClassDeclaration = [{
2806    bool hasIndexSemantics() { return false; }
2807
2808    static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,
2809                              mlir::ArrayRef<mlir::NamedAttribute> attrs) {
2810      b.create<mlir::linalg::YieldOp>(block.getArguments().back());
2811    }
2812
2813    static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,
2814                              mlir::ArrayRef<mlir::NamedAttribute>)>
2815    getRegionBuilder() {
2816      return &regionBuilder;
2817    }
2818
2819    mlir::ArrayAttr iterator_types() {
2820      return getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");
2821    }
2822
2823    mlir::ArrayAttr getIndexingMaps() {
2824      return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");
2825    }
2826
2827    std::string getLibraryCallName() {
2828      return "";
2829    }
2830
2831    // To conform with interface requirement on operand naming.
2832    mlir::ValueRange inputs() { return getInputs(); }
2833    mlir::ValueRange outputs() { return getOutputs(); }
2834  }];
2835}
2836
2837//===----------------------------------------------------------------------===//
2838// Test Ops with Default-Valued String Attributes
2839//===----------------------------------------------------------------------===//
2840
2841def TestDefaultStrAttrNoValueOp : TEST_Op<"no_str_value"> {
2842  let arguments = (ins DefaultValuedAttr<StrAttr, "">:$value);
2843  let assemblyFormat = "attr-dict";
2844}
2845
2846def TestDefaultStrAttrHasValueOp : TEST_Op<"has_str_value"> {
2847  let arguments = (ins DefaultValuedStrAttr<StrAttr, "">:$value);
2848  let assemblyFormat = "attr-dict";
2849}
2850
2851def : Pat<(TestDefaultStrAttrNoValueOp $value),
2852          (TestDefaultStrAttrHasValueOp ConstantStrAttr<StrAttr, "foo">)>;
2853
2854//===----------------------------------------------------------------------===//
2855// Test Ops with effects
2856//===----------------------------------------------------------------------===//
2857
2858def TestResource : Resource<"TestResource">;
2859
2860def TestEffectsOpA : TEST_Op<"op_with_effects_a"> {
2861  let arguments = (ins
2862    Arg<Variadic<AnyMemRef>, "", [MemRead]>,
2863    Arg<FlatSymbolRefAttr, "", [MemRead]>:$first,
2864    Arg<SymbolRefAttr, "", [MemWrite]>:$second,
2865    Arg<OptionalAttr<SymbolRefAttr>, "", [MemRead]>:$optional_symbol
2866  );
2867
2868  let results = (outs Res<AnyMemRef, "", [MemAlloc<TestResource>]>);
2869}
2870
2871def TestEffectsOpB : TEST_Op<"op_with_effects_b",
2872    [MemoryEffects<[MemWrite<TestResource>]>]>;
2873
2874def TestEffectsRead : TEST_Op<"op_with_memread",
2875    [MemoryEffects<[MemRead]>]> {
2876  let results = (outs AnyInteger);
2877}
2878
2879def TestEffectsWrite : TEST_Op<"op_with_memwrite",
2880    [MemoryEffects<[MemWrite]>]>;
2881
2882def TestEffectsResult : TEST_Op<"test_effects_result"> {
2883  let results = (outs Res<I32, "", [MemAlloc, MemWrite]>);
2884}
2885
2886//===----------------------------------------------------------------------===//
2887// Test Ops with verifiers
2888//===----------------------------------------------------------------------===//
2889
2890def TestVerifiersOp : TEST_Op<"verifiers",
2891                              [SingleBlock, NoTerminator, IsolatedFromAbove]> {
2892  let arguments = (ins I32:$input);
2893  let regions = (region SizedRegion<1>:$region);
2894  let hasVerifier = 1;
2895  let hasRegionVerifier = 1;
2896}
2897
2898//===----------------------------------------------------------------------===//
2899// Test Loop Op with a graph region
2900//===----------------------------------------------------------------------===//
2901
2902// Test loop op with a graph region.
2903def TestGraphLoopOp : TEST_Op<"graph_loop",
2904                         [LoopLikeOpInterface, NoSideEffect,
2905                          RecursiveSideEffects, SingleBlock,
2906                          RegionKindInterface, HasOnlyGraphRegion]> {
2907  let arguments = (ins Variadic<AnyType>:$args);
2908  let results = (outs Variadic<AnyType>:$rets);
2909  let regions = (region SizedRegion<1>:$body);
2910
2911  let assemblyFormat = [{
2912    $args $body attr-dict `:` functional-type(operands, results)
2913  }];
2914
2915  let extraClassDeclaration = [{
2916    mlir::Region &getLoopBody() { return getBody(); }
2917  }];
2918}
2919
2920//===----------------------------------------------------------------------===//
2921// Test InferIntRangeInterface
2922//===----------------------------------------------------------------------===//
2923def TestWithBoundsOp : TEST_Op<"with_bounds",
2924                          [DeclareOpInterfaceMethods<InferIntRangeInterface>,
2925                           NoSideEffect]> {
2926  let arguments = (ins IndexAttr:$umin,
2927                       IndexAttr:$umax,
2928                       IndexAttr:$smin,
2929                       IndexAttr:$smax);
2930  let results = (outs Index:$fakeVal);
2931
2932  let assemblyFormat = "attr-dict";
2933}
2934
2935def TestWithBoundsRegionOp : TEST_Op<"with_bounds_region",
2936                          [DeclareOpInterfaceMethods<InferIntRangeInterface>,
2937                           SingleBlock, NoTerminator]> {
2938  let arguments = (ins IndexAttr:$umin,
2939                       IndexAttr:$umax,
2940                       IndexAttr:$smin,
2941                       IndexAttr:$smax);
2942  // The region has one argument of index type
2943  let regions = (region SizedRegion<1>:$region);
2944  let hasCustomAssemblyFormat = 1;
2945}
2946
2947def TestIncrementOp : TEST_Op<"increment",
2948                         [DeclareOpInterfaceMethods<InferIntRangeInterface>,
2949                         NoSideEffect]> {
2950  let arguments = (ins Index:$value);
2951  let results = (outs Index:$result);
2952
2953  let assemblyFormat = "attr-dict $value";
2954}
2955
2956def TestReflectBoundsOp : TEST_Op<"reflect_bounds",
2957                         [DeclareOpInterfaceMethods<InferIntRangeInterface>]> {
2958  let arguments = (ins Index:$value,
2959                       OptionalAttr<IndexAttr>:$umin,
2960                       OptionalAttr<IndexAttr>:$umax,
2961                       OptionalAttr<IndexAttr>:$smin,
2962                       OptionalAttr<IndexAttr>:$smax);
2963  let results = (outs Index:$result);
2964
2965  let assemblyFormat = "attr-dict $value";
2966}
2967#endif // TEST_OPS
2968