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