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