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