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