xref: /llvm-project/mlir/test/lib/Dialect/Test/TestOps.td (revision 8d6b24167b7bdc7ac9c969abe73be857bbcf2b5a)
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/Interfaces/FunctionInterfaces.td"
18include "mlir/IR/OpBase.td"
19include "mlir/IR/OpAsmInterface.td"
20include "mlir/IR/PatternBase.td"
21include "mlir/IR/RegionKindInterface.td"
22include "mlir/IR/SymbolInterfaces.td"
23include "mlir/Interfaces/CallInterfaces.td"
24include "mlir/Interfaces/ControlFlowInterfaces.td"
25include "mlir/Interfaces/CopyOpInterface.td"
26include "mlir/Interfaces/DataLayoutInterfaces.td"
27include "mlir/Interfaces/DestinationStyleOpInterface.td"
28include "mlir/Interfaces/InferIntRangeInterface.td"
29include "mlir/Interfaces/InferTypeOpInterface.td"
30include "mlir/Interfaces/LoopLikeInterface.td"
31include "mlir/Interfaces/MemorySlotInterfaces.td"
32include "mlir/Interfaces/SideEffectInterfaces.td"
33
34
35// Include the attribute definitions.
36include "TestAttrDefs.td"
37// Include the type definitions.
38include "TestTypeDefs.td"
39
40
41class TEST_Op<string mnemonic, list<Trait> traits = []> :
42    Op<Test_Dialect, mnemonic, traits>;
43
44//===----------------------------------------------------------------------===//
45// Test Types
46//===----------------------------------------------------------------------===//
47
48def IntTypesOp : TEST_Op<"int_types"> {
49  let results = (outs
50    AnyI16:$any_i16,
51    SI32:$si32,
52    UI64:$ui64,
53    AnyInteger:$any_int
54  );
55}
56
57def ComplexF64 : Complex<F64>;
58def ComplexOp : TEST_Op<"complex_f64"> {
59  let results = (outs ComplexF64);
60}
61
62def ComplexTensorOp : TEST_Op<"complex_f64_tensor"> {
63  let results = (outs TensorOf<[ComplexF64]>);
64}
65
66def TupleOp : TEST_Op<"tuple_32_bit"> {
67  let results = (outs TupleOf<[I32, F32]>);
68}
69
70def NestedTupleOp : TEST_Op<"nested_tuple_32_bit"> {
71  let results = (outs NestedTupleOf<[I32, F32]>);
72}
73
74def TakesStaticMemRefOp : TEST_Op<"takes_static_memref"> {
75  let arguments = (ins AnyStaticShapeMemRef:$x);
76}
77
78def RankLessThan2I8F32MemRefOp : TEST_Op<"rank_less_than_2_I8_F32_memref"> {
79  let results = (outs MemRefRankOf<[I8, F32], [0, 1]>);
80}
81
82def NDTensorOfOp : TEST_Op<"nd_tensor_of"> {
83  let arguments = (ins
84    0DTensorOf<[F32]>:$arg0,
85    1DTensorOf<[F32]>:$arg1,
86    2DTensorOf<[I16]>:$arg2,
87    3DTensorOf<[I16]>:$arg3,
88    4DTensorOf<[I16]>:$arg4
89  );
90}
91
92def RankedTensorOp : TEST_Op<"ranked_tensor_op"> {
93  let arguments = (ins AnyRankedTensor:$input);
94}
95
96def MultiTensorRankOf : TEST_Op<"multi_tensor_rank_of"> {
97  let arguments = (ins
98    TensorRankOf<[I8, I32, F32], [0, 1]>:$arg0
99  );
100}
101
102def TEST_TestType : DialectType<Test_Dialect,
103    CPred<"::llvm::isa<::test::TestType>($_self)">, "test">,
104    BuildableType<"$_builder.getType<::test::TestType>()">;
105
106//===----------------------------------------------------------------------===//
107// Test Symbols
108//===----------------------------------------------------------------------===//
109
110def SymbolOp : TEST_Op<"symbol", [NoMemoryEffect, Symbol]> {
111  let summary =  "operation which defines a new symbol";
112  let arguments = (ins StrAttr:$sym_name,
113                       OptionalAttr<StrAttr>:$sym_visibility);
114}
115
116def SymbolScopeOp : TEST_Op<"symbol_scope",
117    [SymbolTable, SingleBlockImplicitTerminator<"TerminatorOp">]> {
118  let summary =  "operation which defines a new symbol table";
119  let regions = (region SizedRegion<1>:$region);
120}
121
122def SymbolTableRegionOp : TEST_Op<"symbol_table_region", [SymbolTable]> {
123  let summary =  "operation which defines a new symbol table without a "
124                 "restriction on a terminator";
125  let regions = (region SizedRegion<1>:$region);
126}
127
128//===----------------------------------------------------------------------===//
129// Test Operands
130//===----------------------------------------------------------------------===//
131
132def MixedNormalVariadicOperandOp : TEST_Op<
133    "mixed_normal_variadic_operand", [SameVariadicOperandSize]> {
134  let arguments = (ins
135    Variadic<AnyTensor>:$input1,
136    AnyTensor:$input2,
137    Variadic<AnyTensor>:$input3
138  );
139}
140def VariadicWithSameOperandsResult :
141      TEST_Op<"variadic_with_same_operand_results",
142              [SameOperandsAndResultType]> {
143  let arguments = (ins Variadic<AnySignlessInteger>);
144  let results = (outs AnySignlessInteger:$result);
145}
146
147def SameOperandsResultType : TEST_Op<
148    "same_operand_result_type", [SameOperandsAndResultType]> {
149  let arguments = (ins AnyTensor:$operand);
150  let results = (outs AnyTensor:$result);
151}
152
153//===----------------------------------------------------------------------===//
154// Test Results
155//===----------------------------------------------------------------------===//
156
157def MixedNormalVariadicResults : TEST_Op<
158    "mixed_normal_variadic_result", [SameVariadicResultSize]> {
159  let results = (outs
160    Variadic<AnyTensor>:$output1,
161    AnyTensor:$output2,
162    Variadic<AnyTensor>:$output3
163  );
164}
165
166//===----------------------------------------------------------------------===//
167// Test Attributes
168//===----------------------------------------------------------------------===//
169
170def AnyAttrOfOp : TEST_Op<"any_attr_of_i32_str"> {
171  let arguments = (ins AnyAttrOf<[I32Attr, StrAttr]>:$attr);
172}
173
174def NonNegIntAttrOp : TEST_Op<"non_negative_int_attr"> {
175  let arguments = (ins
176      ConfinedAttr<I32Attr, [IntNonNegative]>:$i32attr,
177      ConfinedAttr<I64Attr, [IntNonNegative]>:$i64attr
178  );
179}
180
181def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> {
182  let arguments = (ins
183      ConfinedAttr<I32Attr, [IntPositive]>:$i32attr,
184      ConfinedAttr<I64Attr, [IntPositive]>:$i64attr
185  );
186}
187
188def TypeArrayAttrOp : TEST_Op<"type_array_attr"> {
189  let arguments = (ins TypeArrayAttr:$attr);
190}
191
192def TypeArrayAttrWithDefaultOp : TEST_Op<"type_array_attr_with_default"> {
193  let arguments = (ins DefaultValuedAttr<TypeArrayAttr, "{}">:$attr);
194}
195
196def TypedStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> {
197  let arguments = (ins TypedStrAttr<AnyInteger>:$attr);
198  let assemblyFormat = "$attr attr-dict";
199}
200
201def TypedStringAttrWithMixedTypeOp : TEST_Op<"string_attr_with_mixed_type"> {
202  let arguments = (ins
203    AnyAttrOf<[TypedStrAttr<AnyInteger>, I64Attr]>:$attr
204  );
205  let assemblyFormat = "$attr attr-dict";
206}
207
208def FloatAttrOp : TEST_Op<"float_attrs"> {
209  // TODO: Clean up the OpBase float type and attribute selectors so they
210  // can express all of the types.
211  let arguments = (ins
212    AnyAttr:$float_attr
213  );
214}
215
216def I32EnumAttrOp : TEST_Op<"i32_enum_attr"> {
217  let arguments = (ins SomeI32Enum:$attr);
218  let results = (outs I32:$val);
219}
220
221def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> {
222  let arguments = (ins SomeI64Enum:$attr);
223  let results = (outs I32:$val);
224}
225
226def IntAttrOp : TEST_Op<"int_attrs"> {
227  let arguments = (ins
228    AnyI32Attr:$any_i32_attr,
229    IndexAttr:$index_attr,
230    UI32Attr:$ui32_attr,
231    SI32Attr:$si32_attr
232  );
233}
234
235def FloatElementsAttrOp : TEST_Op<"float_elements_attr"> {
236  let arguments = (ins
237      RankedF32ElementsAttr<[2]>:$scalar_f32_attr,
238      RankedF64ElementsAttr<[4, 8]>:$tensor_f64_attr
239  );
240}
241
242def ContainingIntPolynomialAttrOp : TEST_Op<"containing_int_polynomial_attr"> {
243  let arguments = (ins NestedPolynomialAttr:$attr);
244  let assemblyFormat = "$attr attr-dict";
245}
246
247def ContainingIntPolynomialAttr2Op : TEST_Op<"containing_int_polynomial_attr2"> {
248  let arguments = (ins NestedPolynomialAttr2:$attr);
249  let assemblyFormat = "$attr attr-dict";
250}
251
252// A pattern that updates dense<[3.0, 4.0]> to dense<[5.0, 6.0]>.
253// This tests both matching and generating float elements attributes.
254def UpdateFloatElementsAttr : Pat<
255  (FloatElementsAttrOp
256    ConstantAttr<RankedF32ElementsAttr<[2]>, "{3.0f, 4.0f}">:$f32attr,
257    $f64attr),
258  (FloatElementsAttrOp
259    ConstantAttr<RankedF32ElementsAttr<[2]>, "{5.0f, 6.0f}">:$f32attr,
260    $f64attr)>;
261
262def IntElementsAttrOp : TEST_Op<"int_elements_attr"> {
263  let arguments = (ins
264      AnyI32ElementsAttr:$any_i32_attr,
265      I32ElementsAttr:$i32_attr
266  );
267}
268
269def RankedIntElementsAttrOp : TEST_Op<"ranked_int_elements_attr"> {
270  let arguments = (ins
271      RankedI32ElementsAttr<[2]>:$vector_i32_attr,
272      RankedI64ElementsAttr<[4, 8]>:$matrix_i64_attr
273  );
274}
275
276def DerivedTypeAttrOp : TEST_Op<"derived_type_attr", []> {
277  let results = (outs AnyTensor:$output);
278  DerivedTypeAttr element_dtype =
279    DerivedTypeAttr<"return getElementTypeOrSelf(getOutput().getType());">;
280  DerivedAttr num_elements = DerivedAttr<"int",
281    "return ::llvm::cast<ShapedType>(getOutput().getType()).getNumElements();",
282    "$_builder.getI32IntegerAttr($_self)">;
283}
284
285def TestPropOp : TEST_Op<"prop">,
286  Arguments<(ins Variadic<Index>:$upperInits,
287      I32ElementsAttr:$transforms)>,
288  Results<(outs Variadic<AnyType>:$results)> {
289  DerivedAttr upperLen = DerivedAttr<"uint32_t", [{
290    return getUpperInits().size() / getTransforms().size();
291  }], [{ $_builder.getI32IntegerAttr($_self) }]>;
292}
293
294
295def StringElementsAttrOp : TEST_Op<"string_elements_attr"> {
296  let arguments = (ins
297      StringElementsAttr:$scalar_string_attr
298  );
299}
300
301def TypedAttrOp : TEST_Op<"typed_attr"> {
302  let arguments = (ins TypeAttr:$type, AnyAttr:$attr);
303  let assemblyFormat = [{
304    attr-dict $type `=` custom<AttrElideType>(ref($type), $attr)
305  }];
306}
307
308def TypeAttrOfOp : TEST_Op<"type_attr_of"> {
309  let arguments = (ins TypeAttrOf<I64>:$type);
310  let assemblyFormat = [{
311    attr-dict $type
312  }];
313}
314
315def DenseArrayAttrOp : TEST_Op<"dense_array_attr"> {
316  let arguments = (ins
317    DenseBoolArrayAttr:$i1attr,
318    DenseI8ArrayAttr:$i8attr,
319    DenseI16ArrayAttr:$i16attr,
320    DenseI32ArrayAttr:$i32attr,
321    DenseI64ArrayAttr:$i64attr,
322    DenseF32ArrayAttr:$f32attr,
323    DenseF64ArrayAttr:$f64attr,
324    DenseI32ArrayAttr:$emptyattr
325  );
326  let assemblyFormat = [{
327   `i1attr` `=` $i1attr `i8attr` `=` $i8attr `i16attr` `=` $i16attr
328   `i32attr` `=` $i32attr `i64attr` `=` $i64attr  `f32attr` `=` $f32attr
329   `f64attr` `=` $f64attr `emptyattr` `=` $emptyattr attr-dict
330  }];
331}
332
333//===----------------------------------------------------------------------===//
334// Test Attributes Constraints
335//===----------------------------------------------------------------------===//
336
337def ConfinedDenseArrayAttrOp : TEST_Op<"confined_dense_array_attr"> {
338  let arguments = (ins
339      ConfinedAttr<DenseI16ArrayAttr,
340                   [DenseArrayStrictlySorted<DenseI16ArrayAttr>]>:$emptyattr,
341      ConfinedAttr<DenseI32ArrayAttr,
342                   [DenseArraySorted<DenseI32ArrayAttr>]>:$i32attr,
343      ConfinedAttr<DenseI64ArrayAttr,
344                   [DenseArrayStrictlySorted<DenseI64ArrayAttr>]>:$i64attr
345  );
346}
347
348// It does not make sense to have this constraint on a DenseBoolArrayAttr.
349def DenseArrayStrictlyPositiveAttrOp : TEST_Op<"confined_strictly_positive_attr"> {
350  let arguments = (ins
351      ConfinedAttr<DenseI8ArrayAttr,
352                   [DenseArrayStrictlyPositive<DenseI8ArrayAttr>]>:$i8attr,
353      ConfinedAttr<DenseI16ArrayAttr,
354                   [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>:$i16attr,
355      ConfinedAttr<DenseI32ArrayAttr,
356                   [DenseArrayStrictlyPositive<DenseI32ArrayAttr>]>:$i32attr,
357      ConfinedAttr<DenseI64ArrayAttr,
358                   [DenseArrayStrictlyPositive<DenseI64ArrayAttr>]>:$i64attr,
359      ConfinedAttr<DenseF32ArrayAttr,
360                   [DenseArrayStrictlyPositive<DenseF32ArrayAttr>]>:$f32attr,
361      ConfinedAttr<DenseF64ArrayAttr,
362                   [DenseArrayStrictlyPositive<DenseF64ArrayAttr>]>:$f64attr,
363      ConfinedAttr<DenseI16ArrayAttr,
364                   [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>:$emptyattr
365  );
366}
367
368// It does not make sense to have this constraint on a DenseBoolArrayAttr.
369// It is always true.
370def DenseArrayNonNegativeOp : TEST_Op<"confined_non_negative_attr"> {
371  let arguments = (ins
372      ConfinedAttr<DenseI8ArrayAttr,
373                   [DenseArrayNonNegative<DenseI8ArrayAttr>]>:$i8attr,
374      ConfinedAttr<DenseI16ArrayAttr,
375                   [DenseArrayNonNegative<DenseI16ArrayAttr>]>:$i16attr,
376      ConfinedAttr<DenseI32ArrayAttr,
377                   [DenseArrayNonNegative<DenseI32ArrayAttr>]>:$i32attr,
378      ConfinedAttr<DenseI64ArrayAttr,
379                   [DenseArrayNonNegative<DenseI64ArrayAttr>]>:$i64attr,
380      ConfinedAttr<DenseF32ArrayAttr,
381                   [DenseArrayNonNegative<DenseF32ArrayAttr>]>:$f32attr,
382      ConfinedAttr<DenseF64ArrayAttr,
383                   [DenseArrayNonNegative<DenseF64ArrayAttr>]>:$f64attr,
384      ConfinedAttr<DenseI16ArrayAttr,
385                   [DenseArrayNonNegative<DenseI16ArrayAttr>]>:$emptyattr
386  );
387}
388
389//===----------------------------------------------------------------------===//
390// Test Promised Interfaces Constraints
391//===----------------------------------------------------------------------===//
392
393def PromisedInterfacesOp : TEST_Op<"promised_interfaces"> {
394  let arguments = (ins
395      ConfinedAttr<AnyAttr,
396          [PromisedAttrInterface<TestExternalAttrInterface>]>:$promisedAttr,
397      ConfinedType<AnyType,
398          [HasPromiseOrImplementsTypeInterface<TestExternalTypeInterface>]
399        >:$promisedType
400  );
401}
402
403//===----------------------------------------------------------------------===//
404// Test Enum Attributes
405//===----------------------------------------------------------------------===//
406
407// Define the enum attribute.
408def TestEnumAttr : EnumAttr<Test_Dialect, TestEnum, "enum">;
409
410// Define an op that contains the enum attribute.
411def OpWithEnum : TEST_Op<"op_with_enum"> {
412  let arguments = (ins TestEnumAttr:$value, OptionalAttr<AnyAttr>:$tag);
413  let assemblyFormat = "$value (`tag` $tag^)? attr-dict";
414}
415
416// Define a pattern that matches and creates an enum attribute.
417def : Pat<(OpWithEnum ConstantEnumCase<TestEnumAttr, "first">:$value,
418                      ConstantAttr<I32Attr, "0">:$tag),
419          (OpWithEnum ConstantEnumCase<TestEnumAttr, "second">,
420                      ConstantAttr<I32Attr, "1">)>;
421
422//===----------------------------------------------------------------------===//
423// Test Bit Enum Attributes
424//===----------------------------------------------------------------------===//
425
426// Define the enum attribute.
427def TestBitEnumAttr : EnumAttr<Test_Dialect, TestBitEnum, "bit_enum"> {
428  let assemblyFormat = "`<` $value `>`";
429}
430
431// Define an op that contains the enum attribute.
432def OpWithBitEnum : TEST_Op<"op_with_bit_enum"> {
433  let arguments = (ins TestBitEnumAttr:$value, OptionalAttr<AnyAttr>:$tag);
434  let assemblyFormat = "$value (`tag` $tag^)? attr-dict";
435}
436
437def TestBitEnumVerticalBarAttr
438    : EnumAttr<Test_Dialect, TestBitEnumVerticalBar, "bit_enum_vbar"> {
439  let assemblyFormat = "`<` $value `>`";
440}
441
442// Define an op that contains the enum attribute.
443def OpWithBitEnumVerticalBar : TEST_Op<"op_with_bit_enum_vbar"> {
444  let arguments = (ins TestBitEnumVerticalBarAttr:$value,
445                   OptionalAttr<AnyAttr>:$tag);
446  let assemblyFormat = "$value (`tag` $tag^)? attr-dict";
447}
448
449// Define a pattern that matches and creates a bit enum attribute.
450def : Pat<(OpWithBitEnum ConstantEnumCase<TestBitEnumAttr, "write|execute">,
451                         ConstantAttr<I32Attr, "0">),
452          (OpWithBitEnum ConstantEnumCase<TestBitEnumAttr, "execute|read">,
453                         ConstantAttr<I32Attr, "1">)>;
454
455//===----------------------------------------------------------------------===//
456// Test Regions
457//===----------------------------------------------------------------------===//
458
459def OneRegionOp : TEST_Op<"one_region_op", []> {
460  let regions = (region AnyRegion);
461}
462
463def TwoRegionOp : TEST_Op<"two_region_op", []> {
464  let regions = (region AnyRegion, AnyRegion);
465}
466
467def SizedRegionOp : TEST_Op<"sized_region_op", []> {
468  let regions = (region SizedRegion<2>:$my_region, SizedRegion<1>);
469}
470
471def VariadicRegionInferredTypesOp : TEST_Op<"variadic_region_inferred",
472                                            [InferTypeOpInterface]> {
473  let regions = (region VariadicRegion<AnyRegion>:$bodies);
474  let results = (outs Variadic<AnyType>);
475
476  let extraClassDeclaration = [{
477    static llvm::LogicalResult inferReturnTypes(mlir::MLIRContext *context,
478          std::optional<::mlir::Location> location, mlir::ValueRange operands,
479          mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, mlir::RegionRange regions,
480          llvm::SmallVectorImpl<mlir::Type> &inferredReturnTypes) {
481      inferredReturnTypes.assign({mlir::IntegerType::get(context, 16)});
482      return mlir::success();
483    }
484  }];
485}
486
487def OneRegionWithOperandsOp : TEST_Op<"one_region_with_operands_op", []> {
488  let arguments = (ins Variadic<AnyType>:$operands);
489  let regions = (region AnyRegion);
490}
491
492def IsolatedOneRegionOp : TEST_Op<"isolated_one_region_op", [IsolatedFromAbove]> {
493  let arguments = (ins Variadic<AnyType>:$operands);
494  let regions = (region AnyRegion:$my_region);
495  let assemblyFormat = [{
496    attr-dict-with-keyword $operands $my_region `:` type($operands)
497  }];
498}
499
500def IsolatedRegionsOp : TEST_Op<"isolated_regions", [IsolatedFromAbove]> {
501  let regions = (region VariadicRegion<AnyRegion>:$regions);
502  let assemblyFormat = "attr-dict-with-keyword $regions";
503}
504
505def AllocaScopeRegionOp : TEST_Op<"alloca_scope_region",
506                                  [AutomaticAllocationScope]> {
507  let regions = (region AnyRegion:$region);
508  let assemblyFormat = "attr-dict-with-keyword $region";
509}
510
511def OneRegionWithRecursiveMemoryEffectsOp
512    : TEST_Op<"one_region_with_recursive_memory_effects", [
513        RecursiveMemoryEffects]> {
514  let description = [{
515    Op that has one region and recursive side effects. The
516    RegionBranchOpInterface is not implemented on this op.
517  }];
518  let results = (outs AnyType:$result);
519  let regions = (region SizedRegion<1>:$body);
520}
521
522//===----------------------------------------------------------------------===//
523// NoTerminator Operation
524//===----------------------------------------------------------------------===//
525
526def SingleNoTerminatorOp : TEST_Op<"single_no_terminator_op",
527                                   GraphRegionNoTerminator.traits> {
528  let regions = (region SizedRegion<1>:$my_region);
529
530  let assemblyFormat = "attr-dict `:` $my_region";
531}
532
533def SingleNoTerminatorCustomAsmOp : TEST_Op<"single_no_terminator_custom_asm_op",
534                                            [SingleBlock, NoTerminator]> {
535  let regions = (region SizedRegion<1>);
536  let hasCustomAssemblyFormat = 1;
537}
538
539def VariadicNoTerminatorOp : TEST_Op<"variadic_no_terminator_op",
540                                     GraphRegionNoTerminator.traits> {
541  let regions = (region VariadicRegion<SizedRegion<1>>:$my_regions);
542
543  let assemblyFormat = "attr-dict `:` $my_regions";
544}
545
546//===----------------------------------------------------------------------===//
547// Test Call Interfaces
548//===----------------------------------------------------------------------===//
549
550def TestCallOp : TEST_Op<"call", [DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
551  let arguments = (ins FlatSymbolRefAttr:$callee, Variadic<AnyType>:$operands);
552  let results = (outs Variadic<AnyType>);
553  let assemblyFormat = [{
554    $callee `(` $operands `)` attr-dict `:` functional-type($operands, results)
555  }];
556}
557
558def ConversionCallOp : TEST_Op<"conversion_call_op",
559    [CallOpInterface]> {
560  let arguments = (ins Variadic<AnyType>:$arg_operands, SymbolRefAttr:$callee);
561  let results = (outs Variadic<AnyType>);
562
563  let extraClassDeclaration = [{
564    /// Return the callee of this operation.
565    ::mlir::CallInterfaceCallable getCallableForCallee();
566
567    /// Set the callee for this operation.
568    void setCalleeFromCallable(::mlir::CallInterfaceCallable);
569  }];
570  let extraClassDefinition = [{
571    ::mlir::CallInterfaceCallable $cppClass::getCallableForCallee() {
572      return (*this)->getAttrOfType<::mlir::SymbolRefAttr>("callee");
573    }
574
575    void $cppClass::setCalleeFromCallable(::mlir::CallInterfaceCallable callee) {
576      (*this)->setAttr("callee", cast<SymbolRefAttr>(callee));
577    }
578  }];
579}
580
581def ConversionFuncOp : TEST_Op<"conversion_func_op", [FunctionOpInterface]> {
582  let arguments = (ins SymbolNameAttr:$sym_name,
583                       TypeAttrOf<FunctionType>:$function_type,
584                       OptionalAttr<DictArrayAttr>:$arg_attrs,
585                       OptionalAttr<DictArrayAttr>:$res_attrs,
586                       OptionalAttr<StrAttr>:$sym_visibility);
587  let regions = (region AnyRegion:$body);
588
589  let extraClassDeclaration = [{
590    //===------------------------------------------------------------------===//
591    // FunctionOpInterface Methods
592    //===------------------------------------------------------------------===//
593
594    /// Returns the region on the current operation that is callable. This may
595    /// return null in the case of an external callable object, e.g. an external
596    /// function.
597    ::mlir::Region *getCallableRegion() {
598      return isExternal() ? nullptr : &getBody();
599    }
600
601    /// Returns the argument types of this async function.
602    ::mlir::ArrayRef<::mlir::Type> getArgumentTypes() {
603      return getFunctionType().getInputs();
604    }
605
606    /// Returns the result types of this async function.
607    ::mlir::ArrayRef<::mlir::Type> getResultTypes() {
608      return getFunctionType().getResults();
609    }
610
611    /// Returns the number of results of this async function
612    unsigned getNumResults() {return getResultTypes().size();}
613  }];
614
615  let hasCustomAssemblyFormat = 1;
616}
617
618def FunctionalRegionOp : TEST_Op<"functional_region_op",
619    [CallableOpInterface]> {
620  let regions = (region AnyRegion:$body);
621  let results = (outs FunctionType);
622
623  let extraClassDeclaration = [{
624    ::mlir::Region *getCallableRegion() { return &getBody(); }
625    ::llvm::ArrayRef<::mlir::Type> getResultTypes() {
626      return ::llvm::cast<::mlir::FunctionType>(getType()).getResults();
627    }
628    ::llvm::ArrayRef<::mlir::Type> getArgumentTypes() {
629      return ::llvm::cast<::mlir::FunctionType>(getType()).getInputs();
630    }
631  }];
632}
633
634
635def FoldToCallOp : TEST_Op<"fold_to_call_op"> {
636  let arguments = (ins FlatSymbolRefAttr:$callee);
637  let hasCanonicalizer = 1;
638}
639
640//===----------------------------------------------------------------------===//
641// Test Traits
642//===----------------------------------------------------------------------===//
643
644def SameOperandElementTypeOp : TEST_Op<"same_operand_element_type",
645    [SameOperandsElementType]> {
646  let arguments = (ins AnyType, AnyType);
647  let results = (outs AnyType);
648}
649
650def SameOperandAndResultElementTypeOp :
651    TEST_Op<"same_operand_and_result_element_type",
652    [SameOperandsAndResultElementType]> {
653  let arguments = (ins Variadic<AnyType>);
654  let results = (outs Variadic<AnyType>);
655}
656
657def SameOperandShapeOp : TEST_Op<"same_operand_shape", [SameOperandsShape]> {
658  let arguments = (ins Variadic<AnyShaped>);
659}
660
661def SameOperandAndResultShapeOp : TEST_Op<"same_operand_and_result_shape",
662    [SameOperandsAndResultShape]> {
663  let arguments = (ins Variadic<AnyShaped>);
664  let results = (outs Variadic<AnyShaped>);
665}
666
667def SameOperandAndResultTypeOp : TEST_Op<"same_operand_and_result_type",
668    [SameOperandsAndResultType]> {
669  let arguments = (ins Variadic<AnyType>);
670  let results = (outs Variadic<AnyType>);
671}
672
673def ElementwiseMappableOp : TEST_Op<"elementwise_mappable",
674    ElementwiseMappable.traits> {
675  let arguments = (ins Variadic<AnyType>);
676  let results = (outs Variadic<AnyType>);
677}
678
679def ArgAndResHaveFixedElementTypesOp :
680    TEST_Op<"arg_and_res_have_fixed_element_types",
681      [PredOpTrait<"fixed type combination",
682         And<[ElementTypeIsPred<"x", I32>,
683              ElementTypeIsPred<"y", F32>]>>,
684      ElementTypeIs<"res", I16>]> {
685  let arguments = (ins
686    AnyShaped:$x, AnyShaped:$y);
687  let results = (outs AnyShaped:$res);
688}
689
690def OperandsHaveSameElementType : TEST_Op<"operands_have_same_element_type", [
691    AllElementTypesMatch<["x", "y"]>]> {
692  let arguments = (ins AnyType:$x, AnyType:$y);
693}
694
695def OperandZeroAndResultHaveSameElementType : TEST_Op<
696    "operand0_and_result_have_same_element_type",
697    [AllElementTypesMatch<["x", "res"]>]> {
698  let arguments = (ins AnyType:$x, AnyType:$y);
699  let results = (outs AnyType:$res);
700}
701
702def OperandsHaveSameType :
703    TEST_Op<"operands_have_same_type", [AllTypesMatch<["x", "y"]>]> {
704  let arguments = (ins AnyType:$x, AnyType:$y);
705}
706
707def ResultHasSameTypeAsAttr :
708    TEST_Op<"result_has_same_type_as_attr",
709            [AllTypesMatch<["attr", "result"]>]> {
710  let arguments = (ins TypedAttrInterface:$attr);
711  let results = (outs AnyType:$result);
712  let assemblyFormat = "$attr `->` type($result) attr-dict";
713}
714
715def OperandZeroAndResultHaveSameType :
716    TEST_Op<"operand0_and_result_have_same_type",
717            [AllTypesMatch<["x", "res"]>]> {
718  let arguments = (ins AnyType:$x, AnyType:$y);
719  let results = (outs AnyType:$res);
720}
721
722def OperandsHaveSameRank :
723    TEST_Op<"operands_have_same_rank", [AllRanksMatch<["x", "y"]>]> {
724  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
725}
726
727def OperandZeroAndResultHaveSameRank :
728    TEST_Op<"operand0_and_result_have_same_rank",
729            [AllRanksMatch<["x", "res"]>]> {
730  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
731  let results = (outs AnyShaped:$res);
732}
733
734def OperandsAndResultHaveSameRank :
735    TEST_Op<"operands_and_result_have_same_rank", [SameOperandsAndResultRank]> {
736  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
737  let results = (outs AnyShaped:$res);
738}
739
740def OperandZeroAndResultHaveSameShape :
741    TEST_Op<"operand0_and_result_have_same_shape",
742            [AllShapesMatch<["x", "res"]>]> {
743  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
744  let results = (outs AnyShaped:$res);
745}
746
747def OperandZeroAndResultHaveSameElementCount :
748    TEST_Op<"operand0_and_result_have_same_element_count",
749            [AllElementCountsMatch<["x", "res"]>]> {
750  let arguments = (ins AnyShaped:$x, AnyShaped:$y);
751  let results = (outs AnyShaped:$res);
752}
753
754def FourEqualsFive :
755    TEST_Op<"four_equals_five", [AllMatch<["5", "4"], "4 equals 5">]>;
756
757def OperandRankEqualsResultSize :
758    TEST_Op<"operand_rank_equals_result_size",
759            [AllMatch<[Rank<"operand">.result, ElementCount<"result">.result],
760                      "operand rank equals result size">]> {
761  let arguments = (ins AnyShaped:$operand);
762  let results = (outs AnyShaped:$result);
763}
764
765def IfFirstOperandIsNoneThenSoIsSecond :
766    TEST_Op<"if_first_operand_is_none_then_so_is_second", [PredOpTrait<
767    "has either both none type operands or first is not none",
768     Or<[
769        And<[TypeIsPred<"x", NoneType>, TypeIsPred<"y", NoneType>]>,
770        Neg<TypeIsPred<"x", NoneType>>]>>]> {
771  let arguments = (ins AnyType:$x, AnyType:$y);
772}
773
774def BroadcastableOp : TEST_Op<"broadcastable", [ResultsBroadcastableShape]> {
775  let arguments = (ins Variadic<AnyTensor>);
776  let results = (outs AnyTensor);
777}
778
779// HasParent trait
780def ParentOp : TEST_Op<"parent"> {
781    let regions = (region AnyRegion);
782}
783def ChildOp : TEST_Op<"child", [HasParent<"ParentOp">]>;
784
785// ParentOneOf trait
786def ParentOp1 : TEST_Op<"parent1"> {
787  let regions = (region AnyRegion);
788}
789def ChildWithParentOneOf : TEST_Op<"child_with_parent_one_of",
790                                [ParentOneOf<["ParentOp", "ParentOp1"]>]>;
791
792def TerminatorOp : TEST_Op<"finish", [Terminator]>;
793def SingleBlockImplicitTerminatorOp : TEST_Op<"SingleBlockImplicitTerminator",
794    [SingleBlockImplicitTerminator<"TerminatorOp">]> {
795  let regions = (region SizedRegion<1>:$region);
796}
797
798def I32ElementsAttrOp : TEST_Op<"i32ElementsAttr"> {
799  let arguments = (ins I32ElementsAttr:$attr);
800}
801
802def IndexElementsAttrOp : TEST_Op<"indexElementsAttr"> {
803  let arguments = (ins IndexElementsAttr:$attr);
804}
805
806def OpWithInferTypeInterfaceOp : TEST_Op<"op_with_infer_type_if", [
807    DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
808  let arguments = (ins AnyTensor, AnyTensor);
809  let results = (outs AnyTensor);
810}
811
812def OpWithInferTypeAdaptorInterfaceOp : TEST_Op<"op_with_infer_type_adaptor_if", [
813    InferTypeOpAdaptor]> {
814  let arguments = (ins AnyTensor:$x, AnyTensor:$y);
815  let results = (outs AnyTensor);
816}
817
818def OpWithRefineTypeInterfaceOp : TEST_Op<"op_with_refine_type_if", [
819    DeclareOpInterfaceMethods<InferTypeOpInterface,
820        ["refineReturnTypes"]>]> {
821  let arguments = (ins AnyTensor, AnyTensor);
822  let results = (outs AnyTensor);
823}
824
825def OpWithShapedTypeInferTypeInterfaceOp : TEST_Op<"op_with_shaped_type_infer_type_if",
826      [InferTensorTypeWithReify]> {
827  let arguments = (ins AnyTensor, AnyTensor);
828  let results = (outs AnyTensor);
829}
830
831def OpWithShapedTypeInferTypeAdaptorInterfaceOp :
832      TEST_Op<"op_with_shaped_type_infer_type_adaptor_if",
833              [InferTensorTypeAdaptorWithReify]> {
834  let arguments = (ins AnyTensor:$operand1, AnyTensor:$operand2);
835  let results = (outs AnyTensor:$result);
836}
837
838def OpWithResultShapeInterfaceOp : TEST_Op<"op_with_result_shape_interface",
839      [DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
840          ["reifyReturnTypeShapes"]>]> {
841  let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2);
842  let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2);
843}
844
845def OpWithResultShapePerDimInterfaceOp :
846    TEST_Op<"op_with_result_shape_per_dim_interface",
847        [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface>]> {
848  let arguments = (ins AnyRankedTensor:$operand1, AnyRankedTensor:$operand2);
849  let results = (outs AnyRankedTensor:$result1, AnyRankedTensor:$result2);
850}
851
852def IsNotScalar : Constraint<CPred<"$0.getType().getRank() != 0">>;
853
854def UpdateAttr : Pat<(I32ElementsAttrOp $attr),
855                     (I32ElementsAttrOp ConstantAttr<I32ElementsAttr, "0">),
856                     [(IsNotScalar $attr)]>;
857
858def TestBranchOp : TEST_Op<"br",
859    [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator]> {
860  let arguments = (ins Variadic<AnyType>:$targetOperands);
861  let successors = (successor AnySuccessor:$target);
862}
863
864def TestProducingBranchOp : TEST_Op<"producing_br",
865    [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator,
866     AttrSizedOperandSegments]> {
867  let arguments = (ins Variadic<AnyType>:$firstOperands,
868                       Variadic<AnyType>:$secondOperands);
869  let results = (outs I32:$dummy);
870  let successors = (successor AnySuccessor:$first,AnySuccessor:$second);
871}
872
873// Produces an error value on the error path
874def TestInternalBranchOp : TEST_Op<"internal_br",
875    [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator,
876     AttrSizedOperandSegments]> {
877
878  let arguments = (ins Variadic<AnyType>:$successOperands,
879                       Variadic<AnyType>:$errorOperands);
880
881  let successors = (successor AnySuccessor:$successPath, AnySuccessor:$errorPath);
882}
883
884def AttrSizedOperandOp : TEST_Op<"attr_sized_operands",
885                                 [AttrSizedOperandSegments]> {
886  let arguments = (ins
887    Variadic<I32>:$a,
888    Variadic<I32>:$b,
889    I32:$c,
890    Variadic<I32>:$d
891  );
892}
893
894def AttrSizedResultOp : TEST_Op<"attr_sized_results",
895                                [AttrSizedResultSegments]> {
896  let results = (outs
897    Variadic<I32>:$a,
898    Variadic<I32>:$b,
899    I32:$c,
900    Variadic<I32>:$d
901  );
902}
903
904def AttrSizedResultCompileTestOp : TEST_Op<"attr_sized_results_compile_test",
905                                           [AttrSizedResultSegments]> {
906  let results = (outs Variadic<I32>:$a, I32:$b, Optional<I32>:$c);
907}
908
909
910
911// This is used to test encoding of a string attribute into an SSA name of a
912// pretty printed value name.
913def StringAttrPrettyNameOp
914 : TEST_Op<"string_attr_pretty_name",
915           [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
916  let arguments = (ins StrArrayAttr:$names);
917  let results = (outs Variadic<I32>:$r);
918  let hasCustomAssemblyFormat = 1;
919}
920
921
922// This is used to test encoding of a string attribute into an SSA name of a
923// pretty printed value name.
924def CustomResultsNameOp
925 : TEST_Op<"custom_result_name",
926           [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
927  let arguments = (ins
928    Variadic<AnyInteger>:$optional,
929    StrArrayAttr:$names
930  );
931  let results = (outs Variadic<AnyInteger>:$r);
932}
933
934// This is used to test OpAsmTypeInterface::getAsmName for op result name,
935def ResultNameFromTypeOp
936 : TEST_Op<"result_name_from_type",
937           [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
938  let results = (outs AnyType:$r);
939}
940
941// This is used to test OpAsmTypeInterface::getAsmName for block argument,
942def BlockArgumentNameFromTypeOp
943  : TEST_Op<"block_argument_name_from_type",
944      [DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmBlockArgumentNames"]>]> {
945  let regions = (region AnyRegion:$body);
946  let assemblyFormat = "regions attr-dict-with-keyword";
947}
948
949// This is used to test the OpAsmOpInterface::getDefaultDialect() feature:
950// operations nested in a region under this op will drop the "test." dialect
951// prefix.
952def DefaultDialectOp : TEST_Op<"default_dialect", [OpAsmOpInterface]> {
953 let regions = (region AnyRegion:$body);
954  let extraClassDeclaration = [{
955    static ::llvm::StringRef getDefaultDialect() {
956      return "test";
957    }
958    void getAsmResultNames(::llvm::function_ref<void(::mlir::Value, ::llvm::StringRef)> setNameFn) {}
959  }];
960  let assemblyFormat = "regions attr-dict-with-keyword";
961}
962
963
964// This is used to test the OpAsmOpInterface::getAsmBlockName() feature:
965// blocks nested in a region under this op will have a name defined by the
966// interface.
967def AsmBlockNameOp : TEST_Op<"block_names", [OpAsmOpInterface]> {
968 let regions = (region AnyRegion:$body);
969  let extraClassDeclaration = [{
970    void getAsmBlockNames(mlir::OpAsmSetBlockNameFn setNameFn) {
971      std::string name;
972      int count = 0;
973      for (::mlir::Block &block : getRegion().getBlocks()) {
974        name = "foo" + std::to_string(count++);
975        setNameFn(&block, name);
976      }
977    }
978  }];
979  let assemblyFormat = "regions attr-dict-with-keyword";
980}
981
982// This operation requires its return type to have the trait 'TestTypeTrait'.
983def ResultTypeWithTraitOp : TEST_Op<"result_type_with_trait", []> {
984  let results = (outs AnyType);
985  let hasVerifier = 1;
986}
987
988// This operation requires its "attr" attribute to have the
989// trait 'TestAttrTrait'.
990def AttrWithTraitOp : TEST_Op<"attr_with_trait", []> {
991  let arguments = (ins AnyAttr:$attr);
992  let hasVerifier = 1;
993}
994
995//===----------------------------------------------------------------------===//
996// Test Locations
997//===----------------------------------------------------------------------===//
998
999def TestLocationSrcOp : TEST_Op<"loc_src"> {
1000  let arguments = (ins I32:$input);
1001  let results = (outs I32:$output);
1002}
1003
1004def TestLocationDstOp : TEST_Op<"loc_dst", [SameOperandsAndResultType]> {
1005  let arguments = (ins I32:$input);
1006  let results = (outs I32:$output);
1007}
1008
1009def TestLocationSrcNoResOp : TEST_Op<"loc_src_no_res"> {
1010  let arguments = (ins I32:$input);
1011  let results = (outs);
1012}
1013
1014def TestLocationDstNoResOp : TEST_Op<"loc_dst_no_res"> {
1015  let arguments = (ins I32:$input);
1016  let results = (outs);
1017}
1018
1019//===----------------------------------------------------------------------===//
1020// Test Patterns
1021//===----------------------------------------------------------------------===//
1022
1023def OpA : TEST_Op<"op_a"> {
1024  let arguments = (ins I32, I32Attr:$attr);
1025  let results = (outs I32);
1026}
1027
1028def OpB : TEST_Op<"op_b"> {
1029  let arguments = (ins I32, I32Attr:$attr);
1030  let results = (outs I32);
1031}
1032
1033// Test named pattern.
1034def TestNamedPatternRule : Pat<(OpA $input, $attr), (OpB $input, $attr)>;
1035
1036// Test with fused location.
1037def : Pat<(OpA (OpA $input, $attr), $bttr), (OpB $input, $bttr)>;
1038
1039// Test added benefit.
1040def OpD : TEST_Op<"op_d">, Arguments<(ins I32)>, Results<(outs I32)>;
1041def OpE : TEST_Op<"op_e">, Arguments<(ins I32)>, Results<(outs I32)>;
1042def OpF : TEST_Op<"op_f">, Arguments<(ins I32)>, Results<(outs I32)>;
1043def OpG : TEST_Op<"op_g">, Arguments<(ins I32)>, Results<(outs I32)>;
1044// Verify that bumping benefit results in selecting different op.
1045def : Pat<(OpD $input), (OpE $input)>;
1046def : Pat<(OpD $input), (OpF $input), [], [], (addBenefit 10)>;
1047// Verify that patterns with more source nodes are selected before those with fewer.
1048def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>;
1049def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>;
1050
1051// Test patterns for zero-result op.
1052def OpH : TEST_Op<"op_h">, Arguments<(ins I32)>, Results<(outs)>;
1053def OpI : TEST_Op<"op_i">, Arguments<(ins I32)>, Results<(outs)>;
1054def : Pat<(OpH $input), (OpI $input)>;
1055
1056// Test patterns for zero-input op.
1057def OpJ : TEST_Op<"op_j">, Arguments<(ins)>, Results<(outs I32)>;
1058def OpK : TEST_Op<"op_k">, Arguments<(ins)>, Results<(outs I32)>;
1059def : Pat<(OpJ), (OpK)>;
1060
1061// Test that natives calls are only called once during rewrites.
1062def OpM : TEST_Op<"op_m"> {
1063  let arguments = (ins I32, OptionalAttr<I32Attr>:$optional_attr);
1064  let results = (outs I32);
1065}
1066
1067def OpN : TEST_Op<"op_n"> {
1068  let arguments = (ins I32, I32);
1069  let results = (outs I32);
1070}
1071
1072def OpO : TEST_Op<"op_o"> {
1073  let arguments = (ins I32);
1074  let results = (outs I32);
1075}
1076
1077def OpP : TEST_Op<"op_p"> {
1078  let arguments = (ins I32, I32, I32, I32, I32, I32);
1079  let results = (outs I32);
1080}
1081
1082// Test same operand name enforces equality condition check.
1083def TestEqualArgsPattern : Pat<(OpN $a, $a), (OpO $a)>;
1084
1085// Test when equality is enforced at different depth.
1086def TestNestedOpEqualArgsPattern :
1087  Pat<(OpN $b, (OpP $a, $b, $c, $d, $e, $f)), (replaceWithValue $b)>;
1088
1089// Test when equality is enforced on same op and same operand but at different
1090// depth. We only bound one of the $x to the second operand of outer OpN and
1091// left another be the default value (which is the value of first operand of
1092// outer OpN). As a result, it ended up comparing wrong values in some cases.
1093def TestNestedSameOpAndSameArgEqualityPattern :
1094  Pat<(OpN (OpN $_, $x), $x), (replaceWithValue $x)>;
1095
1096// Test multiple equal arguments check enforced.
1097def TestMultipleEqualArgsPattern :
1098  Pat<(OpP $a, $b, $a, $a, $b, $c), (OpN $c, $b)>;
1099
1100// Test for memrefs normalization of an op with normalizable memrefs.
1101def OpNorm : TEST_Op<"op_norm", [MemRefsNormalizable]> {
1102  let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y);
1103}
1104// Test for memrefs normalization of an op without normalizable memrefs.
1105def OpNonNorm : TEST_Op<"op_nonnorm"> {
1106  let arguments = (ins AnyMemRef:$X, AnyMemRef:$Y);
1107}
1108// Test for memrefs normalization of an op that has normalizable memref results.
1109def OpNormRet : TEST_Op<"op_norm_ret", [MemRefsNormalizable]> {
1110  let arguments = (ins AnyMemRef:$X);
1111  let results = (outs AnyMemRef:$Y, AnyMemRef:$Z);
1112}
1113
1114// Test for memrefs normalization of an op with a reference to a function
1115// symbol.
1116def OpFuncRef : TEST_Op<"op_funcref"> {
1117  let summary = "Test op with a reference to a function symbol";
1118  let description = [{
1119    The "test.op_funcref" is a test op with a reference to a function symbol.
1120  }];
1121  let builders = [OpBuilder<(ins "::mlir::func::FuncOp":$function)>];
1122}
1123
1124// Pattern add the argument plus a increasing static number hidden in
1125// OpMTest function. That value is set into the optional argument.
1126// That way, we will know if operations is called once or twice.
1127def OpMGetNullAttr : NativeCodeCall<"Attribute()">;
1128def OpMAttributeIsNull : Constraint<CPred<"! ($_self)">, "Attribute is null">;
1129def OpMVal : NativeCodeCall<"opMTest($_builder, $0)">;
1130def : Pat<(OpM $attr, $optAttr), (OpM $attr, (OpMVal $attr) ),
1131    [(OpMAttributeIsNull:$optAttr)]>;
1132
1133// Test `$_` for ignoring op argument match.
1134def TestIgnoreArgMatchSrcOp : TEST_Op<"ignore_arg_match_src"> {
1135  let arguments = (ins
1136    AnyType:$a, AnyType:$b, AnyType:$c,
1137    AnyAttr:$d, AnyAttr:$e, AnyAttr:$f);
1138}
1139def TestIgnoreArgMatchDstOp : TEST_Op<"ignore_arg_match_dst"> {
1140  let arguments = (ins AnyType:$b, AnyAttr:$f);
1141}
1142def : Pat<(TestIgnoreArgMatchSrcOp $_, $b, I32, I64Attr:$_, $_, $f),
1143          (TestIgnoreArgMatchDstOp $b, $f)>;
1144
1145def OpInterleavedOperandAttribute1 : TEST_Op<"interleaved_operand_attr1"> {
1146  let arguments = (ins
1147    I32:$input1,
1148    I64Attr:$attr1,
1149    I32:$input2,
1150    I64Attr:$attr2
1151  );
1152}
1153
1154def OpInterleavedOperandAttribute2 : TEST_Op<"interleaved_operand_attr2"> {
1155  let arguments = (ins
1156    I32:$input1,
1157    I64Attr:$attr1,
1158    I32:$input2,
1159    I64Attr:$attr2
1160  );
1161}
1162
1163def ManyArgsOp : TEST_Op<"many_arguments"> {
1164  let arguments = (ins
1165    I32:$input1, I32:$input2, I32:$input3, I32:$input4, I32:$input5,
1166    I32:$input6, I32:$input7, I32:$input8, I32:$input9,
1167    I64Attr:$attr1, I64Attr:$attr2, I64Attr:$attr3, I64Attr:$attr4,
1168    I64Attr:$attr5, I64Attr:$attr6, I64Attr:$attr7, I64Attr:$attr8,
1169    I64Attr:$attr9
1170  );
1171}
1172
1173// Test that DRR does not blow up when seeing lots of arguments.
1174def : Pat<(ManyArgsOp
1175            $input1, $input2, $input3, $input4, $input5,
1176            $input6, $input7, $input8, $input9,
1177            ConstantAttr<I64Attr, "42">,
1178            $attr2, $attr3, $attr4, $attr5, $attr6,
1179            $attr7, $attr8, $attr9),
1180          (ManyArgsOp
1181            $input1, $input2, $input3, $input4, $input5,
1182            $input6, $input7, $input8, $input9,
1183            ConstantAttr<I64Attr, "24">,
1184            $attr2, $attr3, $attr4, $attr5, $attr6,
1185            $attr7, $attr8, $attr9)>;
1186
1187// Test that we can capture and reference interleaved operands and attributes.
1188def : Pat<(OpInterleavedOperandAttribute1 $input1, $attr1, $input2, $attr2),
1189          (OpInterleavedOperandAttribute2 $input1, $attr1, $input2, $attr2)>;
1190
1191// Test NativeCodeCall.
1192def OpNativeCodeCall1 : TEST_Op<"native_code_call1"> {
1193  let arguments = (ins
1194    I32:$input1, I32:$input2,
1195    BoolAttr:$choice,
1196    I64Attr:$attr1, I64Attr:$attr2
1197  );
1198  let results = (outs I32);
1199}
1200def OpNativeCodeCall2 : TEST_Op<"native_code_call2"> {
1201  let arguments = (ins I32:$input, I64ArrayAttr:$attr);
1202  let results = (outs I32);
1203}
1204// Native code call to invoke a C++ function
1205def CreateOperand: NativeCodeCall<"chooseOperand($0, $1, $2)">;
1206// Native code call to invoke a C++ expression
1207def CreateArrayAttr: NativeCodeCall<"$_builder.getArrayAttr({$0, $1})">;
1208// Test that we can use NativeCodeCall to create operand and attribute.
1209// This pattern chooses between $input1 and $input2 according to $choice and
1210// it combines $attr1 and $attr2 into an array attribute.
1211def : Pat<(OpNativeCodeCall1 $input1, $input2,
1212                             ConstBoolAttrTrue:$choice, $attr1, $attr2),
1213          (OpNativeCodeCall2 (CreateOperand $input1, $input2, $choice),
1214                             (CreateArrayAttr $attr1, $attr2))>;
1215// Note: the following is just for testing purpose.
1216// Should use the replaceWithValue directive instead.
1217def UseOpResult: NativeCodeCall<"$0">;
1218// Test that we can use NativeCodeCall to create result.
1219def : Pat<(OpNativeCodeCall1 $input1, $input2,
1220                             ConstBoolAttrFalse, $attr1, $attr2),
1221          (UseOpResult $input2)>;
1222
1223def OpNativeCodeCall3 : TEST_Op<"native_code_call3"> {
1224  let arguments = (ins I32:$input);
1225  let results = (outs I32);
1226}
1227// Test that NativeCodeCall is not ignored if it is not used to directly
1228// replace the matched root op.
1229def : Pattern<(OpNativeCodeCall3 $input),
1230              [(NativeCodeCallVoid<"createOpI($_builder, $_loc, $0)"> $input),
1231               (OpK)]>;
1232
1233def OpNativeCodeCall4 : TEST_Op<"native_code_call4"> {
1234  let arguments = (ins AnyType:$input1);
1235  let results = (outs I32:$output1, I32:$output2);
1236}
1237def OpNativeCodeCall5 : TEST_Op<"native_code_call5"> {
1238  let arguments = (ins I32:$input1, I32:$input2);
1239  let results = (outs I32:$output1, I32:$output2);
1240}
1241
1242def GetFirstI32Result : NativeCodeCall<"success(getFirstI32Result($_self, $0))">;
1243def BindNativeCodeCallResult : NativeCodeCall<"bindNativeCodeCallResult($0)">;
1244def : Pat<(OpNativeCodeCall4 (GetFirstI32Result $ret)),
1245          (OpNativeCodeCall5 (BindNativeCodeCallResult:$native $ret), $native)>;
1246
1247def OpNativeCodeCall6 : TEST_Op<"native_code_call6"> {
1248  let arguments = (ins I32:$input1, I32:$input2);
1249  let results = (outs I32:$output1, I32:$output2);
1250}
1251def OpNativeCodeCall7 : TEST_Op<"native_code_call7"> {
1252  let arguments = (ins I32:$input);
1253  let results = (outs I32);
1254}
1255def BindMultipleNativeCodeCallResult : NativeCodeCall<"bindMultipleNativeCodeCallResult($0, $1)", 2>;
1256def : Pattern<(OpNativeCodeCall6 $arg1, $arg2),
1257              [(OpNativeCodeCall7 (BindMultipleNativeCodeCallResult:$native__0 $arg1, $arg2)),
1258               (OpNativeCodeCall7 $native__1)]>;
1259
1260// Test AllAttrOf.
1261def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> {
1262  let arguments = (ins I64ArrayAttr:$attr);
1263  let results = (outs I32);
1264}
1265def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> {
1266  let arguments = (ins I64ArrayAttr:$attr);
1267  let results = (outs I32);
1268}
1269def Constraint0 : AttrConstraint<
1270    CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<ArrayAttr>($_self)[0]).getInt() == 0">,
1271    "[0] == 0">;
1272def Constraint1 : AttrConstraint<
1273    CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<ArrayAttr>($_self)[1]).getInt() == 1">,
1274    "[1] == 1">;
1275def : Pat<(OpAllAttrConstraint1
1276            AllAttrOf<[Constraint0, Constraint1]>:$attr),
1277          (OpAllAttrConstraint2 $attr)>;
1278
1279// Op for testing RewritePattern removing op with inner ops.
1280def TestOpWithRegionPattern : TEST_Op<"op_with_region_pattern"> {
1281  let regions = (region SizedRegion<1>:$region);
1282  let hasCanonicalizer = 1;
1283}
1284
1285def TestOpConstant : TEST_Op<"constant", [ConstantLike, NoMemoryEffect]> {
1286  let arguments = (ins AnyAttr:$value);
1287  let results = (outs AnyType);
1288
1289  let hasFolder = 1;
1290}
1291
1292def OpR : TEST_Op<"op_r">, Arguments<(ins AnyInteger, AnyInteger)>, Results<(outs AnyInteger)>;
1293def OpS : TEST_Op<"op_s">, Arguments<(ins AnyInteger, AnyAttr:$value)>, Results<(outs AnyInteger)>;
1294
1295def : Pat<(OpR $input1, (ConstantLikeMatcher I32Attr:$input2)),
1296          (OpS:$unused $input1, $input2)>;
1297
1298// Op for testing trivial removal via folding of op with inner ops and no uses.
1299def TestOpWithRegionFoldNoMemoryEffect : TEST_Op<
1300    "op_with_region_fold_no_side_effect", [NoMemoryEffect]> {
1301  let regions = (region SizedRegion<1>:$region);
1302}
1303
1304// Op for testing folding of outer op with inner ops.
1305def TestOpWithRegionFold : TEST_Op<"op_with_region_fold"> {
1306  let arguments = (ins AnyType:$operand);
1307  let results = (outs AnyType);
1308  let regions = (region SizedRegion<1>:$region);
1309  let hasFolder = 1;
1310}
1311
1312def TestOpWithVariadicResultsAndFolder: TEST_Op<"op_with_variadic_results_and_folder"> {
1313  let arguments = (ins Variadic<I32>);
1314  let results = (outs Variadic<I32>);
1315  let hasFolder = 1;
1316}
1317
1318def TestAddIOp : TEST_Op<"addi"> {
1319  let arguments = (ins AnyTypeOf<[I32, TestI32]>:$op1,
1320                       AnyTypeOf<[I32, TestI32]>:$op2);
1321  let results = (outs AnyTypeOf<[I32, TestI32]>);
1322}
1323
1324def TestCommutativeOp : TEST_Op<"op_commutative", [Commutative]> {
1325  let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4);
1326  let results = (outs I32);
1327}
1328
1329def TestLargeCommutativeOp : TEST_Op<"op_large_commutative", [Commutative]> {
1330  let arguments = (ins I32:$op1, I32:$op2, I32:$op3, I32:$op4, I32:$op5, I32:$op6, I32:$op7);
1331  let results = (outs I32);
1332}
1333
1334def TestCommutative2Op : TEST_Op<"op_commutative2", [Commutative]> {
1335  let arguments = (ins I32:$op1, I32:$op2);
1336  let results = (outs I32);
1337}
1338
1339def TestIdempotentTraitOp
1340 : TEST_Op<"op_idempotent_trait",
1341           [SameOperandsAndResultType, NoMemoryEffect, Idempotent]> {
1342  let arguments = (ins I32:$op1);
1343  let results = (outs I32);
1344}
1345
1346def TestIdempotentTraitBinaryOp
1347    : TEST_Op<"op_idempotent_trait_binary",
1348              [SameOperandsAndResultType, NoMemoryEffect, Idempotent]> {
1349  let arguments = (ins I32:$op1, I32:$op2);
1350  let results = (outs I32);
1351}
1352
1353def TestInvolutionTraitNoOperationFolderOp
1354 : TEST_Op<"op_involution_trait_no_operation_fold",
1355           [SameOperandsAndResultType, NoMemoryEffect, Involution]> {
1356  let arguments = (ins I32:$op1);
1357  let results = (outs I32);
1358}
1359
1360def TestInvolutionTraitFailingOperationFolderOp
1361 : TEST_Op<"op_involution_trait_failing_operation_fold",
1362           [SameOperandsAndResultType, NoMemoryEffect, Involution]> {
1363  let arguments = (ins I32:$op1);
1364  let results = (outs I32);
1365  let hasFolder = 1;
1366}
1367
1368def TestInvolutionTraitSuccesfulOperationFolderOp
1369 : TEST_Op<"op_involution_trait_succesful_operation_fold",
1370           [SameOperandsAndResultType, NoMemoryEffect, Involution]> {
1371  let arguments = (ins I32:$op1);
1372  let results = (outs I32);
1373  let hasFolder = 1;
1374}
1375
1376def TestOpInPlaceFoldAnchor : TEST_Op<"op_in_place_fold_anchor"> {
1377  let arguments = (ins I32);
1378  let results = (outs I32);
1379}
1380
1381def TestOpInPlaceFold : TEST_Op<"op_in_place_fold"> {
1382  let arguments = (ins I32:$op, OptionalAttr<I32Attr>:$attr);
1383  let results = (outs I32);
1384  let hasFolder = 1;
1385}
1386
1387def TestOpInPlaceSelfFold : TEST_Op<"op_in_place_self_fold"> {
1388  let arguments = (ins UnitAttr:$folded);
1389  let results = (outs I32);
1390  let hasFolder = 1;
1391}
1392
1393// Test op that simply returns success.
1394def TestOpInPlaceFoldSuccess : TEST_Op<"op_in_place_fold_success"> {
1395  let results = (outs Variadic<I1>);
1396  let hasFolder = 1;
1397  let extraClassDefinition = [{
1398    ::llvm::LogicalResult $cppClass::fold(FoldAdaptor adaptor,
1399        SmallVectorImpl<OpFoldResult> &results) {
1400      return success();
1401    }
1402  }];
1403}
1404
1405def TestOpFoldWithFoldAdaptor
1406  : TEST_Op<"fold_with_fold_adaptor",
1407      [AttrSizedOperandSegments, NoTerminator]> {
1408  let arguments = (ins
1409    I32:$op,
1410    DenseI32ArrayAttr:$attr,
1411    Variadic<I32>:$variadic,
1412    VariadicOfVariadic<I32, "attr">:$var_of_var
1413  );
1414
1415  let results = (outs I32:$res);
1416
1417  let regions = (region AnyRegion:$body);
1418
1419  let assemblyFormat = [{
1420    $op `,` `[` $variadic `]` `,` `{` $var_of_var `}` $body attr-dict-with-keyword
1421  }];
1422
1423  let hasFolder = 1;
1424}
1425
1426def TestDialectCanonicalizerOp : TEST_Op<"dialect_canonicalizable"> {
1427  let arguments = (ins);
1428  let results = (outs I32);
1429}
1430
1431//===----------------------------------------------------------------------===//
1432// Test Patterns (Symbol Binding)
1433
1434// Test symbol binding.
1435def OpSymbolBindingA : TEST_Op<"symbol_binding_a", []> {
1436  let arguments = (ins I32:$operand, I64Attr:$attr);
1437  let results = (outs I32);
1438}
1439def OpSymbolBindingB : TEST_Op<"symbol_binding_b", []> {
1440  let arguments = (ins I32:$operand);
1441  let results = (outs I32);
1442}
1443def OpSymbolBindingC : TEST_Op<"symbol_binding_c", []> {
1444  let arguments = (ins I32:$operand);
1445  let results = (outs I32);
1446  let builders = OpSymbolBindingB.builders;
1447}
1448def OpSymbolBindingD : TEST_Op<"symbol_binding_d", []> {
1449  let arguments = (ins I32:$input1, I32:$input2, I64Attr:$attr);
1450  let results = (outs I32);
1451}
1452def HasOneUse: Constraint<CPred<"$0.hasOneUse()">, "has one use">;
1453def : Pattern<
1454    // Bind to source pattern op operand/attribute/result
1455    (OpSymbolBindingA:$res_a $operand, $attr), [
1456        // Bind to auxiliary op result
1457        (OpSymbolBindingC:$res_c (OpSymbolBindingB:$res_b $operand)),
1458
1459        // Use bound symbols in resultant ops
1460        (OpSymbolBindingD $res_b, $res_c, $attr)],
1461    // Use bound symbols in additional constraints
1462    [(HasOneUse $res_a)]>;
1463
1464def OpSymbolBindingNoResult : TEST_Op<"symbol_binding_no_result", []> {
1465  let arguments = (ins I32:$operand);
1466}
1467
1468// Test that we can bind to an op without results and reference it later.
1469def : Pat<(OpSymbolBindingNoResult:$op $operand),
1470          (NativeCodeCallVoid<"handleNoResultOp($_builder, $0)"> $op)>;
1471
1472//===----------------------------------------------------------------------===//
1473// Test Patterns (Attributes)
1474
1475// Test matching against op attributes.
1476def OpAttrMatch1 : TEST_Op<"match_op_attribute1"> {
1477  let arguments = (ins
1478    I32Attr:$required_attr,
1479    OptionalAttr<I32Attr>:$optional_attr,
1480    DefaultValuedAttr<I32Attr, "42">:$default_valued_attr,
1481    I32Attr:$more_attr
1482  );
1483  let results = (outs I32);
1484}
1485def OpAttrMatch2 : TEST_Op<"match_op_attribute2"> {
1486  let arguments = OpAttrMatch1.arguments;
1487  let results = (outs I32);
1488}
1489def MoreConstraint : AttrConstraint<
1490    CPred<"::llvm::cast<IntegerAttr>($_self).getInt() == 4">, "more constraint">;
1491def : Pat<(OpAttrMatch1 $required, $optional, $default_valued,
1492                        MoreConstraint:$more),
1493          (OpAttrMatch2 $required, $optional, $default_valued, $more)>;
1494
1495// Test unit attrs.
1496def OpAttrMatch3 : TEST_Op<"match_op_attribute3"> {
1497  let arguments = (ins UnitAttr:$attr);
1498  let results = (outs I32);
1499}
1500def OpAttrMatch4 : TEST_Op<"match_op_attribute4"> {
1501  let arguments = (ins UnitAttr:$attr1, UnitAttr:$attr2);
1502  let results = (outs I32);
1503}
1504def : Pat<(OpAttrMatch3 $attr), (OpAttrMatch4 ConstUnitAttr, $attr)>;
1505
1506// Test with constant attr.
1507def OpC : TEST_Op<"op_c">, Arguments<(ins I32)>, Results<(outs I32)>;
1508def : Pat<(OpC $input), (OpB $input, ConstantAttr<I32Attr, "17">:$attr)>;
1509
1510// Test integer enum attribute in rewrites.
1511def : Pat<(I32EnumAttrOp I32Case5), (I32EnumAttrOp I32Case10)>;
1512def : Pat<(I64EnumAttrOp I64Case5), (I64EnumAttrOp I64Case10)>;
1513
1514def ThreeResultOp : TEST_Op<"three_result"> {
1515  let arguments = (ins MultiResultOpEnum:$kind);
1516  let results = (outs I32:$result1, F32:$result2, F32:$result3);
1517}
1518
1519def AnotherThreeResultOp
1520    : TEST_Op<"another_three_result",
1521              [DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
1522  let arguments = (ins MultiResultOpEnum:$kind);
1523  let results = (outs I32:$result1, F32:$result2, F32:$result3);
1524}
1525
1526def TwoResultOp : TEST_Op<"two_result"> {
1527  let arguments = (ins MultiResultOpEnum:$kind);
1528  let results = (outs I32:$result1, F32:$result2);
1529}
1530
1531def AnotherTwoResultOp : TEST_Op<"another_two_result"> {
1532  let arguments = (ins MultiResultOpEnum:$kind);
1533  let results = (outs F32:$result1, F32:$result2);
1534}
1535
1536def OneResultOp1 : TEST_Op<"one_result1"> {
1537  let arguments = (ins MultiResultOpEnum:$kind);
1538  let results = (outs F32:$result1);
1539}
1540
1541def OneResultOp2 : TEST_Op<"one_result2"> {
1542  let arguments = (ins MultiResultOpEnum:$kind);
1543  let results = (outs I32:$result1);
1544}
1545
1546def OneResultOp3 : TEST_Op<"one_result3"> {
1547  let arguments = (ins F32);
1548  let results = (outs I32:$result1);
1549}
1550
1551// Test using multi-result op as a whole
1552def : Pat<(ThreeResultOp MultiResultOpKind1:$kind),
1553          (AnotherThreeResultOp $kind)>;
1554
1555// Test using multi-result op as a whole for partial replacement
1556def : Pattern<(ThreeResultOp MultiResultOpKind2:$kind),
1557              [(TwoResultOp $kind),
1558               (OneResultOp1 $kind)]>;
1559def : Pattern<(ThreeResultOp MultiResultOpKind3:$kind),
1560              [(OneResultOp2 $kind),
1561               (AnotherTwoResultOp $kind)]>;
1562
1563// Test using results separately in a multi-result op
1564def : Pattern<(ThreeResultOp MultiResultOpKind4:$kind),
1565              [(TwoResultOp:$res1__0 $kind),
1566               (OneResultOp1 $kind),
1567               (TwoResultOp:$res2__1 $kind)]>;
1568
1569// Test referencing a single value in the value pack
1570// This rule only matches TwoResultOp if its second result has no use.
1571def : Pattern<(TwoResultOp:$res MultiResultOpKind5:$kind),
1572              [(OneResultOp2 $kind),
1573               (OneResultOp1 $kind)],
1574              [(HasNoUseOf:$res__1)]>;
1575
1576// Test using auxiliary ops for replacing multi-result op
1577def : Pattern<
1578    (ThreeResultOp MultiResultOpKind6:$kind), [
1579        // Auxiliary op generated to help building the final result but not
1580        // directly used to replace the source op's results.
1581        (TwoResultOp:$interm $kind),
1582
1583        (OneResultOp3 $interm__1),
1584        (AnotherTwoResultOp $kind)
1585    ]>;
1586
1587//===----------------------------------------------------------------------===//
1588// Test Patterns (Variadic Ops)
1589
1590def OneVResOneVOperandOp1 : TEST_Op<"one_variadic_out_one_variadic_in1"> {
1591  let arguments = (ins Variadic<I32>);
1592  let results = (outs Variadic<I32>);
1593}
1594def OneVResOneVOperandOp2 : TEST_Op<"one_variadic_out_one_variadic_in2"> {
1595  let arguments = (ins Variadic<I32>);
1596  let results = (outs Variadic<I32>);
1597}
1598
1599// Rewrite an op with one variadic operand and one variadic result to
1600// another similar op.
1601def : Pat<(OneVResOneVOperandOp1 $inputs), (OneVResOneVOperandOp2 $inputs)>;
1602
1603def MixedVOperandOp1 : TEST_Op<"mixed_variadic_in1",
1604                               [SameVariadicOperandSize]> {
1605  let arguments = (ins
1606    Variadic<I32>:$input1,
1607    F32:$input2,
1608    Variadic<I32>:$input3
1609  );
1610}
1611
1612def MixedVOperandOp2 : TEST_Op<"mixed_variadic_in2",
1613                               [SameVariadicOperandSize]> {
1614  let arguments = (ins
1615    Variadic<I32>:$input1,
1616    F32:$input2,
1617    Variadic<I32>:$input3
1618  );
1619}
1620
1621// Rewrite an op with both variadic operands and normal operands.
1622def : Pat<(MixedVOperandOp1 $input1, $input2, $input3),
1623          (MixedVOperandOp2 $input1, $input2, $input3)>;
1624
1625def MixedVResultOp1 : TEST_Op<"mixed_variadic_out1", [SameVariadicResultSize]> {
1626  let results = (outs
1627    Variadic<I32>:$output1,
1628    F32:$output2,
1629    Variadic<I32>:$output3
1630  );
1631}
1632
1633def MixedVResultOp2 : TEST_Op<"mixed_variadic_out2", [SameVariadicResultSize]> {
1634  let results = (outs
1635    Variadic<I32>:$output1,
1636    F32:$output2,
1637    Variadic<I32>:$output3
1638  );
1639}
1640
1641// Rewrite an op with both variadic results and normal results.
1642// Note that because we are generating the op with a top-level result pattern,
1643// we are able to deduce the correct result types for the generated op using
1644// the information from the matched root op.
1645def : Pat<(MixedVResultOp1), (MixedVResultOp2)>;
1646
1647def OneI32ResultOp : TEST_Op<"one_i32_out"> {
1648  let results = (outs I32);
1649}
1650
1651def MixedVOperandOp3 : TEST_Op<"mixed_variadic_in3",
1652                               [SameVariadicOperandSize]> {
1653  let arguments = (ins
1654    I32:$input1,
1655    Variadic<I32>:$input2,
1656    Variadic<I32>:$input3,
1657    I32Attr:$count
1658  );
1659
1660  let results = (outs I32);
1661}
1662
1663def MixedVResultOp3 : TEST_Op<"mixed_variadic_out3",
1664                               [SameVariadicResultSize]> {
1665  let arguments = (ins I32Attr:$count);
1666
1667  let results = (outs
1668    I32:$output1,
1669    Variadic<I32>:$output2,
1670    Variadic<I32>:$output3
1671  );
1672
1673  // We will use this op in a nested result pattern, where we cannot deduce the
1674  // result type. So need to provide a builder not requiring result types.
1675  let builders = [
1676    OpBuilder<(ins "::mlir::IntegerAttr":$count),
1677    [{
1678      auto i32Type = $_builder.getIntegerType(32);
1679      $_state.addTypes(i32Type); // $output1
1680      SmallVector<Type, 4> types(count.getInt(), i32Type);
1681      $_state.addTypes(types); // $output2
1682      $_state.addTypes(types); // $output3
1683      $_state.addAttribute("count", count);
1684    }]>
1685  ];
1686}
1687
1688// Generates an op with variadic results using nested pattern.
1689def : Pat<(OneI32ResultOp),
1690          (MixedVOperandOp3
1691              (MixedVResultOp3:$results__0 ConstantAttr<I32Attr, "2">),
1692              (replaceWithValue $results__1),
1693              (replaceWithValue $results__2),
1694              ConstantAttr<I32Attr, "2">)>;
1695
1696// Variadic structured matching
1697def MixedVOperandOp4 : TEST_Op<"mixed_variadic_in4"> {
1698  let arguments = (ins
1699    Variadic<I32>:$input1,
1700    I32:$input2,
1701    I32Attr:$attr1
1702  );
1703}
1704
1705def MixedVOperandOp5 : TEST_Op<"mixed_variadic_in5"> {
1706  let arguments = (ins
1707    I32:$input1,
1708    I32:$input2,
1709    I32:$input3,
1710    I32Attr:$attr1,
1711    StrAttr:$pattern_name
1712  );
1713}
1714
1715// Helper op to test variadic recursive pattern matching
1716def MixedVOperandInOutI32Op : TEST_Op<"mixed_variadic_in_out_i32"> {
1717  let arguments = (ins
1718    I32:$input
1719  );
1720  let results = (outs
1721    I32:$output
1722  );
1723}
1724
1725def : Pat<
1726  (MixedVOperandOp4 (variadic $input1a, $input1b), $input2,
1727                    ConstantAttr<I32Attr, "0">:$attr1),
1728  (MixedVOperandOp5 $input1a, $input1b, $input2, $attr1,
1729                    ConstantStrAttr<StrAttr, "MatchVariadic">)>;
1730
1731def : Pat<
1732  (MixedVOperandOp5 $input1a, $input1b, $input2, $attr1,
1733                    ConstantStrAttr<StrAttr, "MatchInverseVariadic">),
1734  (MixedVOperandOp3 $input2, (variadic $input1b), (variadic $input1a),
1735                    ConstantAttr<I32Attr, "1">:$attr1)>;
1736
1737def : Pat<
1738  (MixedVOperandOp4 (variadic (MixedVOperandInOutI32Op $input1a),
1739                              (MixedVOperandInOutI32Op $input1b)),
1740                    $input2, ConstantAttr<I32Attr, "1">:$attr1),
1741  (MixedVOperandOp5 $input1a, $input1b, $input2, $attr1,
1742                    ConstantStrAttr<StrAttr, "MatchVariadicSubDag">)>;
1743
1744def : Pat<
1745  (MixedVOperandOp4 (variadic $input1, $input1), $input2,
1746                    ConstantAttr<I32Attr, "2">:$attr1),
1747  (MixedVOperandOp5 $input1, $input1, $input2, $attr1,
1748                    ConstantStrAttr<StrAttr, "MatchVariadicSameSymbol">)>;
1749
1750def MixedVOperandOp6 : TEST_Op<"mixed_variadic_in6",
1751                               [SameVariadicOperandSize]> {
1752  let arguments = (ins
1753    Variadic<I32>:$input1,
1754    Variadic<I32>:$input2,
1755    I32Attr:$attr1
1756  );
1757}
1758
1759def : Pat<
1760  (MixedVOperandOp6 (variadic:$input1 $input1a, $input1b),
1761                    (variadic:$input2 $input2a, $input2b),
1762                    ConstantAttr<I32Attr, "1">:$attr1),
1763  (MixedVOperandOp6 $input2, $input1, ConstantAttr<I32Attr, "-1">)>;
1764
1765def : Pat<
1766  (MixedVOperandOp6 (variadic $input1a, $input1b),
1767                    (variadic $input2a, $input2b),
1768                    ConstantAttr<I32Attr, "2">:$attr1),
1769  (MixedVOperandOp5 $input2a, $input2b, $input1b, $attr1,
1770                    ConstantStrAttr<StrAttr, "MatchMultiVariadicSubSymbol">)>;
1771
1772//===----------------------------------------------------------------------===//
1773// Test Patterns (either)
1774
1775def TestEitherOpA : TEST_Op<"either_op_a"> {
1776  let arguments = (ins AnyInteger:$arg0, AnyInteger:$arg1, AnyInteger:$arg2);
1777  let results = (outs I32:$output);
1778}
1779
1780def TestEitherOpB : TEST_Op<"either_op_b"> {
1781  let arguments = (ins AnyInteger:$arg0, AnyInteger:$arg1);
1782  let results = (outs I32:$output);
1783}
1784
1785def : Pat<(TestEitherOpA (either I32:$arg1, I16:$arg2), $x),
1786          (TestEitherOpB $arg2, $x)>;
1787
1788def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1, $_), I16:$arg2), $x),
1789          (TestEitherOpB $arg2, $x)>;
1790
1791def : Pat<(TestEitherOpA (either (TestEitherOpB I32:$arg1, $_),
1792                                 (TestEitherOpB I16:$arg2, $_)),
1793                          $x),
1794          (TestEitherOpB $arg2, $x)>;
1795
1796def TestEitherHelperOpA : TEST_Op<"either_helper_op_a"> {
1797  let arguments = (ins I32:$arg0);
1798  let results = (outs I32:$output);
1799}
1800
1801def TestEitherHelperOpB : TEST_Op<"either_helper_op_b"> {
1802  let arguments = (ins I32:$arg0);
1803  let results = (outs I32:$output);
1804}
1805
1806// This test case ensures `emitOpMatch` doesn't redefine `castedOp{0}` local
1807// variables. To trigger this, we must ensure the matcher for
1808// `TestEitherHelperOpA` and `TestEitherHelperOpB` are not lifted as a static
1809// matcher.
1810def : Pat<(TestEitherOpB (either (TestEitherHelperOpA I32:$either_helper_0),
1811                                 (TestEitherHelperOpB I32:$either_helper_1))),
1812          (TestEitherOpB $either_helper_0, $either_helper_1)>;
1813
1814//===----------------------------------------------------------------------===//
1815// Test Patterns (Location)
1816
1817// Test that we can specify locations for generated ops.
1818def : Pat<(TestLocationSrcOp:$res1
1819           (TestLocationSrcOp:$res2
1820            (TestLocationSrcOp:$res3 $input))),
1821          (TestLocationDstOp
1822            (TestLocationDstOp
1823              (TestLocationDstOp $input, (location $res1)),
1824              (location "named")),
1825            (location "fused", $res2, $res3))>;
1826
1827// Test that we can use the location of an op without results
1828def : Pat<(TestLocationSrcNoResOp:$loc
1829            (TestLocationSrcOp (TestLocationSrcOp $input))),
1830          (TestLocationDstNoResOp $input, (location $loc))>;
1831
1832//===----------------------------------------------------------------------===//
1833// Test Patterns (Type Builders)
1834
1835def SourceOp : TEST_Op<"source_op"> {
1836  let arguments = (ins AnyInteger:$arg, AnyI32Attr:$tag);
1837  let results = (outs AnyInteger);
1838}
1839
1840// An op without return type deduction.
1841def OpX : TEST_Op<"op_x"> {
1842  let arguments = (ins AnyInteger:$input);
1843  let results = (outs AnyInteger);
1844}
1845
1846// Test that ops without built-in type deduction can be created in the
1847// replacement DAG with an explicitly specified type.
1848def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "11">:$attr),
1849          (OpX (OpX $val, (returnType "$_builder.getI32Type()")))>;
1850// Test NativeCodeCall type builder can accept arguments.
1851def SameTypeAs : NativeCodeCall<"$0.getType()">;
1852
1853def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "22">:$attr),
1854          (OpX (OpX $val, (returnType (SameTypeAs $val))))>;
1855
1856// Test multiple return types.
1857def MakeI64Type : NativeCodeCall<"$_builder.getI64Type()">;
1858def MakeI32Type : NativeCodeCall<"$_builder.getI32Type()">;
1859
1860def OneToTwo : TEST_Op<"one_to_two"> {
1861  let arguments = (ins AnyInteger);
1862  let results = (outs AnyInteger, AnyInteger);
1863}
1864
1865def TwoToOne : TEST_Op<"two_to_one"> {
1866  let arguments = (ins AnyInteger, AnyInteger);
1867  let results = (outs AnyInteger);
1868}
1869
1870def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "33">:$attr),
1871          (TwoToOne (OpX (OneToTwo:$res__0 $val, (returnType (MakeI64Type), (MakeI32Type))), (returnType (MakeI32Type))),
1872                    (OpX $res__1, (returnType (MakeI64Type))))>;
1873
1874// Test copy value return type.
1875def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "44">:$attr),
1876          (OpX (OpX $val, (returnType $val)))>;
1877
1878// Test create multiple return types with different methods.
1879def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "55">:$attr),
1880          (TwoToOne (OneToTwo:$res__0 $val, (returnType $val, "$_builder.getI64Type()")), $res__1)>;
1881
1882//===----------------------------------------------------------------------===//
1883// Test Patterns (Trailing Directives)
1884
1885// Test that we can specify both `location` and `returnType` directives.
1886def : Pat<(SourceOp $val, ConstantAttr<I32Attr, "66">:$attr),
1887          (TwoToOne (OpX $val, (returnType $val), (location "loc1")),
1888                    (OpX $val, (location "loc2"), (returnType $val)))>;
1889
1890//===----------------------------------------------------------------------===//
1891// Test Legalization
1892//===----------------------------------------------------------------------===//
1893
1894def Test_LegalizerEnum_Success : ConstantStrAttr<StrAttr, "Success">;
1895def Test_LegalizerEnum_Failure : ConstantStrAttr<StrAttr, "Failure">;
1896
1897def ILLegalOpA : TEST_Op<"illegal_op_a">, Results<(outs I32)>;
1898def ILLegalOpB : TEST_Op<"illegal_op_b">, Results<(outs I32)>;
1899def ILLegalOpC : TEST_Op<"illegal_op_c">, Results<(outs I32)>;
1900def ILLegalOpD : TEST_Op<"illegal_op_d">, Results<(outs I32)>;
1901def ILLegalOpE : TEST_Op<"illegal_op_e">, Results<(outs I32)>;
1902def ILLegalOpF : TEST_Op<"illegal_op_f">, Results<(outs I32)>;
1903def ILLegalOpG : TEST_Op<"illegal_op_g">, Results<(outs I32)>;
1904def LegalOpA : TEST_Op<"legal_op_a">,
1905  Arguments<(ins StrAttr:$status)>, Results<(outs I32)>;
1906def LegalOpB : TEST_Op<"legal_op_b">, Results<(outs I32)>;
1907def LegalOpC : TEST_Op<"legal_op_c">,
1908  Arguments<(ins I32)>, Results<(outs I32)>;
1909def LegalOpD : TEST_Op<"legal_op_d">, Arguments<(ins AnyType)>;
1910
1911def DuplicateBlockArgsOp : TEST_Op<"duplicate_block_args", [SingleBlock]> {
1912  let arguments = (ins UnitAttr:$is_legal);
1913  let regions = (region SizedRegion<1>:$body);
1914}
1915
1916// Check that the conversion infrastructure can properly undo the creation of
1917// operations where an operation was created before its parent, in this case,
1918// in the parent's builder.
1919def IllegalOpTerminator : TEST_Op<"illegal_op_terminator", [Terminator]>;
1920def IllegalOpWithRegion : TEST_Op<"illegal_op_with_region"> {
1921  let skipDefaultBuilders = 1;
1922  let builders = [OpBuilder<(ins),
1923    [{
1924       Region *bodyRegion = $_state.addRegion();
1925       OpBuilder::InsertionGuard g($_builder);
1926       Block *body = $_builder.createBlock(bodyRegion);
1927       $_builder.setInsertionPointToEnd(body);
1928       $_builder.create<IllegalOpTerminator>($_state.location);
1929    }]>];
1930}
1931def IllegalOpWithRegionAnchor : TEST_Op<"illegal_op_with_region_anchor">;
1932
1933// Check that smaller pattern depths are chosen, i.e. prioritize more direct
1934// mappings.
1935def : Pat<(ILLegalOpA), (LegalOpA Test_LegalizerEnum_Success)>;
1936
1937def : Pat<(ILLegalOpA), (ILLegalOpB)>;
1938def : Pat<(ILLegalOpB), (LegalOpA Test_LegalizerEnum_Failure)>;
1939
1940// Check that the higher benefit pattern is taken for multiple legalizations
1941// with the same depth.
1942def : Pat<(ILLegalOpC), (ILLegalOpD)>;
1943def : Pat<(ILLegalOpD), (LegalOpA Test_LegalizerEnum_Failure)>;
1944
1945def : Pat<(ILLegalOpC), (ILLegalOpE), [], [], (addBenefit 10)>;
1946def : Pat<(ILLegalOpE), (LegalOpA Test_LegalizerEnum_Success)>;
1947
1948// Check that patterns use the most up-to-date value when being replaced.
1949def TestRewriteOp : TEST_Op<"rewrite">,
1950  Arguments<(ins AnyType)>, Results<(outs AnyType)>;
1951def : Pat<(TestRewriteOp $input), (replaceWithValue $input)>;
1952
1953// Check that patterns can specify bounded recursion when rewriting.
1954def TestRecursiveRewriteOp : TEST_Op<"recursive_rewrite"> {
1955  let arguments = (ins I64Attr:$depth);
1956  let assemblyFormat = "$depth attr-dict";
1957}
1958
1959// Test legalization pattern: this op will be erase and will also erase the
1960// producer of its operand.
1961def BlackHoleOp : TEST_Op<"blackhole">,
1962  Arguments<(ins AnyType)>;
1963
1964//===----------------------------------------------------------------------===//
1965// Test Type Legalization
1966//===----------------------------------------------------------------------===//
1967
1968def TestRegionBuilderOp : TEST_Op<"region_builder">;
1969def TestReturnOp : TEST_Op<"return", [Pure, ReturnLike, Terminator]> {
1970  let arguments = (ins Variadic<AnyType>);
1971  let builders = [OpBuilder<(ins),
1972    [{ build($_builder, $_state, {}); }]>
1973  ];
1974}
1975def TestCastOp : TEST_Op<"cast">,
1976  Arguments<(ins Variadic<AnyType>)>, Results<(outs AnyType)>;
1977def TestInvalidOp : TEST_Op<"invalid", [Terminator]>,
1978  Arguments<(ins Variadic<AnyType>)>;
1979def TestTypeProducerOp : TEST_Op<"type_producer">,
1980  Results<(outs AnyType)>;
1981def TestAnotherTypeProducerOp : TEST_Op<"another_type_producer">,
1982  Results<(outs AnyType)>;
1983def TestTypeConsumerOp : TEST_Op<"type_consumer">,
1984  Arguments<(ins AnyType)>;
1985def TestTypeChangerOp : TEST_Op<"type_changer">,
1986  Arguments<(ins AnyType)>, Results<(outs AnyType)>;
1987def TestValidOp : TEST_Op<"valid", [Terminator]>,
1988  Arguments<(ins Variadic<AnyType>)>;
1989
1990def TestMergeBlocksOp : TEST_Op<"merge_blocks"> {
1991  let summary = "merge_blocks operation";
1992  let description = [{
1993    Test op with multiple blocks that are merged with Dialect Conversion
1994  }];
1995
1996  let regions = (region AnyRegion:$body);
1997  let results = (outs Variadic<AnyType>:$result);
1998}
1999
2000def TestRemappedValueRegionOp : TEST_Op<"remapped_value_region",
2001                                        [SingleBlock]> {
2002  let summary = "remapped_value_region operation";
2003  let description = [{
2004    Test op that remaps values that haven't yet been converted in Dialect
2005    Conversion.
2006  }];
2007
2008  let regions = (region SizedRegion<1>:$body);
2009  let results = (outs Variadic<AnyType>:$result);
2010}
2011
2012def TestSignatureConversionUndoOp : TEST_Op<"signature_conversion_undo"> {
2013  let regions = (region AnyRegion);
2014}
2015
2016def TestSignatureConversionNoConverterOp
2017  : TEST_Op<"signature_conversion_no_converter"> {
2018  let regions = (region AnyRegion);
2019}
2020
2021//===----------------------------------------------------------------------===//
2022// Test parser.
2023//===----------------------------------------------------------------------===//
2024
2025def ParseIntegerLiteralOp : TEST_Op<"parse_integer_literal"> {
2026  let results = (outs Variadic<Index>:$results);
2027  let hasCustomAssemblyFormat = 1;
2028}
2029
2030def ParseWrappedKeywordOp : TEST_Op<"parse_wrapped_keyword"> {
2031  let arguments = (ins StrAttr:$keyword);
2032  let hasCustomAssemblyFormat = 1;
2033}
2034
2035def ParseB64BytesOp : TEST_Op<"parse_b64"> {
2036  let arguments = (ins StrAttr:$b64);
2037  let hasCustomAssemblyFormat = 1;
2038}
2039
2040//===----------------------------------------------------------------------===//
2041// Test region argument list parsing.
2042
2043def IsolatedRegionOp : TEST_Op<"isolated_region", [IsolatedFromAbove]> {
2044  let summary =  "isolated region operation";
2045  let description = [{
2046    Test op with an isolated region, to test passthrough region arguments. Each
2047    argument is of index type.
2048  }];
2049
2050  let arguments = (ins Index);
2051  let regions = (region SizedRegion<1>:$region);
2052  let hasCustomAssemblyFormat = 1;
2053}
2054
2055def SSACFGRegionOp : TEST_Op<"ssacfg_region",  [
2056    DeclareOpInterfaceMethods<RegionKindInterface>]> {
2057  let summary =  "operation with an SSACFG region";
2058  let description = [{
2059    Test op that defines an SSACFG region.
2060  }];
2061
2062  let regions = (region VariadicRegion<AnyRegion>:$regions);
2063  let arguments = (ins Variadic<AnyType>);
2064  let results = (outs Variadic<AnyType>);
2065}
2066
2067def GraphRegionOp : TEST_Op<"graph_region",  [
2068    DeclareOpInterfaceMethods<RegionKindInterface>]> {
2069  let summary =  "operation with a graph region";
2070  let description = [{
2071    Test op that defines a graph region.
2072  }];
2073
2074  let regions = (region AnyRegion:$region);
2075  let assemblyFormat = "attr-dict-with-keyword $region";
2076}
2077
2078def IsolatedGraphRegionOp : TEST_Op<"isolated_graph_region",  [
2079    DeclareOpInterfaceMethods<RegionKindInterface>,
2080    IsolatedFromAbove]> {
2081  let summary =  "isolated from above operation with a graph region";
2082  let description = [{
2083    Test op that defines a graph region which is isolated from above.
2084  }];
2085
2086  let regions = (region AnyRegion:$region);
2087  let assemblyFormat = "attr-dict-with-keyword $region";
2088}
2089
2090def AffineScopeOp : TEST_Op<"affine_scope", [AffineScope]> {
2091  let summary =  "affine scope operation";
2092  let description = [{
2093    Test op that defines a new affine scope.
2094  }];
2095
2096  let regions = (region SizedRegion<1>:$region);
2097  let hasCustomAssemblyFormat = 1;
2098}
2099
2100//===----------------------------------------------------------------------===//
2101// Custom printer/parser
2102
2103def CustomDimensionListAttrOp : TEST_Op<"custom_dimension_list_attr"> {
2104  let description = [{
2105    Test printing/parsing of dimension list attribute.
2106  }];
2107  let arguments = (ins DenseI64ArrayAttr:$dimension_list);
2108  let assemblyFormat = [{
2109    `dimension_list` `=` custom<DimensionList>($dimension_list)
2110    attr-dict
2111  }];
2112}
2113
2114def OptionalCustomAttrOp : TEST_Op<"optional_custom_attr"> {
2115  let description = [{
2116    Test using a custom directive as the optional group anchor and the first
2117    element to parse. It is expected to return an `OptionalParseResult`.
2118  }];
2119  let arguments = (ins OptionalAttr<I1Attr>:$attr);
2120  let assemblyFormat = [{
2121    attr-dict (custom<OptionalCustomParser>($attr)^) : (`bar`)?
2122  }];
2123}
2124
2125//===----------------------------------------------------------------------===//
2126// Test OpAsmInterface.
2127
2128def AsmInterfaceOp : TEST_Op<"asm_interface_op"> {
2129  let results = (outs AnyType:$first, Variadic<AnyType>:$middle_results,
2130                      AnyType);
2131}
2132
2133def AsmDialectInterfaceOp : TEST_Op<"asm_dialect_interface_op"> {
2134  let results = (outs AnyType);
2135}
2136
2137//===----------------------------------------------------------------------===//
2138// Test ArrayOfAttr
2139//===----------------------------------------------------------------------===//
2140
2141// Embed the array attributes directly in the assembly format for a nice syntax.
2142def ArrayOfAttrOp : TEST_Op<"array_of_attr_op"> {
2143  let arguments = (ins TestArrayOfUglyAttrs:$a, TestArrayOfInts:$b,
2144                       TestArrayOfEnums:$c);
2145  let assemblyFormat = "`a` `=` $a `,` `b` `=` $b `,` `c` `=` $c attr-dict";
2146}
2147
2148//===----------------------------------------------------------------------===//
2149// Test SideEffects
2150//===----------------------------------------------------------------------===//
2151
2152def SideEffectOp : TEST_Op<"side_effect_op",
2153    [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
2154     DeclareOpInterfaceMethods<TestEffectOpInterface>]> {
2155  let results = (outs AnyType:$result);
2156}
2157
2158def SideEffectWithRegionOp : TEST_Op<"side_effect_with_region_op",
2159    [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
2160     DeclareOpInterfaceMethods<TestEffectOpInterface>]> {
2161  let arguments = (ins AnyType:$operand);
2162  let results = (outs AnyType:$result);
2163  let regions = (region AnyRegion:$region);
2164  let assemblyFormat = [{
2165    `(` $operand`)` $region attr-dict `:`  type($operand)  `->` type($result)
2166  }];
2167}
2168
2169//===----------------------------------------------------------------------===//
2170// Test CopyOpInterface
2171//===----------------------------------------------------------------------===//
2172
2173def CopyOp : TEST_Op<"copy", [CopyOpInterface]> {
2174  let description = [{
2175    Represents a copy operation.
2176  }];
2177  let arguments = (ins Res<AnyRankedOrUnrankedMemRef, "", [MemRead]>:$source,
2178                   Res<AnyRankedOrUnrankedMemRef, "", [MemWrite]>:$target);
2179  let assemblyFormat = [{
2180    `(` $source `,` $target `)` `:` `(` type($source) `,` type($target) `)`
2181     attr-dict
2182  }];
2183}
2184
2185//===----------------------------------------------------------------------===//
2186// Test Buffer/Tensor
2187//===----------------------------------------------------------------------===//
2188
2189def RegionYieldOp : TEST_Op<"region_yield",
2190      [Pure, ReturnLike, Terminator]> {
2191  let description = [{
2192    This operation is used in a region and yields the corresponding type for
2193    that operation.
2194  }];
2195  let arguments = (ins AnyType:$result);
2196  let assemblyFormat = [{
2197    $result `:` type($result) attr-dict
2198  }];
2199  let builders = [OpBuilder<(ins),
2200    [{ build($_builder, $_state, {}); }]>
2201  ];
2202}
2203
2204class BufferBasedOpBase<string mnemonic, list<Trait> traits>
2205    : TEST_Op<mnemonic, traits> {
2206  let description = [{
2207    A buffer based operation, that uses memRefs as input and output.
2208  }];
2209  let arguments = (ins Arg<AnyRankedOrUnrankedMemRef, "reading",
2210                           [MemRead]>:$input,
2211                       Arg<AnyRankedOrUnrankedMemRef, "writing",
2212                           [MemWrite]>:$output);
2213}
2214
2215def BufferBasedOp : BufferBasedOpBase<"buffer_based", []>{
2216  let assemblyFormat = [{
2217    `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`
2218    attr-dict
2219  }];
2220}
2221
2222def RegionBufferBasedOp : BufferBasedOpBase<"region_buffer_based",
2223      [SingleBlockImplicitTerminator<"RegionYieldOp">]> {
2224  let regions = (region AnyRegion:$region);
2225  let assemblyFormat = [{
2226    `in` `(` $input`:` type($input) `)` `out` `(` $output`:` type($output) `)`
2227    $region attr-dict
2228  }];
2229}
2230
2231def TensorBasedOp : TEST_Op<"tensor_based", []> {
2232  let description = [{
2233    A tensor based operation, that uses a tensor as an input and results in a
2234    tensor again.
2235  }];
2236  let arguments = (ins AnyRankedTensor:$input);
2237  let results = (outs AnyRankedTensor:$result);
2238  let assemblyFormat = [{
2239    `in` `(` $input`:` type($input) `)` `->` type($result) attr-dict
2240  }];
2241}
2242
2243def ReadBufferOp : TEST_Op<"read_buffer", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
2244  let description = [{
2245    An operation that reads the buffer operand and dumps its contents.
2246  }];
2247  let arguments = (ins AnyRankedOrUnrankedMemRef:$buffer);
2248}
2249
2250def ForwardBufferOp : TEST_Op<"forward_buffer", [Pure]> {
2251  let description = [{
2252    A pure operation that takes a buffer and returns a buffer. This op does not
2253    have any side effects, so it cannot allocate or read a buffer from memory.
2254    It must return the input buffer (or a view thereof). This op purposely does
2255    does not implement any interface.
2256  }];
2257  let arguments = (ins AnyRankedOrUnrankedMemRef:$buffer);
2258  let results = (outs AnyRankedOrUnrankedMemRef:$result);
2259}
2260
2261//===----------------------------------------------------------------------===//
2262// Test ValueBoundsOpInterface
2263//===----------------------------------------------------------------------===//
2264
2265def ReifyBoundOp : TEST_Op<"reify_bound", [Pure]> {
2266  let description = [{
2267    Reify a bound for the given index-typed value or dimension size of a shaped
2268    value. "LB", "EQ" and "UB" bounds are supported. If `scalable` is set,
2269    `vscale_min` and `vscale_max` must be provided, which allows computing
2270    a bound in terms of "vector.vscale" for a given range of vscale.
2271  }];
2272
2273  let arguments = (ins AnyType:$var,
2274                       OptionalAttr<I64Attr>:$dim,
2275                       DefaultValuedAttr<StrAttr, "\"EQ\"">:$type,
2276                       UnitAttr:$constant,
2277                       UnitAttr:$scalable,
2278                       OptionalAttr<I64Attr>:$vscale_min,
2279                       OptionalAttr<I64Attr>:$vscale_max);
2280  let results = (outs Index:$result);
2281
2282  let extraClassDeclaration = [{
2283    ::mlir::presburger::BoundType getBoundType();
2284    ::mlir::ValueBoundsConstraintSet::Variable getVariable();
2285  }];
2286
2287  let hasVerifier = 1;
2288}
2289
2290def CompareOp : TEST_Op<"compare"> {
2291  let description = [{
2292    Compare `lhs` and `rhs`. A remark is emitted which indicates whether the
2293    specified comparison operator was proven to hold. The remark also indicates
2294    whether the opposite comparison operator was proven to hold.
2295
2296    `var_operands` must have exactly two operands: one for the LHS operand and
2297    one for the RHS operand. If `lhs_map` is specified, as many operands as
2298    `lhs_map` has inputs are expected instead of the first operand. If `rhs_map`
2299    is specified, as many operands as `rhs_map` has inputs are expected instead
2300    of the second operand.
2301  }];
2302
2303  let arguments = (ins Variadic<Index>:$var_operands,
2304                       DefaultValuedAttr<StrAttr, "\"EQ\"">:$cmp,
2305                       OptionalAttr<AffineMapAttr>:$lhs_map,
2306                       OptionalAttr<AffineMapAttr>:$rhs_map,
2307                       UnitAttr:$compose);
2308  let results = (outs);
2309
2310  let extraClassDeclaration = [{
2311    ::mlir::ValueBoundsConstraintSet::ComparisonOperator
2312        getComparisonOperator();
2313    ::mlir::ValueBoundsConstraintSet::Variable getLhs();
2314    ::mlir::ValueBoundsConstraintSet::Variable getRhs();
2315  }];
2316
2317  let hasVerifier = 1;
2318}
2319
2320//===----------------------------------------------------------------------===//
2321// Test RegionBranchOpInterface
2322//===----------------------------------------------------------------------===//
2323
2324def RegionIfYieldOp : TEST_Op<"region_if_yield",
2325      [NoMemoryEffect, ReturnLike, Terminator]> {
2326  let arguments = (ins Variadic<AnyType>:$results);
2327  let assemblyFormat = [{
2328    $results `:` type($results) attr-dict
2329  }];
2330}
2331
2332def RegionIfOp : TEST_Op<"region_if",
2333      [DeclareOpInterfaceMethods<RegionBranchOpInterface,
2334                                 ["getRegionInvocationBounds",
2335                                  "getEntrySuccessorOperands"]>,
2336       SingleBlockImplicitTerminator<"RegionIfYieldOp">,
2337       RecursiveMemoryEffects]> {
2338  let description =[{
2339    Represents an abstract if-then-else-join pattern. In this context, the then
2340    and else regions jump to the join region, which finally returns to its
2341    parent op.
2342  }];
2343
2344  let arguments = (ins Variadic<AnyType>);
2345  let results = (outs Variadic<AnyType>:$results);
2346  let regions = (region SizedRegion<1>:$thenRegion,
2347                        AnyRegion:$elseRegion,
2348                        AnyRegion:$joinRegion);
2349  let extraClassDeclaration = [{
2350    ::mlir::Block::BlockArgListType getThenArgs() {
2351      return getBody(0)->getArguments();
2352    }
2353    ::mlir::Block::BlockArgListType getElseArgs() {
2354      return getBody(1)->getArguments();
2355    }
2356    ::mlir::Block::BlockArgListType getJoinArgs() {
2357      return getBody(2)->getArguments();
2358    }
2359  }];
2360  let hasCustomAssemblyFormat = 1;
2361}
2362
2363def AnyCondOp : TEST_Op<"any_cond",
2364      [DeclareOpInterfaceMethods<RegionBranchOpInterface,
2365                                 ["getRegionInvocationBounds"]>,
2366       RecursiveMemoryEffects]> {
2367  let results = (outs Variadic<AnyType>:$results);
2368  let regions = (region AnyRegion:$region);
2369}
2370
2371def LoopBlockOp : TEST_Op<"loop_block",
2372    [DeclareOpInterfaceMethods<RegionBranchOpInterface,
2373        ["getEntrySuccessorOperands"]>, RecursiveMemoryEffects]> {
2374
2375  let results = (outs F32:$floatResult);
2376  let arguments = (ins I32:$init);
2377  let regions = (region SizedRegion<1>:$body);
2378
2379  let assemblyFormat = [{
2380    $init `:` functional-type($init, $floatResult) $body
2381    attr-dict-with-keyword
2382  }];
2383}
2384
2385def LoopBlockTerminatorOp : TEST_Op<"loop_block_term",
2386    [DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>, Pure,
2387     Terminator]> {
2388  let arguments = (ins I32:$nextIterArg, F32:$exitArg);
2389
2390  let assemblyFormat = [{
2391    `iter` $nextIterArg `exit` $exitArg attr-dict
2392  }];
2393}
2394
2395def TestNoTerminatorOp : TEST_Op<"switch_with_no_break", [
2396    NoTerminator,
2397    DeclareOpInterfaceMethods<RegionBranchOpInterface, ["getSuccessorRegions"]>
2398  ]> {
2399  let arguments = (ins Index:$arg, DenseI64ArrayAttr:$cases);
2400  let regions = (region VariadicRegion<SizedRegion<1>>:$caseRegions);
2401
2402  let assemblyFormat = [{
2403    $arg attr-dict custom<SwitchCases>($cases, $caseRegions)
2404  }];
2405}
2406
2407//===----------------------------------------------------------------------===//
2408// Test TableGen generated build() methods
2409//===----------------------------------------------------------------------===//
2410
2411def TableGenConstant : TEST_Op<"tblgen_constant"> {
2412  let results = (outs AnyType);
2413}
2414
2415// No variadic args or results.
2416def TableGenBuildOp0 : TEST_Op<"tblgen_build_0"> {
2417  let arguments = (ins AnyType:$value);
2418  let results = (outs AnyType:$result);
2419}
2420
2421// Sigle variadic arg and single variadic results.
2422def TableGenBuildOp1 : TEST_Op<"tblgen_build_1"> {
2423  let arguments = (ins Variadic<AnyType>:$inputs);
2424  let results = (outs Variadic<AnyType>:$results);
2425}
2426
2427// Single variadic arg and non-variadic results.
2428def TableGenBuildOp2 : TEST_Op<"tblgen_build_2"> {
2429  let arguments = (ins Variadic<AnyType>:$inputs);
2430  let results = (outs AnyType:$result);
2431}
2432
2433// Single variadic arg and multiple variadic results.
2434def TableGenBuildOp3 : TEST_Op<"tblgen_build_3", [SameVariadicResultSize]> {
2435  let arguments = (ins Variadic<AnyType>:$inputs);
2436  let results = (outs Variadic<AnyType>:$resultA, Variadic<AnyType>:$resultB);
2437}
2438
2439// Single variadic arg, non variadic results, with SameOperandsAndResultType.
2440// Tests suppression of ambiguous build methods for operations with
2441// SameOperandsAndResultType trait.
2442def TableGenBuildOp4 : TEST_Op<"tblgen_build_4", [SameOperandsAndResultType]> {
2443  let arguments = (ins Variadic<AnyType>:$inputs);
2444  let results = (outs AnyType:$result);
2445}
2446
2447// Base class for testing `build` methods for ops with
2448// InferReturnTypeOpInterface.
2449class TableGenBuildInferReturnTypeBaseOp<string mnemonic,
2450                                         list<Trait> traits = []>
2451    : TEST_Op<mnemonic, [InferTypeOpInterface] # traits> {
2452  let arguments = (ins Variadic<AnyType>:$inputs);
2453  let results = (outs AnyType:$result);
2454
2455  let extraClassDeclaration = [{
2456    static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *,
2457          ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
2458          ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
2459          ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
2460      inferredReturnTypes.assign({operands[0].getType()});
2461      return ::mlir::success();
2462    }
2463   }];
2464}
2465
2466// Op with InferTypeOpInterface and regions.
2467def TableGenBuildOp5 : TableGenBuildInferReturnTypeBaseOp<
2468    "tblgen_build_5", [InferTypeOpInterface]> {
2469  let regions = (region AnyRegion:$body);
2470}
2471
2472// Two variadic args, non variadic results, with AttrSizedOperandSegments
2473// Test build method generation for property conversion & type inference.
2474def TableGenBuildOp6 : TEST_Op<"tblgen_build_6", [AttrSizedOperandSegments]> {
2475  let arguments = (ins Variadic<AnyType>:$a, Variadic<AnyType>:$b);
2476  let results = (outs F32:$result);
2477}
2478
2479//===----------------------------------------------------------------------===//
2480// Test BufferPlacement
2481//===----------------------------------------------------------------------===//
2482
2483def GetTupleElementOp: TEST_Op<"get_tuple_element"> {
2484  let description = [{
2485    Test op that returns a specified element of the tuple.
2486  }];
2487
2488  let arguments = (ins
2489    TupleOf<[AnyType]>,
2490    I32Attr:$index
2491  );
2492  let results = (outs AnyType);
2493}
2494
2495def MakeTupleOp: TEST_Op<"make_tuple"> {
2496  let description = [{
2497    Test op that creates a tuple value from a list of values.
2498  }];
2499
2500  let arguments = (ins
2501    Variadic<AnyType>:$inputs
2502  );
2503  let results = (outs TupleOf<[AnyType]>);
2504}
2505
2506//===----------------------------------------------------------------------===//
2507// Test Target DataLayout
2508//===----------------------------------------------------------------------===//
2509
2510def OpWithDataLayoutOp : TEST_Op<"op_with_data_layout",
2511                                 [HasDefaultDLTIDataLayout, DataLayoutOpInterface]> {
2512  let summary =
2513      "An op that uses DataLayout implementation from the Target dialect";
2514  let regions = (region VariadicRegion<AnyRegion>:$regions);
2515}
2516
2517def DataLayoutQueryOp : TEST_Op<"data_layout_query"> {
2518  let summary = "A token op recognized by data layout query test pass";
2519  let description = [{
2520    The data layout query pass pattern-matches this op and attaches to it an
2521    array attribute containing the result of data layout query of the result
2522    type of this op.
2523  }];
2524
2525  let results = (outs AnyType:$res);
2526}
2527
2528//===----------------------------------------------------------------------===//
2529// Test Reducer Patterns
2530//===----------------------------------------------------------------------===//
2531
2532def OpCrashLong : TEST_Op<"op_crash_long"> {
2533  let arguments = (ins I32, I32, I32);
2534  let results = (outs I32);
2535}
2536
2537def OpCrashShort : TEST_Op<"op_crash_short"> {
2538  let results = (outs I32);
2539}
2540
2541def : Pat<(OpCrashLong $_, $_, $_), (OpCrashShort)>;
2542
2543//===----------------------------------------------------------------------===//
2544// Test DestinationStyleOpInterface.
2545//===----------------------------------------------------------------------===//
2546
2547def TestDestinationStyleOp :
2548    TEST_Op<"destination_style_op", [
2549      DestinationStyleOpInterface,
2550      AttrSizedOperandSegments]> {
2551  let arguments = (ins
2552    Variadic<AnyType>:$inputs,
2553    Variadic<AnyType>:$outputs,
2554    Variadic<AnyType>:$other_operands);
2555  let results = (outs Variadic<AnyType>:$results);
2556  let assemblyFormat = [{
2557    attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?
2558    (`outs` `(` $outputs^  `:` type($outputs) `)`)?
2559    (`(` $other_operands^ `:` type($other_operands) `)`)?
2560    (`->` type($results)^)?
2561  }];
2562
2563  let extraClassDeclaration = [{
2564    mlir::MutableOperandRange getDpsInitsMutable() {
2565      return getOutputsMutable();
2566    }
2567  }];
2568}
2569
2570//===----------------------------------------------------------------------===//
2571// Test LinalgConvolutionOpInterface.
2572//===----------------------------------------------------------------------===//
2573
2574def TestLinalgConvOpNotLinalgOp : TEST_Op<"conv_op_not_linalg_op", [
2575    LinalgConvolutionOpInterface]> {
2576  let arguments = (ins
2577    AnyType:$image, AnyType:$filter, AnyType:$output);
2578  let results = (outs AnyRankedTensor:$result);
2579}
2580
2581def TestLinalgConvOp :
2582  TEST_Op<"linalg_conv_op", [AttrSizedOperandSegments, SingleBlock,
2583      DestinationStyleOpInterface, LinalgStructuredInterface,
2584      LinalgConvolutionOpInterface]> {
2585
2586  let arguments = (ins Variadic<AnyType>:$inputs,
2587    Variadic<AnyType>:$outputs);
2588  let results = (outs Variadic<AnyType>:$results);
2589  let regions = (region AnyRegion:$region);
2590
2591  let assemblyFormat = [{
2592    attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?
2593    `outs` `(` $outputs `:` type($outputs) `)`
2594    $region (`->` type($results)^)?
2595  }];
2596
2597  let extraClassDeclaration = [{
2598    bool hasIndexSemantics() { return false; }
2599
2600    static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,
2601                              mlir::ArrayRef<mlir::NamedAttribute> attrs) {
2602      b.create<mlir::linalg::YieldOp>(block.getArguments().back());
2603    }
2604
2605    static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,
2606                              mlir::ArrayRef<mlir::NamedAttribute>)>
2607    getRegionBuilder() {
2608      return &regionBuilder;
2609    }
2610
2611    llvm::SmallVector<mlir::utils::IteratorType> getIteratorTypesArray() {
2612      auto attrs = getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");
2613      auto range = attrs.getAsValueRange<IteratorTypeAttr, mlir::utils::IteratorType>();
2614      return {range.begin(), range.end()};
2615    }
2616
2617    mlir::ArrayAttr getIndexingMaps() {
2618      return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");
2619    }
2620
2621    std::string getLibraryCallName() {
2622      return "";
2623    }
2624
2625    mlir::MutableOperandRange getDpsInitsMutable() {
2626      return getOutputsMutable();
2627    }
2628  }];
2629}
2630
2631//===----------------------------------------------------------------------===//
2632// Test LinalgFillOpInterface.
2633//===----------------------------------------------------------------------===//
2634
2635def TestLinalgFillOpNotLinalgOp : TEST_Op<"fill_op_not_linalg_op", [
2636    LinalgFillOpInterface]> {
2637  let arguments = (ins
2638    AnyType:$value, AnyType:$output);
2639  let results = (outs AnyRankedTensor:$result);
2640}
2641
2642def TestLinalgFillOp :
2643  TEST_Op<"linalg_fill_op", [AttrSizedOperandSegments, SingleBlock,
2644      DestinationStyleOpInterface, LinalgStructuredInterface,
2645      LinalgFillOpInterface]> {
2646
2647  let arguments = (ins Variadic<AnyType>:$inputs,
2648    Variadic<AnyType>:$outputs);
2649  let results = (outs Variadic<AnyType>:$results);
2650  let regions = (region AnyRegion:$region);
2651
2652  let assemblyFormat = [{
2653    attr-dict (`ins` `(` $inputs^ `:` type($inputs) `)`)?
2654    `outs` `(` $outputs `:` type($outputs) `)`
2655    $region (`->` type($results)^)?
2656  }];
2657
2658  let extraClassDeclaration = [{
2659    bool hasIndexSemantics() { return false; }
2660
2661    static void regionBuilder(mlir::ImplicitLocOpBuilder &b, mlir::Block &block,
2662                              mlir::ArrayRef<mlir::NamedAttribute> attrs) {
2663      b.create<mlir::linalg::YieldOp>(block.getArguments().back());
2664    }
2665
2666    static std::function<void(mlir::ImplicitLocOpBuilder &, mlir::Block &,
2667                              mlir::ArrayRef<mlir::NamedAttribute>)>
2668    getRegionBuilder() {
2669      return &regionBuilder;
2670    }
2671
2672    llvm::SmallVector<mlir::utils::IteratorType> getIteratorTypesArray() {
2673      auto attrs = getOperation()->getAttrOfType<mlir::ArrayAttr>("iterator_types");
2674      auto range = attrs.getAsValueRange<IteratorTypeAttr, mlir::utils::IteratorType>();
2675      return {range.begin(), range.end()};
2676    }
2677
2678    mlir::ArrayAttr getIndexingMaps() {
2679      return getOperation()->getAttrOfType<mlir::ArrayAttr>("indexing_maps");
2680    }
2681
2682    std::string getLibraryCallName() {
2683      return "";
2684    }
2685
2686    mlir::MutableOperandRange getDpsInitsMutable() {
2687      return getOutputsMutable();
2688    }
2689  }];
2690}
2691
2692//===----------------------------------------------------------------------===//
2693// Test Ops with Default-Valued String Attributes
2694//===----------------------------------------------------------------------===//
2695
2696def TestDefaultStrAttrNoValueOp : TEST_Op<"no_str_value"> {
2697  let arguments = (ins DefaultValuedAttr<StrAttr, "">:$value);
2698  let assemblyFormat = "attr-dict";
2699}
2700
2701def TestDefaultStrAttrHasValueOp : TEST_Op<"has_str_value"> {
2702  let arguments = (ins DefaultValuedStrAttr<StrAttr, "">:$value);
2703  let assemblyFormat = "attr-dict";
2704}
2705
2706def : Pat<(TestDefaultStrAttrNoValueOp $value),
2707          (TestDefaultStrAttrHasValueOp ConstantStrAttr<StrAttr, "foo">)>;
2708
2709//===----------------------------------------------------------------------===//
2710// Test Ops with variadics
2711//===----------------------------------------------------------------------===//
2712
2713def TestVariadicRewriteSrcOp : TEST_Op<"variadic_rewrite_src_op", [AttrSizedOperandSegments]> {
2714  let arguments = (ins
2715    Variadic<AnyType>:$arg,
2716    AnyType:$brg,
2717    Variadic<AnyType>:$crg
2718  );
2719}
2720
2721def TestVariadicRewriteDstOp : TEST_Op<"variadic_rewrite_dst_op", [AttrSizedOperandSegments]> {
2722  let arguments = (ins
2723    AnyType:$brg,
2724    Variadic<AnyType>:$crg,
2725    Variadic<AnyType>:$arg
2726  );
2727}
2728
2729def : Pat<(TestVariadicRewriteSrcOp $arg, $brg, $crg),
2730          (TestVariadicRewriteDstOp $brg, $crg, $arg)>;
2731
2732//===----------------------------------------------------------------------===//
2733// Test Ops with Default-Valued Attributes and Differing Print Settings
2734//===----------------------------------------------------------------------===//
2735
2736def TestDefaultAttrPrintOp : TEST_Op<"default_value_print"> {
2737  let arguments = (ins DefaultValuedAttr<I32Attr, "0">:$value_with_default,
2738                   I32:$operand);
2739  let assemblyFormat = "attr-dict $operand";
2740}
2741
2742//===----------------------------------------------------------------------===//
2743// Test Ops with effects
2744//===----------------------------------------------------------------------===//
2745
2746def TestResource : Resource<"TestResource">;
2747
2748def TestEffectsOpA : TEST_Op<"op_with_effects_a"> {
2749  let arguments = (ins
2750    Arg<Variadic<AnyMemRef>, "", [MemRead]>,
2751    Arg<FlatSymbolRefAttr, "", [MemRead]>:$first,
2752    Arg<SymbolRefAttr, "", [MemWrite]>:$second,
2753    Arg<OptionalAttr<SymbolRefAttr>, "", [MemRead]>:$optional_symbol
2754  );
2755
2756  let results = (outs Res<AnyMemRef, "", [MemAlloc<TestResource, 0>]>);
2757}
2758
2759def TestEffectsOpB : TEST_Op<"op_with_effects_b",
2760    [MemoryEffects<[MemWrite<TestResource, 0>]>]>;
2761
2762def TestEffectsRead : TEST_Op<"op_with_memread",
2763    [MemoryEffects<[MemRead]>]> {
2764  let results = (outs AnyInteger);
2765}
2766
2767def TestEffectsWrite : TEST_Op<"op_with_memwrite",
2768    [MemoryEffects<[MemWrite]>]>;
2769
2770def TestEffectsResult : TEST_Op<"test_effects_result"> {
2771  let results = (outs Res<I32, "", [MemAlloc, MemWrite]>);
2772}
2773
2774//===----------------------------------------------------------------------===//
2775// Test Ops with verifiers
2776//===----------------------------------------------------------------------===//
2777
2778def TestVerifiersOp : TEST_Op<"verifiers",
2779                              [SingleBlock, NoTerminator, IsolatedFromAbove]> {
2780  let arguments = (ins I32:$input);
2781  let regions = (region SizedRegion<1>:$region);
2782  let hasVerifier = 1;
2783  let hasRegionVerifier = 1;
2784}
2785
2786//===----------------------------------------------------------------------===//
2787// Test Loop Op with a graph region
2788//===----------------------------------------------------------------------===//
2789
2790// Test loop op with a graph region.
2791def TestGraphLoopOp : TEST_Op<"graph_loop",
2792                         [LoopLikeOpInterface, NoMemoryEffect,
2793                          RecursivelySpeculatable, SingleBlock,
2794                          RegionKindInterface, HasOnlyGraphRegion]> {
2795  let arguments = (ins Variadic<AnyType>:$args);
2796  let results = (outs Variadic<AnyType>:$rets);
2797  let regions = (region SizedRegion<1>:$body);
2798
2799  let assemblyFormat = [{
2800    $args $body attr-dict `:` functional-type(operands, results)
2801  }];
2802
2803  let extraClassDeclaration = [{
2804    llvm::SmallVector<mlir::Region *> getLoopRegions() { return {&getBody()}; }
2805  }];
2806}
2807
2808//===----------------------------------------------------------------------===//
2809// Test InferIntRangeInterface
2810//===----------------------------------------------------------------------===//
2811def InferIntRangeType : AnyTypeOf<[AnyInteger, Index, VectorOfNonZeroRankOf<[AnyInteger, Index]>]>;
2812
2813def TestWithBoundsOp : TEST_Op<"with_bounds",
2814                          [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,
2815                           NoMemoryEffect]> {
2816  let description = [{
2817    Creates a value with specified [min, max] range for integer range analysis.
2818
2819    Example:
2820
2821    ```mlir
2822    %0 = test.with_bounds { umin = 4 : index, umax = 5 : index, smin = 4 : index, smax = 5 : index } : index
2823    ```
2824  }];
2825
2826  let arguments = (ins APIntAttr:$umin,
2827                       APIntAttr:$umax,
2828                       APIntAttr:$smin,
2829                       APIntAttr:$smax);
2830  let results = (outs InferIntRangeType:$fakeVal);
2831
2832  let assemblyFormat = "attr-dict `:` type($fakeVal)";
2833}
2834
2835def TestWithBoundsRegionOp : TEST_Op<"with_bounds_region",
2836                          [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,
2837                           SingleBlock, NoTerminator]> {
2838  let arguments = (ins APIntAttr:$umin,
2839                       APIntAttr:$umax,
2840                       APIntAttr:$smin,
2841                       APIntAttr:$smax);
2842  // The region has one argument of any integer type
2843  let regions = (region SizedRegion<1>:$region);
2844  let hasCustomAssemblyFormat = 1;
2845}
2846
2847def TestIncrementOp : TEST_Op<"increment",
2848                         [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,
2849                         NoMemoryEffect, AllTypesMatch<["value", "result"]>]> {
2850  let arguments = (ins InferIntRangeType:$value);
2851  let results = (outs InferIntRangeType:$result);
2852
2853  let assemblyFormat = "attr-dict $value `:` type($result)";
2854}
2855
2856def TestReflectBoundsOp : TEST_Op<"reflect_bounds",
2857                         [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>,
2858                          AllTypesMatch<["value", "result"]>]> {
2859  let description = [{
2860    Integer range analysis will update this op to reflect inferred integer range
2861    of the input, so it can be checked with FileCheck
2862
2863    Example:
2864
2865    ```mlir
2866    CHECK: test.reflect_bounds {smax = 7 : index, smin = 0 : index, umax = 7 : index, umin = 0 : index}
2867    %1 = test.reflect_bounds %0 : index
2868    ```
2869  }];
2870
2871  let arguments = (ins InferIntRangeType:$value,
2872                       OptionalAttr<APIntAttr>:$umin,
2873                       OptionalAttr<APIntAttr>:$umax,
2874                       OptionalAttr<APIntAttr>:$smin,
2875                       OptionalAttr<APIntAttr>:$smax);
2876  let results = (outs InferIntRangeType:$result);
2877
2878  let assemblyFormat = "attr-dict $value `:` type($result)";
2879}
2880
2881//===----------------------------------------------------------------------===//
2882// Test ConditionallySpeculatable
2883//===----------------------------------------------------------------------===//
2884
2885def ConditionallySpeculatableOp : TEST_Op<"conditionally_speculatable_op",
2886    [ConditionallySpeculatable, NoMemoryEffect]> {
2887  let description = [{
2888    Op used to test conditional speculation.  This op can be speculatively
2889    executed if the input to it is an `arith.constant`.
2890  }];
2891
2892  let arguments = (ins I32:$input);
2893  let results = (outs I32:$result);
2894
2895  let extraClassDeclaration = [{
2896    ::mlir::Speculation::Speculatability getSpeculatability();
2897  }];
2898
2899  let extraClassDefinition = [{
2900    ::mlir::Speculation::Speculatability
2901    ConditionallySpeculatableOp::getSpeculatability() {
2902      Operation* definingOp = getInput().getDefiningOp();
2903      return definingOp && isa<::mlir::arith::ConstantOp>(definingOp) ?
2904          ::mlir::Speculation::Speculatable : ::mlir::Speculation::NotSpeculatable;
2905    }
2906  }];
2907}
2908
2909def PureOp : TEST_Op<"always_speculatable_op", [Pure]> {
2910  let description = [{
2911    Op used to test conditional speculation.  This op can always be
2912    speculatively executed.
2913  }];
2914  let results = (outs I32:$result);
2915}
2916
2917def NeverSpeculatableOp : TEST_Op<"never_speculatable_op", [ConditionallySpeculatable]> {
2918  let description = [{
2919    Op used to test conditional speculation.  This op can never be
2920    speculatively executed.
2921  }];
2922  let results = (outs I32:$result);
2923
2924  let extraClassDeclaration = [{
2925    ::mlir::Speculation::Speculatability getSpeculatability() {
2926      return ::mlir::Speculation::NotSpeculatable;
2927    }
2928  }];
2929}
2930
2931def RecursivelySpeculatableOp : TEST_Op<"recursively_speculatable_op", [
2932    RecursivelySpeculatable, RecursiveMemoryEffects]> {
2933  let description = [{
2934    Op used to test conditional speculation.  This op can be speculatively
2935    executed only if all the ops in the attached region can be.
2936  }];
2937  let results = (outs I32:$result);
2938  let regions = (region SizedRegion<1>:$body);
2939}
2940
2941//===---------------------------------------------------------------------===//
2942// Test CSE
2943//===---------------------------------------------------------------------===//
2944
2945def TestCSEOfSingleBlockOp : TEST_Op<"cse_of_single_block_op",
2946    [SingleBlockImplicitTerminator<"RegionYieldOp">, Pure]> {
2947  let arguments = (ins Variadic<AnyType>:$inputs);
2948  let results = (outs Variadic<AnyType>:$outputs);
2949  let regions = (region SizedRegion<1>:$region);
2950  let assemblyFormat = [{
2951    attr-dict `inputs` `(` $inputs `)`
2952    $region `:` type($inputs)  `->` type($outputs)
2953  }];
2954}
2955
2956//===----------------------------------------------------------------------===//
2957// Test Ops to upgrade base on the dialect versions
2958//===----------------------------------------------------------------------===//
2959
2960def TestVersionedOpA : TEST_Op<"versionedA"> {
2961  // A previous version of the dialect (let's say 1.*) supported an attribute
2962  // named "dimensions":
2963  // let arguments = (ins
2964  //   AnyI64Attr:$dimensions
2965  // );
2966
2967  // In the current version (2.0) "dimensions" was renamed to "dims", and a new
2968  // boolean attribute "modifier" was added. The previous version of the op
2969  // corresponds to "modifier=false". We support loading old IR through
2970  // upgrading, see `upgradeFromVersion()` in `TestBytecodeDialectInterface`.
2971  let arguments = (ins
2972   AnyI64Attr:$dims,
2973   BoolAttr:$modifier
2974  );
2975
2976  // Since we use properties to store attributes, we need a custom encoding
2977  // reader/writer to handle versioning.
2978  let useCustomPropertiesEncoding = 1;
2979}
2980
2981def TestVersionedOpB : TEST_Op<"versionedB"> {
2982  // A previous version of the dialect (let's say 1.*) we encoded TestAttrParams
2983  // with a custom encoding:
2984  //
2985  //    #test.attr_params<X, Y> -> { varInt: Y, varInt: X }
2986  //
2987  // In the current version (2.0) the encoding changed and the two parameters of
2988  // the attribute are swapped:
2989  //
2990  //    #test.attr_params<X, Y> -> { varInt: X, varInt: Y }
2991  //
2992  // We support loading old IR through a custom readAttribute method, see
2993  // `readAttribute()` in `TestBytecodeDialectInterface`
2994  let arguments = (ins
2995    TestAttrParams:$attribute
2996  );
2997}
2998
2999def TestVersionedOpC : TEST_Op<"versionedC"> {
3000  let arguments = (ins AnyAttrOf<[TestAttrParams,
3001                                  I32ElementsAttr]>:$attribute
3002  );
3003}
3004
3005//===----------------------------------------------------------------------===//
3006// Test Properties
3007//===----------------------------------------------------------------------===//
3008
3009
3010// Op with a properties struct defined inline.
3011def TestOpWithProperties : TEST_Op<"with_properties"> {
3012  let assemblyFormat = [{
3013    `a` `=` $a `,`
3014    `b` `=` $b `,`
3015    `c` `=` $c `,`
3016    `flag` `=` $flag `,`
3017    `array` `=` $array attr-dict}];
3018  let arguments = (ins
3019    I64Prop:$a,
3020    StrAttr:$b, // Attributes can directly be used here.
3021    StringProp:$c,
3022    BoolProp:$flag,
3023    IntArrayProp<I64Prop>:$array // example of an array
3024  );
3025}
3026
3027def TestOpWithPropertiesAndAttr
3028  : TEST_Op<"with_properties_and_attr"> {
3029  let assemblyFormat = "$lhs prop-dict attr-dict";
3030
3031  let arguments = (ins I32Attr:$lhs, IntProp<"int64_t">:$rhs);
3032}
3033
3034def TestOpWithPropertiesAndInferredType
3035  : TEST_Op<"with_properties_and_inferred_type", [
3036    DeclareOpInterfaceMethods<InferTypeOpInterface>
3037  ]> {
3038  let assemblyFormat = "$lhs prop-dict attr-dict";
3039
3040  let arguments = (ins I32Attr:$lhs, IntProp<"int64_t">:$rhs);
3041  let results = (outs AnyType:$result);
3042}
3043
3044// Demonstrate how to wrap an existing C++ class named MyPropStruct.
3045def MyStructProperty : Property<"MyPropStruct"> {
3046  let convertToAttribute = "return $_storage.asAttribute($_ctxt);";
3047  let convertFromAttribute = "return MyPropStruct::setFromAttr($_storage, $_attr, $_diag);";
3048  let hashProperty = "$_storage.hash();";
3049}
3050
3051def TestOpWithWrappedProperties : TEST_Op<"with_wrapped_properties"> {
3052  let assemblyFormat = "prop-dict attr-dict";
3053  let arguments = (ins
3054    MyStructProperty:$prop
3055  );
3056}
3057
3058def TestOpWithEmptyProperties : TEST_Op<"empty_properties"> {
3059  let assemblyFormat = "prop-dict attr-dict";
3060  let arguments = (ins);
3061}
3062
3063def TestOpUsingPropertyInCustom : TEST_Op<"using_property_in_custom"> {
3064  let assemblyFormat = "custom<UsingPropertyInCustom>($prop) attr-dict";
3065  let arguments = (ins IntArrayProp<I64Prop>:$prop);
3066}
3067
3068def TestOpUsingPropertyInCustomAndOther
3069  : TEST_Op<"using_property_in_custom_and_other"> {
3070  let assemblyFormat = "custom<UsingPropertyInCustom>($prop) prop-dict attr-dict";
3071  let arguments = (ins
3072    IntArrayProp<I64Prop>:$prop,
3073    I64Prop:$other
3074  );
3075}
3076
3077def TestOpWithVariadicSegmentProperties : TEST_Op<"variadic_segment_prop",
3078    [AttrSizedOperandSegments, AttrSizedResultSegments]> {
3079  let arguments = (ins Variadic<I64>:$a1, Variadic<I64>:$a2);
3080  let results = (outs Variadic<I64>:$b1, Variadic<I64>:$b2);
3081  let assemblyFormat = [{
3082    $a1 `:` $a2 `:` type($b1) `:` type($b2) prop-dict attr-dict `end`
3083  }];
3084}
3085
3086def TestOpUsingPropertyRefInCustom : TEST_Op<"using_property_ref_in_custom"> {
3087  let assemblyFormat = "custom<IntProperty>($first) `+` custom<SumProperty>($second, ref($first)) attr-dict";
3088  let arguments = (ins IntProp<"int64_t">:$first, IntProp<"int64_t">:$second);
3089}
3090
3091def IntPropertyWithWorseBytecode : Property<"int64_t"> {
3092  let writeToMlirBytecode = writeMlirBytecodeWithConvertToAttribute;
3093
3094  let readFromMlirBytecode = readMlirBytecodeUsingConvertFromAttribute;
3095}
3096
3097def TestOpUsingIntPropertyWithWorseBytecode
3098    : TEST_Op<"using_int_property_with_worse_bytecode"> {
3099  let arguments = (ins IntPropertyWithWorseBytecode:$value);
3100}
3101
3102// Op with a properties struct defined out-of-line. The struct has custom
3103// printer/parser.
3104
3105def PropertiesWithCustomPrint : Property<"PropertiesWithCustomPrint"> {
3106  let convertToAttribute = [{
3107    return getPropertiesAsAttribute($_ctxt, $_storage);
3108  }];
3109  let convertFromAttribute = [{
3110    return setPropertiesFromAttribute($_storage, $_attr, $_diag);
3111  }];
3112  let hashProperty = [{
3113    computeHash($_storage);
3114  }];
3115}
3116
3117def TestOpWithNiceProperties : TEST_Op<"with_nice_properties"> {
3118  let assemblyFormat = "prop-dict attr-dict";
3119  let arguments = (ins
3120     PropertiesWithCustomPrint:$prop
3121  );
3122  let extraClassDeclaration = [{
3123    void printProperties(::mlir::MLIRContext *ctx, ::mlir::OpAsmPrinter &p,
3124                         const Properties &prop,
3125                         ::mlir::ArrayRef<::llvm::StringRef> elidedProps);
3126    static ::mlir::ParseResult  parseProperties(::mlir::OpAsmParser &parser,
3127                                     ::mlir::OperationState &result);
3128    static ::llvm::LogicalResult readFromMlirBytecode(
3129        ::mlir::DialectBytecodeReader &,
3130        test::PropertiesWithCustomPrint &prop);
3131    static void writeToMlirBytecode(
3132        ::mlir::DialectBytecodeWriter &,
3133        const test::PropertiesWithCustomPrint &prop);
3134  }];
3135  let extraClassDefinition = [{
3136    ::llvm::LogicalResult TestOpWithNiceProperties::readFromMlirBytecode(
3137        ::mlir::DialectBytecodeReader &reader,
3138        test::PropertiesWithCustomPrint &prop) {
3139      StringRef label;
3140      uint64_t value;
3141      if (failed(reader.readString(label)) || failed(reader.readVarInt(value)))
3142        return failure();
3143      prop.label = std::make_shared<std::string>(label.str());
3144      prop.value = value;
3145      return success();
3146    }
3147    void TestOpWithNiceProperties::writeToMlirBytecode(
3148        ::mlir::DialectBytecodeWriter &writer,
3149        const test::PropertiesWithCustomPrint &prop) {
3150      writer.writeOwnedString(*prop.label);
3151      writer.writeVarInt(prop.value);
3152    }
3153    void TestOpWithNiceProperties::printProperties(::mlir::MLIRContext *ctx,
3154            ::mlir::OpAsmPrinter &p, const Properties &prop,
3155            ::mlir::ArrayRef<::llvm::StringRef> elidedProps) {
3156      customPrintProperties(p, prop.prop);
3157    }
3158    ::mlir::ParseResult TestOpWithNiceProperties::parseProperties(
3159        ::mlir::OpAsmParser &parser,
3160        ::mlir::OperationState &result) {
3161      Properties &prop = result.getOrAddProperties<Properties>();
3162      if (customParseProperties(parser, prop.prop))
3163        return failure();
3164      return success();
3165    }
3166  }];
3167}
3168
3169def VersionedProperties : Property<"VersionedProperties"> {
3170  let convertToAttribute = [{
3171    return getPropertiesAsAttribute($_ctxt, $_storage);
3172  }];
3173  let convertFromAttribute = [{
3174    return setPropertiesFromAttribute($_storage, $_attr, $_diag);
3175  }];
3176  let hashProperty = [{
3177    computeHash($_storage);
3178  }];
3179}
3180
3181def TestOpWithVersionedProperties : TEST_Op<"with_versioned_properties"> {
3182  let assemblyFormat = "prop-dict attr-dict";
3183  let arguments = (ins
3184     VersionedProperties:$prop
3185  );
3186  let extraClassDeclaration = [{
3187    void printProperties(::mlir::MLIRContext *ctx, ::mlir::OpAsmPrinter &p,
3188                         const Properties &prop,
3189                         ::mlir::ArrayRef<::llvm::StringRef> elidedProps);
3190    static ::mlir::ParseResult  parseProperties(::mlir::OpAsmParser &parser,
3191                                     ::mlir::OperationState &result);
3192    static ::llvm::LogicalResult readFromMlirBytecode(
3193        ::mlir::DialectBytecodeReader &,
3194        test::VersionedProperties &prop);
3195    static void writeToMlirBytecode(
3196        ::mlir::DialectBytecodeWriter &,
3197        const test::VersionedProperties &prop);
3198  }];
3199  let extraClassDefinition = [{
3200    void TestOpWithVersionedProperties::printProperties(::mlir::MLIRContext *ctx,
3201            ::mlir::OpAsmPrinter &p, const Properties &prop,
3202            ::mlir::ArrayRef<::llvm::StringRef> elidedProps) {
3203      customPrintProperties(p, prop.prop);
3204    }
3205    ::mlir::ParseResult TestOpWithVersionedProperties::parseProperties(
3206        ::mlir::OpAsmParser &parser,
3207        ::mlir::OperationState &result) {
3208      Properties &prop = result.getOrAddProperties<Properties>();
3209      if (customParseProperties(parser, prop.prop))
3210        return failure();
3211      return success();
3212    }
3213  }];
3214}
3215
3216def TestOpWithDefaultValuedProperties : TEST_Op<"with_default_valued_properties"> {
3217  let assemblyFormat = [{
3218    ($a^) : (`na`)?
3219    ($b^)?
3220    ($c^)?
3221    ($unit^)?
3222    attr-dict
3223  }];
3224  let arguments = (ins DefaultValuedAttr<I32Attr, "0">:$a,
3225    DefaultValuedProp<StringProp, "\"\"">:$b,
3226    DefaultValuedProp<IntProp<"int32_t">, "-1">:$c,
3227    UnitProp:$unit);
3228}
3229
3230def TestOpWithOptionalProperties : TEST_Op<"with_optional_properties"> {
3231  let assemblyFormat = [{
3232    (`anAttr` `=` $anAttr^)?
3233    (`simple` `=` $simple^)?
3234    (`nonTrivialStorage` `=` $nonTrivialStorage^)?
3235    (`hasDefault` `=` $hasDefault^)?
3236    (`nested` `=` $nested^)?
3237    (`longSyntax` `=` $longSyntax^)?
3238    (`hasUnit` $hasUnit^)?
3239    (`maybeUnit` `=` $maybeUnit^)?
3240    attr-dict
3241  }];
3242  let arguments = (ins
3243    OptionalAttr<I32Attr>:$anAttr,
3244    OptionalProp<I64Prop>:$simple,
3245    OptionalProp<StringProp>:$nonTrivialStorage,
3246    // Confirm that properties with default values now default to nullopt and have
3247    // the long syntax.
3248    OptionalProp<DefaultValuedProp<I64Prop, "0">>:$hasDefault,
3249    OptionalProp<OptionalProp<I64Prop>>:$nested,
3250    OptionalProp<StringProp, 0>:$longSyntax,
3251    UnitProp:$hasUnit,
3252    OptionalProp<UnitProp>:$maybeUnit);
3253}
3254
3255def TestOpWithArrayProperties : TEST_Op<"with_array_properties"> {
3256  let assemblyFormat = [{
3257    `ints` `=` $ints
3258    `strings` `=` $strings
3259    `nested` `=` $nested
3260    `opt` `=` $opt
3261    `explicitOptions` `=` $explicitOptions
3262    `explicitUnits` `=` $explicitUnits
3263    ($hasDefault^ `thats_has_default`)?
3264    attr-dict
3265  }];
3266  let arguments = (ins
3267    ArrayProp<I64Prop>:$ints,
3268    ArrayProp<StringProp>:$strings,
3269    ArrayProp<ArrayProp<I32Prop>>:$nested,
3270    OptionalProp<ArrayProp<I32Prop>>:$opt,
3271    ArrayProp<OptionalProp<I64Prop>>:$explicitOptions,
3272    ArrayProp<UnitProp>:$explicitUnits,
3273    DefaultValuedProp<ArrayProp<I64Prop>,
3274      "::llvm::ArrayRef<int64_t>{}", "::llvm::SmallVector<int64_t>{}">:$hasDefault
3275  );
3276}
3277
3278def NonNegativeI64Prop : ConfinedProp<I64Prop,
3279  CPred<"$_self >= 0">, "non-negative int64_t">;
3280
3281class NonEmptyArray<Property p> : ConfinedProp
3282    <ArrayProp<p>, Neg<CPred<"$_self.empty()">>,
3283    "non-empty array of " # p.summary>;
3284
3285def OpWithPropertyPredicates : TEST_Op<"op_with_property_predicates"> {
3286  let arguments = (ins
3287    NonNegativeI64Prop:$scalar,
3288    OptionalProp<NonNegativeI64Prop>:$optional,
3289    DefaultValuedProp<NonNegativeI64Prop, "0">:$defaulted,
3290    ConfinedProp<NonNegativeI64Prop,
3291      CPred<"$_self <= 5">, "between 0 and 5">:$more_constrained,
3292    ArrayProp<NonNegativeI64Prop>:$array,
3293    NonEmptyArray<I64Prop>:$non_empty_unconstrained,
3294    NonEmptyArray<NonNegativeI64Prop>:$non_empty_constrained,
3295    // Test applying predicates when the fromStorage() on the optional<> isn't trivial.
3296    OptionalProp<NonEmptyArray<NonNegativeI64Prop>>:$non_empty_optional,
3297    I64Prop:$unconstrained
3298  );
3299  let assemblyFormat = "attr-dict prop-dict";
3300}
3301
3302//===----------------------------------------------------------------------===//
3303// Test Dataflow
3304//===----------------------------------------------------------------------===//
3305
3306def TestCallAndStoreOp : TEST_Op<"call_and_store",
3307    [DeclareOpInterfaceMethods<CallOpInterface>]> {
3308  let arguments = (ins
3309    SymbolRefAttr:$callee,
3310    Arg<AnyMemRef, "", [MemWrite]>:$address,
3311    Variadic<AnyType>:$callee_operands,
3312    BoolAttr:$store_before_call
3313  );
3314  let results = (outs
3315    Variadic<AnyType>:$results
3316  );
3317  let assemblyFormat =
3318    "$callee `(` $callee_operands `)` `,` $address attr-dict "
3319    "`:` functional-type(operands, results)";
3320}
3321
3322def TestCallOnDeviceOp : TEST_Op<"call_on_device",
3323    [DeclareOpInterfaceMethods<CallOpInterface>]> {
3324  let arguments = (ins
3325    SymbolRefAttr:$callee,
3326    Variadic<AnyType>:$forwarded_operands,
3327    AnyType:$non_forwarded_device_operand
3328  );
3329  let results = (outs
3330    Variadic<AnyType>:$results
3331  );
3332  let assemblyFormat =
3333    "$callee `(` $forwarded_operands `)` `,` $non_forwarded_device_operand "
3334    "attr-dict `:` functional-type(operands, results)";
3335}
3336
3337def TestStoreWithARegion : TEST_Op<"store_with_a_region",
3338    [DeclareOpInterfaceMethods<RegionBranchOpInterface>,
3339     SingleBlock]> {
3340  let arguments = (ins
3341    Arg<AnyMemRef, "", [MemWrite]>:$address,
3342    BoolAttr:$store_before_region
3343  );
3344  let regions = (region AnyRegion:$body);
3345  let assemblyFormat =
3346    "$address attr-dict-with-keyword regions `:` type($address)";
3347}
3348
3349def TestStoreWithALoopRegion : TEST_Op<"store_with_a_loop_region",
3350    [DeclareOpInterfaceMethods<RegionBranchOpInterface>,
3351     SingleBlock]> {
3352  let arguments = (ins
3353    Arg<AnyMemRef, "", [MemWrite]>:$address,
3354    BoolAttr:$store_before_region
3355  );
3356  let regions = (region AnyRegion:$body);
3357  let assemblyFormat =
3358    "$address attr-dict-with-keyword regions `:` type($address)";
3359}
3360
3361def TestStoreWithARegionTerminator : TEST_Op<"store_with_a_region_terminator",
3362    [ReturnLike, Terminator, NoMemoryEffect]> {
3363  let assemblyFormat = "attr-dict";
3364}
3365
3366def TestOpOptionallyImplementingInterface
3367    : TEST_Op<"op_optionally_implementing_interface",
3368        [TestOptionallyImplementedOpInterface]> {
3369  let arguments = (ins BoolAttr:$implementsInterface);
3370}
3371
3372//===----------------------------------------------------------------------===//
3373// Test Mem2Reg & SROA
3374//===----------------------------------------------------------------------===//
3375
3376def TestMultiSlotAlloca : TEST_Op<"multi_slot_alloca",
3377    [DeclareOpInterfaceMethods<PromotableAllocationOpInterface>,
3378     DeclareOpInterfaceMethods<DestructurableAllocationOpInterface>]> {
3379  let results = (outs Variadic<MemRefOf<[I32]>>:$results);
3380  let assemblyFormat = "attr-dict `:` functional-type(operands, results)";
3381}
3382
3383#endif // TEST_OPS
3384