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