1//===- PDLInterpOps.td - Pattern Interpreter Dialect -------*- 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// This file declares the PDL interpreter dialect ops. 10// 11//===----------------------------------------------------------------------===// 12 13#ifndef MLIR_DIALECT_PDLINTERP_IR_PDLINTERPOPS 14#define MLIR_DIALECT_PDLINTERP_IR_PDLINTERPOPS 15 16include "mlir/Dialect/PDL/IR/PDLTypes.td" 17include "mlir/Interfaces/FunctionInterfaces.td" 18include "mlir/IR/SymbolInterfaces.td" 19include "mlir/Interfaces/SideEffectInterfaces.td" 20 21//===----------------------------------------------------------------------===// 22// PDLInterp Dialect 23//===----------------------------------------------------------------------===// 24 25def PDLInterp_Dialect : Dialect { 26 let summary = "Interpreted pattern execution dialect"; 27 let description = [{ 28 The PDL Interpreter dialect provides a lower level abstraction compared to 29 the PDL dialect, and is targeted towards low level optimization and 30 interpreter code generation. The dialect operations encapsulates 31 low-level pattern match and rewrite "primitives", such as navigating the 32 IR (Operation::getOperand), creating new operations (OpBuilder::create), 33 etc. Many of the operations within this dialect also fuse branching control 34 flow with some form of a predicate comparison operation. This type of fusion 35 reduces the amount of work that an interpreter must do when executing. 36 }]; 37 38 let name = "pdl_interp"; 39 let cppNamespace = "::mlir::pdl_interp"; 40 let dependentDialects = ["pdl::PDLDialect"]; 41 let extraClassDeclaration = [{ 42 /// Returns the name of the function containing the matcher code. This 43 /// function is called by the interpreter when matching an operation. 44 static StringRef getMatcherFunctionName() { return "matcher"; } 45 46 /// Returns the name of the module containing the rewrite functions. These 47 /// functions are invoked by distinct patterns within the matcher function 48 /// to rewrite the IR after a successful match. 49 static StringRef getRewriterModuleName() { return "rewriters"; } 50 }]; 51} 52 53//===----------------------------------------------------------------------===// 54// PDLInterp Operations 55//===----------------------------------------------------------------------===// 56 57// Generic interpreter operation. 58class PDLInterp_Op<string mnemonic, list<Trait> traits = []> : 59 Op<PDLInterp_Dialect, mnemonic, traits>; 60 61//===----------------------------------------------------------------------===// 62// PDLInterp_PredicateOp 63 64// Check operations evaluate a predicate on a positional value and then 65// conditionally branch on the result. 66class PDLInterp_PredicateOp<string mnemonic, list<Trait> traits = []> : 67 PDLInterp_Op<mnemonic, !listconcat([Terminator], traits)> { 68 let successors = (successor AnySuccessor:$trueDest, AnySuccessor:$falseDest); 69} 70 71//===----------------------------------------------------------------------===// 72// PDLInterp_SwitchOp 73 74// Switch operations evaluate a predicate on a positional value and then 75// conditionally branch on the result. 76class PDLInterp_SwitchOp<string mnemonic, list<Trait> traits = []> : 77 PDLInterp_Op<mnemonic, !listconcat([Terminator], traits)> { 78 let successors = (successor AnySuccessor:$defaultDest, 79 VariadicSuccessor<AnySuccessor>:$cases); 80} 81 82//===----------------------------------------------------------------------===// 83// pdl_interp::ApplyConstraintOp 84//===----------------------------------------------------------------------===// 85 86def PDLInterp_ApplyConstraintOp : PDLInterp_PredicateOp<"apply_constraint"> { 87 let summary = "Apply a constraint to a set of positional values"; 88 let description = [{ 89 `pdl_interp.apply_constraint` operations apply a generic constraint, that 90 has been registered with the interpreter, with a given set of positional 91 values. 92 The constraint function may return any number of results. 93 On success, this operation branches to the true destination, 94 otherwise the false destination is taken. This behavior can be reversed 95 by setting the attribute `isNegated` to true. 96 97 Example: 98 99 ```mlir 100 // Apply `myConstraint` to the entities defined by `input`, `attr`, and 101 // `op`. 102 pdl_interp.apply_constraint "myConstraint"(%input, %attr, %op : !pdl.value, !pdl.attribute, !pdl.operation) -> ^matchDest, ^failureDest 103 ``` 104 }]; 105 106 let arguments = (ins StrAttr:$name, 107 Variadic<PDL_AnyType>:$args, 108 DefaultValuedAttr<BoolAttr, "false">:$isNegated); 109 let results = (outs Variadic<PDL_AnyType>:$results); 110 let assemblyFormat = [{ 111 $name `(` $args `:` type($args) `)` (`:` type($results)^)? attr-dict 112 `->` successors 113 }]; 114} 115 116//===----------------------------------------------------------------------===// 117// pdl_interp::ApplyRewriteOp 118//===----------------------------------------------------------------------===// 119 120def PDLInterp_ApplyRewriteOp : PDLInterp_Op<"apply_rewrite"> { 121 let summary = "Invoke and apply an externally registered rewrite method"; 122 let description = [{ 123 `pdl_interp.apply_rewrite` operations invoke an external rewriter that has 124 been registered with the interpreter to perform the rewrite after a 125 successful match. The rewrite is passed a set of positional arguments. The 126 rewrite function may return any number of results. 127 128 Example: 129 130 ```mlir 131 // Rewriter operating solely on the root operation. 132 pdl_interp.apply_rewrite "rewriter"(%root : !pdl.operation) 133 134 // Rewriter operating solely on the root operation and return an attribute. 135 %attr = pdl_interp.apply_rewrite "rewriter"(%root : !pdl.operation) : !pdl.attribute 136 137 // Rewriter operating on the root operation along with additional arguments 138 // from the matcher. 139 pdl_interp.apply_rewrite "rewriter"(%root : !pdl.operation, %value : !pdl.value) 140 ``` 141 }]; 142 let arguments = (ins StrAttr:$name, Variadic<PDL_AnyType>:$args); 143 let results = (outs Variadic<PDL_AnyType>:$results); 144 let assemblyFormat = [{ 145 $name (`(` $args^ `:` type($args) `)`)? (`:` type($results)^)? attr-dict 146 }]; 147} 148 149//===----------------------------------------------------------------------===// 150// pdl_interp::AreEqualOp 151//===----------------------------------------------------------------------===// 152 153def PDLInterp_AreEqualOp 154 : PDLInterp_PredicateOp<"are_equal", [Pure, SameTypeOperands]> { 155 let summary = "Check if two positional values or ranges are equivalent"; 156 let description = [{ 157 `pdl_interp.are_equal` operations compare two positional values for 158 equality. On success, this operation branches to the true destination, 159 otherwise the false destination is taken. 160 161 Example: 162 163 ```mlir 164 pdl_interp.are_equal %result1, %result2 : !pdl.value -> ^matchDest, ^failureDest 165 ``` 166 }]; 167 168 let arguments = (ins PDL_AnyType:$lhs, PDL_AnyType:$rhs); 169 let assemblyFormat = "operands `:` type($lhs) attr-dict `->` successors"; 170} 171 172//===----------------------------------------------------------------------===// 173// pdl_interp::BranchOp 174//===----------------------------------------------------------------------===// 175 176def PDLInterp_BranchOp : PDLInterp_Op<"branch", [Pure, Terminator]> { 177 let summary = "General branch operation"; 178 let description = [{ 179 `pdl_interp.branch` operations expose general branch functionality to the 180 interpreter, and are generally used to branch from one pattern match 181 sequence to another. 182 183 Example: 184 185 ```mlir 186 pdl_interp.branch ^dest 187 ``` 188 }]; 189 190 let successors = (successor AnySuccessor:$dest); 191 let assemblyFormat = "$dest attr-dict"; 192} 193 194//===----------------------------------------------------------------------===// 195// pdl_interp::CheckAttributeOp 196//===----------------------------------------------------------------------===// 197 198def PDLInterp_CheckAttributeOp 199 : PDLInterp_PredicateOp<"check_attribute", [Pure]> { 200 let summary = "Check the value of an `Attribute`"; 201 let description = [{ 202 `pdl_interp.check_attribute` operations compare the value of a given 203 attribute with a constant value. On success, this operation branches to the 204 true destination, otherwise the false destination is taken. 205 206 Example: 207 208 ```mlir 209 pdl_interp.check_attribute %attr is 10 -> ^matchDest, ^failureDest 210 ``` 211 }]; 212 213 let arguments = (ins PDL_Attribute:$attribute, AnyAttr:$constantValue); 214 let assemblyFormat = [{ 215 $attribute `is` $constantValue attr-dict `->` successors 216 }]; 217} 218 219//===----------------------------------------------------------------------===// 220// pdl_interp::CheckOperandCountOp 221//===----------------------------------------------------------------------===// 222 223def PDLInterp_CheckOperandCountOp 224 : PDLInterp_PredicateOp<"check_operand_count", [Pure]> { 225 let summary = "Check the number of operands of an `Operation`"; 226 let description = [{ 227 `pdl_interp.check_operand_count` operations compare the number of operands 228 of a given operation value with a constant. The comparison is either exact 229 or at_least, with the latter used to compare against a minimum number of 230 expected operands. On success, this operation branches to the true 231 destination, otherwise the false destination is taken. 232 233 Example: 234 235 ```mlir 236 // Check for exact equality. 237 pdl_interp.check_operand_count of %op is 2 -> ^matchDest, ^failureDest 238 239 // Check for at least N operands. 240 pdl_interp.check_operand_count of %op is at_least 2 -> ^matchDest, ^failureDest 241 ``` 242 }]; 243 244 let arguments = (ins PDL_Operation:$inputOp, 245 ConfinedAttr<I32Attr, [IntNonNegative]>:$count, 246 UnitAttr:$compareAtLeast); 247 let assemblyFormat = [{ 248 `of` $inputOp `is` (`at_least` $compareAtLeast^)? $count attr-dict 249 `->` successors 250 }]; 251} 252 253//===----------------------------------------------------------------------===// 254// pdl_interp::CheckOperationNameOp 255//===----------------------------------------------------------------------===// 256 257def PDLInterp_CheckOperationNameOp 258 : PDLInterp_PredicateOp<"check_operation_name", [Pure]> { 259 let summary = "Check the OperationName of an `Operation`"; 260 let description = [{ 261 `pdl_interp.check_operation_name` operations compare the name of a given 262 operation with a known name. On success, this operation branches to the true 263 destination, otherwise the false destination is taken. 264 265 Example: 266 267 ```mlir 268 pdl_interp.check_operation_name of %op is "foo.op" -> ^matchDest, ^failureDest 269 ``` 270 }]; 271 272 let arguments = (ins PDL_Operation:$inputOp, StrAttr:$name); 273 let assemblyFormat = "`of` $inputOp `is` $name attr-dict `->` successors"; 274} 275 276//===----------------------------------------------------------------------===// 277// pdl_interp::CheckResultCountOp 278//===----------------------------------------------------------------------===// 279 280def PDLInterp_CheckResultCountOp 281 : PDLInterp_PredicateOp<"check_result_count", [Pure]> { 282 let summary = "Check the number of results of an `Operation`"; 283 let description = [{ 284 `pdl_interp.check_result_count` operations compare the number of results 285 of a given operation value with a constant. The comparison is either exact 286 or at_least, with the latter used to compare against a minimum number of 287 expected results. On success, this operation branches to the true 288 destination, otherwise the false destination is taken. 289 290 Example: 291 292 ```mlir 293 // Check for exact equality. 294 pdl_interp.check_result_count of %op is 2 -> ^matchDest, ^failureDest 295 296 // Check for at least N results. 297 pdl_interp.check_result_count of %op is at_least 2 -> ^matchDest, ^failureDest 298 ``` 299 }]; 300 301 let arguments = (ins PDL_Operation:$inputOp, 302 ConfinedAttr<I32Attr, [IntNonNegative]>:$count, 303 UnitAttr:$compareAtLeast); 304 let assemblyFormat = [{ 305 `of` $inputOp `is` (`at_least` $compareAtLeast^)? $count attr-dict 306 `->` successors 307 }]; 308} 309 310//===----------------------------------------------------------------------===// 311// pdl_interp::CheckTypeOp 312//===----------------------------------------------------------------------===// 313 314def PDLInterp_CheckTypeOp 315 : PDLInterp_PredicateOp<"check_type", [Pure]> { 316 let summary = "Compare a type to a known value"; 317 let description = [{ 318 `pdl_interp.check_type` operations compare a type with a statically known 319 type. On success, this operation branches to the true destination, otherwise 320 the false destination is taken. 321 322 Example: 323 324 ```mlir 325 pdl_interp.check_type %type is i32 -> ^matchDest, ^failureDest 326 ``` 327 }]; 328 329 let arguments = (ins PDL_Type:$value, TypeAttr:$type); 330 let assemblyFormat = "$value `is` $type attr-dict `->` successors"; 331} 332 333//===----------------------------------------------------------------------===// 334// pdl_interp::CheckTypesOp 335//===----------------------------------------------------------------------===// 336 337def PDLInterp_CheckTypesOp 338 : PDLInterp_PredicateOp<"check_types", [Pure]> { 339 let summary = "Compare a range of types to a range of known values"; 340 let description = [{ 341 `pdl_interp.check_types` operations compare a range of types with a 342 statically known range of types. On success, this operation branches 343 to the true destination, otherwise the false destination is taken. 344 345 Example: 346 347 ```mlir 348 pdl_interp.check_types %type are [i32, i64] -> ^matchDest, ^failureDest 349 ``` 350 }]; 351 352 let arguments = (ins PDL_RangeOf<PDL_Type>:$value, 353 TypeArrayAttr:$types); 354 let assemblyFormat = "$value `are` $types attr-dict `->` successors"; 355} 356 357//===----------------------------------------------------------------------===// 358// pdl_interp::ContinueOp 359//===----------------------------------------------------------------------===// 360 361def PDLInterp_ContinueOp 362 : PDLInterp_Op<"continue", [Pure, HasParent<"ForEachOp">, 363 Terminator]> { 364 let summary = "Breaks the current iteration"; 365 let description = [{ 366 `pdl_interp.continue` operation breaks the current iteration within the 367 `pdl_interp.foreach` region and continues with the next iteration from 368 the beginning of the region. 369 370 Example: 371 372 ```mlir 373 pdl_interp.continue 374 ``` 375 }]; 376 377 let assemblyFormat = "attr-dict"; 378} 379 380//===----------------------------------------------------------------------===// 381// pdl_interp::CreateAttributeOp 382//===----------------------------------------------------------------------===// 383 384def PDLInterp_CreateAttributeOp 385 : PDLInterp_Op<"create_attribute", [Pure]> { 386 let summary = "Create an interpreter handle to a constant `Attribute`"; 387 let description = [{ 388 `pdl_interp.create_attribute` operations generate a handle within the 389 interpreter for a specific constant attribute value. 390 391 Example: 392 393 ```mlir 394 %attr = pdl_interp.create_attribute 10 : i64 395 ``` 396 }]; 397 398 let arguments = (ins AnyAttr:$value); 399 let results = (outs PDL_Attribute:$attribute); 400 let assemblyFormat = "$value attr-dict-with-keyword"; 401 402 let builders = [ 403 OpBuilder<(ins "Attribute":$value), [{ 404 build($_builder, $_state, $_builder.getType<pdl::AttributeType>(), value); 405 }]>]; 406} 407 408//===----------------------------------------------------------------------===// 409// pdl_interp::CreateOperationOp 410//===----------------------------------------------------------------------===// 411 412def PDLInterp_CreateOperationOp 413 : PDLInterp_Op<"create_operation", [AttrSizedOperandSegments]> { 414 let summary = "Create an instance of a specific `Operation`"; 415 let description = [{ 416 `pdl_interp.create_operation` operations create an `Operation` instance with 417 the specified attributes, operands, and result types. See `pdl.operation` 418 for a more detailed description on the general interpretation of the arguments 419 to this operation. 420 421 Example: 422 423 ```mlir 424 // Create an instance of a `foo.op` operation. 425 %op = pdl_interp.create_operation "foo.op"(%arg0 : !pdl.value) {"attrA" = %attr0} -> (%type : !pdl.type) 426 427 // Create an instance of a `foo.op` operation that has inferred result types 428 // (using the InferTypeOpInterface). 429 %op = pdl_interp.create_operation "foo.op"(%arg0 : !pdl.value) {"attrA" = %attr0} -> <inferred> 430 ``` 431 }]; 432 433 let arguments = (ins StrAttr:$name, 434 Variadic<PDL_InstOrRangeOf<PDL_Value>>:$inputOperands, 435 Variadic<PDL_Attribute>:$inputAttributes, 436 StrArrayAttr:$inputAttributeNames, 437 Variadic<PDL_InstOrRangeOf<PDL_Type>>:$inputResultTypes, 438 UnitAttr:$inferredResultTypes); 439 let results = (outs PDL_Operation:$resultOp); 440 441 let builders = [ 442 OpBuilder<(ins "StringRef":$name, "ValueRange":$types, 443 "bool":$inferredResultTypes, "ValueRange":$operands, 444 "ValueRange":$attributes, "ArrayAttr":$attributeNames), [{ 445 build($_builder, $_state, $_builder.getType<pdl::OperationType>(), name, 446 operands, attributes, attributeNames, types, inferredResultTypes); 447 }]> 448 ]; 449 let assemblyFormat = [{ 450 $name (`(` $inputOperands^ `:` type($inputOperands) `)`)? `` 451 custom<CreateOperationOpAttributes>($inputAttributes, $inputAttributeNames) 452 custom<CreateOperationOpResults>($inputResultTypes, type($inputResultTypes), 453 $inferredResultTypes) 454 attr-dict 455 }]; 456 let hasVerifier = 1; 457} 458 459//===----------------------------------------------------------------------===// 460// pdl_interp::CreateTypeOp 461//===----------------------------------------------------------------------===// 462 463def PDLInterp_CreateTypeOp : PDLInterp_Op<"create_type", [Pure]> { 464 let summary = "Create an interpreter handle to a constant `Type`"; 465 let description = [{ 466 `pdl_interp.create_type` operations generate a handle within the interpreter 467 for a specific constant type value. 468 469 Example: 470 471 ```mlir 472 pdl_interp.create_type i64 473 ``` 474 }]; 475 476 let arguments = (ins TypeAttr:$value); 477 let results = (outs PDL_Type:$result); 478 let assemblyFormat = "$value attr-dict"; 479 480 let builders = [ 481 OpBuilder<(ins "TypeAttr":$type), [{ 482 build($_builder, $_state, $_builder.getType<pdl::TypeType>(), type); 483 }]> 484 ]; 485} 486 487//===----------------------------------------------------------------------===// 488// pdl_interp::CreateTypesOp 489//===----------------------------------------------------------------------===// 490 491def PDLInterp_CreateTypesOp : PDLInterp_Op<"create_types", [Pure]> { 492 let summary = "Create an interpreter handle to a range of constant `Type`s"; 493 let description = [{ 494 `pdl_interp.create_types` operations generate a handle within the 495 interpreter for a specific range of constant type values. 496 497 Example: 498 499 ```mlir 500 pdl_interp.create_types [i64, i64] 501 ``` 502 }]; 503 504 let arguments = (ins TypeArrayAttr:$value); 505 let results = (outs PDL_RangeOf<PDL_Type>:$result); 506 let assemblyFormat = "$value attr-dict"; 507 508 let builders = [ 509 OpBuilder<(ins "ArrayAttr":$type), [{ 510 build($_builder, $_state, 511 pdl::RangeType::get($_builder.getType<pdl::TypeType>()), type); 512 }]> 513 ]; 514} 515 516//===----------------------------------------------------------------------===// 517// pdl_interp::EraseOp 518//===----------------------------------------------------------------------===// 519 520def PDLInterp_EraseOp : PDLInterp_Op<"erase"> { 521 let summary = "Mark an operation as `erased`"; 522 let description = [{ 523 `pdl.erase` operations are used to specify that an operation should be 524 marked as erased. The semantics of this operation correspond with the 525 `eraseOp` method on a `PatternRewriter`. 526 527 Example: 528 529 ```mlir 530 pdl_interp.erase %root 531 ``` 532 }]; 533 534 let arguments = (ins PDL_Operation:$inputOp); 535 let assemblyFormat = "$inputOp attr-dict"; 536} 537 538//===----------------------------------------------------------------------===// 539// pdl_interp::ExtractOp 540//===----------------------------------------------------------------------===// 541 542def PDLInterp_ExtractOp 543 : PDLInterp_Op<"extract", [Pure, 544 TypesMatchWith< 545 "`range` is a PDL range whose element type matches type of `result`", 546 "result", "range", "pdl::RangeType::get($_self)">]> { 547 let summary = "Extract the item at the specified index in a range"; 548 let description = [{ 549 `pdl_interp.extract` operations are used to extract an item from a range 550 at the specified index. If the index is out of range, returns null. 551 552 Example: 553 554 ```mlir 555 // Extract the value at index 1 from a range of values. 556 %ops = pdl_interp.extract 1 of %values : !pdl.value 557 ``` 558 }]; 559 560 let arguments = (ins PDL_RangeOf<PDL_AnyType>:$range, 561 ConfinedAttr<I32Attr, [IntNonNegative]>:$index); 562 let results = (outs PDL_AnyType:$result); 563 let assemblyFormat = "$index `of` $range `:` type($result) attr-dict"; 564 565 let builders = [ 566 OpBuilder<(ins "Value":$range, "unsigned":$index), [{ 567 build($_builder, $_state, 568 ::llvm::cast<pdl::RangeType>(range.getType()).getElementType(), 569 range, index); 570 }]>, 571 ]; 572} 573 574//===----------------------------------------------------------------------===// 575// pdl_interp::FinalizeOp 576//===----------------------------------------------------------------------===// 577 578def PDLInterp_FinalizeOp 579 : PDLInterp_Op<"finalize", [Pure, Terminator]> { 580 let summary = "Finalize a pattern match or rewrite sequence"; 581 let description = [{ 582 `pdl_interp.finalize` is used to denote the termination of a match or 583 rewrite sequence. 584 585 Example: 586 587 ```mlir 588 pdl_interp.finalize 589 ``` 590 }]; 591 let assemblyFormat = "attr-dict"; 592} 593 594//===----------------------------------------------------------------------===// 595// pdl_interp::ForEachOp 596//===----------------------------------------------------------------------===// 597 598def PDLInterp_ForEachOp 599 : PDLInterp_Op<"foreach", [Terminator]> { 600 let summary = "Iterates over a range of values or ranges"; 601 let description = [{ 602 `pdl_interp.foreach` iteratively selects an element from a range of values 603 and executes the region until pdl.continue is reached. 604 605 In the bytecode interpreter, this operation is implemented by looping over 606 the values and, for each selection, running the bytecode until we reach 607 pdl.continue. This may result in multiple matches being reported. Note 608 that the input range is mutated (popped from). 609 610 Example: 611 612 ```mlir 613 pdl_interp.foreach %op : !pdl.operation in %ops { 614 pdl_interp.continue 615 } -> ^next 616 ``` 617 }]; 618 619 let arguments = (ins PDL_RangeOf<PDL_AnyType>:$values); 620 let regions = (region AnyRegion:$region); 621 let successors = (successor AnySuccessor:$successor); 622 623 let builders = [ 624 OpBuilder<(ins "Value":$range, "Block *":$successor, "bool":$initLoop)> 625 ]; 626 627 let extraClassDeclaration = [{ 628 /// Returns the loop variable. 629 BlockArgument getLoopVariable() { return getRegion().getArgument(0); } 630 }]; 631 let hasCustomAssemblyFormat = 1; 632 let hasVerifier = 1; 633} 634 635//===----------------------------------------------------------------------===// 636// pdl_interp::FuncOp 637//===----------------------------------------------------------------------===// 638 639def PDLInterp_FuncOp : PDLInterp_Op<"func", [ 640 FunctionOpInterface, IsolatedFromAbove 641 ]> { 642 let summary = "PDL Interpreter Function Operation"; 643 let description = [{ 644 `pdl_interp.func` operations act as interpreter functions. These are 645 callable SSA-region operations that contain other interpreter operations. 646 Interpreter functions are used for both the matching and the rewriting 647 portion of the interpreter. 648 649 Example: 650 651 ```mlir 652 pdl_interp.func @rewriter(%root: !pdl.operation) { 653 %op = pdl_interp.create_operation "foo.new_operation" 654 pdl_interp.erase %root 655 pdl_interp.finalize 656 } 657 ``` 658 }]; 659 660 let arguments = (ins 661 SymbolNameAttr:$sym_name, 662 TypeAttrOf<FunctionType>:$function_type, 663 OptionalAttr<DictArrayAttr>:$arg_attrs, 664 OptionalAttr<DictArrayAttr>:$res_attrs 665 ); 666 let regions = (region MinSizedRegion<1>:$body); 667 668 // Create the function with the given name and type. This also automatically 669 // inserts the entry block for the function. 670 let builders = [OpBuilder<(ins 671 "StringRef":$name, "FunctionType":$type, 672 CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs) 673 >]; 674 let extraClassDeclaration = [{ 675 //===------------------------------------------------------------------===// 676 // FunctionOpInterface Methods 677 //===------------------------------------------------------------------===// 678 679 /// Returns the argument types of this function. 680 ArrayRef<Type> getArgumentTypes() { return getFunctionType().getInputs(); } 681 682 /// Returns the result types of this function. 683 ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); } 684 685 Region *getCallableRegion() { return &getBody(); } 686 }]; 687 let hasCustomAssemblyFormat = 1; 688 let skipDefaultBuilders = 1; 689} 690 691//===----------------------------------------------------------------------===// 692// pdl_interp::GetAttributeOp 693//===----------------------------------------------------------------------===// 694 695def PDLInterp_GetAttributeOp : PDLInterp_Op<"get_attribute", [Pure]> { 696 let summary = "Get a specified attribute value from an `Operation`"; 697 let description = [{ 698 `pdl_interp.get_attribute` operations try to get a specific attribute from 699 an operation. If the operation does not have that attribute, a null value is 700 returned. 701 702 Example: 703 704 ```mlir 705 %attr = pdl_interp.get_attribute "attr" of %op 706 ``` 707 }]; 708 709 let arguments = (ins PDL_Operation:$inputOp, StrAttr:$name); 710 let results = (outs PDL_Attribute:$attribute); 711 let assemblyFormat = "$name `of` $inputOp attr-dict"; 712} 713 714//===----------------------------------------------------------------------===// 715// pdl_interp::GetAttributeTypeOp 716//===----------------------------------------------------------------------===// 717 718def PDLInterp_GetAttributeTypeOp 719 : PDLInterp_Op<"get_attribute_type", [Pure]> { 720 let summary = "Get the result type of a specified `Attribute`"; 721 let description = [{ 722 `pdl_interp.get_attribute_type` operations get the resulting type of a 723 specific attribute. 724 725 Example: 726 727 ```mlir 728 %type = pdl_interp.get_attribute_type of %attr 729 ``` 730 }]; 731 732 let arguments = (ins PDL_Attribute:$value); 733 let results = (outs PDL_Type:$result); 734 let assemblyFormat = "`of` $value attr-dict"; 735 736 let builders = [ 737 OpBuilder<(ins "Value":$value), [{ 738 build($_builder, $_state, $_builder.getType<pdl::TypeType>(), value); 739 }]> 740 ]; 741} 742 743//===----------------------------------------------------------------------===// 744// pdl_interp::GetDefiningOpOp 745//===----------------------------------------------------------------------===// 746 747def PDLInterp_GetDefiningOpOp 748 : PDLInterp_Op<"get_defining_op", [Pure]> { 749 let summary = "Get the defining operation of a `Value`"; 750 let description = [{ 751 `pdl_interp.get_defining_op` operations try to get the defining operation 752 of a specific value or range of values. In the case of range, the defining 753 op of the first value is returned. If the value is not an operation result 754 or range of operand results, null is returned. 755 756 Example: 757 758 ```mlir 759 %op = pdl_interp.get_defining_op of %value : !pdl.value 760 ``` 761 }]; 762 763 let arguments = (ins PDL_InstOrRangeOf<PDL_Value>:$value); 764 let results = (outs PDL_Operation:$inputOp); 765 let assemblyFormat = "`of` $value `:` type($value) attr-dict"; 766} 767 768//===----------------------------------------------------------------------===// 769// pdl_interp::GetOperandOp 770//===----------------------------------------------------------------------===// 771 772def PDLInterp_GetOperandOp : PDLInterp_Op<"get_operand", [Pure]> { 773 let summary = "Get a specified operand from an `Operation`"; 774 let description = [{ 775 `pdl_interp.get_operand` operations try to get a specific operand from an 776 operation If the operation does not have an operand for the given index, a 777 null value is returned. 778 779 Example: 780 781 ```mlir 782 %operand = pdl_interp.get_operand 1 of %op 783 ``` 784 }]; 785 786 let arguments = (ins PDL_Operation:$inputOp, 787 ConfinedAttr<I32Attr, [IntNonNegative]>:$index); 788 let results = (outs PDL_Value:$value); 789 let assemblyFormat = "$index `of` $inputOp attr-dict"; 790} 791 792//===----------------------------------------------------------------------===// 793// pdl_interp::GetOperandsOp 794//===----------------------------------------------------------------------===// 795 796def PDLInterp_GetOperandsOp : PDLInterp_Op<"get_operands", [Pure]> { 797 let summary = "Get a specified operand group from an `Operation`"; 798 let description = [{ 799 `pdl_interp.get_operands` operations try to get a specific operand 800 group from an operation. If the expected result is a single Value, null is 801 returned if the operand group is not of size 1. If a range is expected, 802 null is returned if the operand group is invalid. If no index is provided, 803 the returned operand group corresponds to all operands of the operation. 804 805 Example: 806 807 ```mlir 808 // Get the first group of operands from an operation, and expect a single 809 // element. 810 %operand = pdl_interp.get_operands 0 of %op : !pdl.value 811 812 // Get the first group of operands from an operation. 813 %operands = pdl_interp.get_operands 0 of %op : !pdl.range<value> 814 815 // Get all of the operands from an operation. 816 %operands = pdl_interp.get_operands of %op : !pdl.range<value> 817 ``` 818 }]; 819 820 let arguments = (ins 821 PDL_Operation:$inputOp, 822 OptionalAttr<ConfinedAttr<I32Attr, [IntNonNegative]>>:$index 823 ); 824 let results = (outs PDL_InstOrRangeOf<PDL_Value>:$value); 825 let assemblyFormat = "($index^)? `of` $inputOp `:` type($value) attr-dict"; 826 let builders = [ 827 OpBuilder<(ins "Type":$resultType, "Value":$inputOp, 828 "std::optional<unsigned>":$index), [{ 829 build($_builder, $_state, resultType, inputOp, 830 index ? $_builder.getI32IntegerAttr(*index) : IntegerAttr()); 831 }]>, 832 ]; 833} 834 835//===----------------------------------------------------------------------===// 836// pdl_interp::GetResultOp 837//===----------------------------------------------------------------------===// 838 839def PDLInterp_GetResultOp : PDLInterp_Op<"get_result", [Pure]> { 840 let summary = "Get a specified result from an `Operation`"; 841 let description = [{ 842 `pdl_interp.get_result` operations try to get a specific result from an 843 operation. If the operation does not have a result for the given index, a 844 null value is returned. 845 846 Example: 847 848 ```mlir 849 %result = pdl_interp.get_result 1 of %op 850 ``` 851 }]; 852 853 let arguments = (ins PDL_Operation:$inputOp, 854 ConfinedAttr<I32Attr, [IntNonNegative]>:$index); 855 let results = (outs PDL_Value:$value); 856 let assemblyFormat = "$index `of` $inputOp attr-dict"; 857} 858 859//===----------------------------------------------------------------------===// 860// pdl_interp::GetResultsOp 861//===----------------------------------------------------------------------===// 862 863def PDLInterp_GetResultsOp : PDLInterp_Op<"get_results", [Pure]> { 864 let summary = "Get a specified result group from an `Operation`"; 865 let description = [{ 866 `pdl_interp.get_results` operations try to get a specific result group 867 from an operation. If the expected result is a single Value, null is 868 returned if the result group is not of size 1. If a range is expected, 869 null is returned if the result group is invalid. If no index is provided, 870 the returned operand group corresponds to all results of the operation. 871 872 Example: 873 874 ```mlir 875 // Get the first group of results from an operation, and expect a single 876 // element. 877 %result = pdl_interp.get_results 0 of %op : !pdl.value 878 879 // Get the first group of results from an operation. 880 %results = pdl_interp.get_results 0 of %op : !pdl.range<value> 881 882 // Get all of the results from an operation. 883 %results = pdl_interp.get_results of %op : !pdl.range<value> 884 ``` 885 }]; 886 887 let arguments = (ins 888 PDL_Operation:$inputOp, 889 OptionalAttr<ConfinedAttr<I32Attr, [IntNonNegative]>>:$index 890 ); 891 let results = (outs PDL_InstOrRangeOf<PDL_Value>:$value); 892 let assemblyFormat = "($index^)? `of` $inputOp `:` type($value) attr-dict"; 893 let builders = [ 894 OpBuilder<(ins "Type":$resultType, "Value":$inputOp, 895 "std::optional<unsigned>":$index), [{ 896 build($_builder, $_state, resultType, inputOp, 897 index ? $_builder.getI32IntegerAttr(*index) : IntegerAttr()); 898 }]>, 899 OpBuilder<(ins "Value":$inputOp), [{ 900 build($_builder, $_state, 901 pdl::RangeType::get($_builder.getType<pdl::ValueType>()), inputOp, 902 IntegerAttr()); 903 }]>, 904 ]; 905} 906 907//===----------------------------------------------------------------------===// 908// pdl_interp::GetUsersOp 909//===----------------------------------------------------------------------===// 910 911def PDLInterp_GetUsersOp 912 : PDLInterp_Op<"get_users", [Pure]> { 913 let summary = "Get the users of a `Value`"; 914 let description = [{ 915 `pdl_interp.get_users` extracts the users that accept this value. In the 916 case of a range, the union of users of the all the values are returned, 917 similarly to ResultRange::getUsers. 918 919 Example: 920 921 ```mlir 922 // Get all the users of a single value. 923 %ops = pdl_interp.get_users of %value : !pdl.value 924 925 // Get all the users of the first value in a range. 926 %ops = pdl_interp.get_users of %values : !pdl.range<value> 927 ``` 928 }]; 929 930 let arguments = (ins PDL_InstOrRangeOf<PDL_Value>:$value); 931 let results = (outs PDL_RangeOf<PDL_Operation>:$operations); 932 let assemblyFormat = "`of` $value `:` type($value) attr-dict"; 933 934 let builders = [ 935 OpBuilder<(ins "Value":$value), [{ 936 build($_builder, $_state, 937 pdl::RangeType::get($_builder.getType<pdl::OperationType>()), 938 value); 939 }]>, 940 ]; 941} 942 943//===----------------------------------------------------------------------===// 944// pdl_interp::GetValueTypeOp 945//===----------------------------------------------------------------------===// 946 947def PDLInterp_GetValueTypeOp : PDLInterp_Op<"get_value_type", [Pure, 948 TypesMatchWith<"`value` type matches arity of `result`", 949 "result", "value", "getGetValueTypeOpValueType($_self)">]> { 950 let summary = "Get the result type of a specified `Value`"; 951 let description = [{ 952 `pdl_interp.get_value_type` operations get the resulting type of a specific 953 value or range thereof. 954 955 Example: 956 957 ```mlir 958 // Get the type of a single value. 959 %type = pdl_interp.get_value_type of %value : !pdl.type 960 961 // Get the types of a value range. 962 %type = pdl_interp.get_value_type of %values : !pdl.range<type> 963 ``` 964 }]; 965 966 let arguments = (ins PDL_InstOrRangeOf<PDL_Value>:$value); 967 let results = (outs PDL_InstOrRangeOf<PDL_Type>:$result); 968 let assemblyFormat = "`of` $value `:` type($result) attr-dict"; 969 970 let builders = [ 971 OpBuilder<(ins "Value":$value), [{ 972 Type valType = value.getType(); 973 Type typeType = $_builder.getType<pdl::TypeType>(); 974 build($_builder, $_state, 975 ::llvm::isa<pdl::RangeType>(valType) ? pdl::RangeType::get(typeType) 976 : typeType, 977 value); 978 }]> 979 ]; 980} 981 982//===----------------------------------------------------------------------===// 983// pdl_interp::IsNotNullOp 984//===----------------------------------------------------------------------===// 985 986def PDLInterp_IsNotNullOp 987 : PDLInterp_PredicateOp<"is_not_null", [Pure]> { 988 let summary = "Check if a positional value is non-null"; 989 let description = [{ 990 `pdl_interp.is_not_null` operations check that a positional value or range 991 exists. For ranges, this does not mean that the range was simply empty. On 992 success, this operation branches to the true destination. Otherwise, the 993 false destination is taken. 994 995 Example: 996 997 ```mlir 998 pdl_interp.is_not_null %value : !pdl.value -> ^matchDest, ^failureDest 999 ``` 1000 }]; 1001 1002 let arguments = (ins PDL_AnyType:$value); 1003 let assemblyFormat = "$value `:` type($value) attr-dict `->` successors"; 1004} 1005 1006 1007//===----------------------------------------------------------------------===// 1008// pdl_interp::CreateRangeOp 1009//===----------------------------------------------------------------------===// 1010 1011def PDLInterp_CreateRangeOp : PDLInterp_Op<"create_range", [Pure]> { 1012 let summary = "Construct a range of PDL entities"; 1013 let description = [{ 1014 `pdl_interp.create_range` operations construct a range from a given set of PDL 1015 entities, which all share the same underlying element type. For example, a 1016 `!pdl.range<value>` may be constructed from a list of `!pdl.value` 1017 or `!pdl.range<value>` entities. 1018 1019 Example: 1020 1021 ```mlir 1022 // Construct a range of values. 1023 %valueRange = pdl_interp.create_range %inputValue, %inputRange : !pdl.value, !pdl.range<value> 1024 1025 // Construct a range of types. 1026 %typeRange = pdl_interp.create_range %inputType, %inputRange : !pdl.type, !pdl.range<type> 1027 1028 // Construct an empty range of types. 1029 %valueRange = pdl_interp.create_range : !pdl.range<type> 1030 ``` 1031 }]; 1032 1033 let arguments = (ins Variadic<PDL_AnyType>:$arguments); 1034 let results = (outs PDL_RangeOf<AnyTypeOf<[PDL_Type, PDL_Value]>>:$result); 1035 let assemblyFormat = [{ 1036 ($arguments^ `:` type($arguments))? 1037 custom<RangeType>(ref(type($arguments)), type($result)) 1038 attr-dict 1039 }]; 1040 let hasVerifier = 1; 1041} 1042 1043//===----------------------------------------------------------------------===// 1044// pdl_interp::RecordMatchOp 1045//===----------------------------------------------------------------------===// 1046 1047def PDLInterp_RecordMatchOp 1048 : PDLInterp_Op<"record_match", [AttrSizedOperandSegments, Terminator]> { 1049 let summary = "Record the metadata for a successful pattern match"; 1050 let description = [{ 1051 `pdl_interp.record_match` operations record a successful pattern match with 1052 the interpreter and branch to the next part of the matcher. The metadata 1053 recorded by these operations correspond to a specific `pdl.pattern`, as well 1054 as what values were used during that match that should be propagated to the 1055 rewriter. 1056 1057 Example: 1058 1059 ```mlir 1060 pdl_interp.record_match @rewriters::myRewriter(%root : !pdl.operation) : benefit(1), loc([%root, %op1]), root("foo.op") -> ^nextDest 1061 ``` 1062 }]; 1063 1064 let arguments = (ins Variadic<PDL_AnyType>:$inputs, 1065 Variadic<PDL_Operation>:$matchedOps, 1066 SymbolRefAttr:$rewriter, 1067 OptionalAttr<StrAttr>:$rootKind, 1068 OptionalAttr<StrArrayAttr>:$generatedOps, 1069 ConfinedAttr<I16Attr, [IntNonNegative]>:$benefit); 1070 let successors = (successor AnySuccessor:$dest); 1071 let assemblyFormat = [{ 1072 $rewriter (`(` $inputs^ `:` type($inputs) `)`)? `:` 1073 `benefit` `(` $benefit `)` `,` 1074 (`generatedOps` `(` $generatedOps^ `)` `,`)? 1075 `loc` `(` `[` $matchedOps `]` `)` 1076 (`,` `root` `(` $rootKind^ `)`)? attr-dict `->` $dest 1077 }]; 1078} 1079 1080//===----------------------------------------------------------------------===// 1081// pdl_interp::ReplaceOp 1082//===----------------------------------------------------------------------===// 1083 1084def PDLInterp_ReplaceOp : PDLInterp_Op<"replace"> { 1085 let summary = "Mark an operation as `replace`d"; 1086 let description = [{ 1087 `pdl_interp.replaced` operations are used to specify that an operation 1088 should be marked as replaced. The semantics of this operation correspond 1089 with the `replaceOp` method on a `PatternRewriter`. The set of replacement 1090 values must match the number of results specified by the operation. 1091 1092 Example: 1093 1094 ```mlir 1095 // Replace root node with 2 values: 1096 pdl_interp.replace %root with (%val0, %val1 : !pdl.type, !pdl.type) 1097 ``` 1098 }]; 1099 let arguments = (ins PDL_Operation:$inputOp, 1100 Variadic<PDL_InstOrRangeOf<PDL_Value>>:$replValues); 1101 let assemblyFormat = [{ 1102 $inputOp `with` ` ` `(` ($replValues^ `:` type($replValues))? `)` 1103 attr-dict 1104 }]; 1105} 1106 1107//===----------------------------------------------------------------------===// 1108// pdl_interp::SwitchAttributeOp 1109//===----------------------------------------------------------------------===// 1110 1111def PDLInterp_SwitchAttributeOp 1112 : PDLInterp_SwitchOp<"switch_attribute", [Pure]> { 1113 let summary = "Switch on the value of an `Attribute`"; 1114 let description = [{ 1115 `pdl_interp.switch_attribute` operations compare the value of a given 1116 attribute with a set of constant attributes. If the value matches one of the 1117 provided case values the destination for that case value is taken, otherwise 1118 the default destination is taken. 1119 1120 Example: 1121 1122 ```mlir 1123 pdl_interp.switch_attribute %attr to [10, true](^10Dest, ^trueDest) -> ^defaultDest 1124 ``` 1125 }]; 1126 let arguments = (ins PDL_Attribute:$attribute, ArrayAttr:$caseValues); 1127 let assemblyFormat = [{ 1128 $attribute `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 1129 }]; 1130 1131 let builders = [ 1132 OpBuilder<(ins "Value":$attribute, "ArrayRef<Attribute>":$caseValues, 1133 "Block *":$defaultDest, "BlockRange":$dests), [{ 1134 build($_builder, $_state, attribute, $_builder.getArrayAttr(caseValues), 1135 defaultDest, dests); 1136 }]>]; 1137 let hasVerifier = 1; 1138} 1139 1140//===----------------------------------------------------------------------===// 1141// pdl_interp::SwitchOperandCountOp 1142//===----------------------------------------------------------------------===// 1143 1144def PDLInterp_SwitchOperandCountOp 1145 : PDLInterp_SwitchOp<"switch_operand_count", [Pure]> { 1146 let summary = "Switch on the operand count of an `Operation`"; 1147 let description = [{ 1148 `pdl_interp.switch_operand_count` operations compare the operand count of a 1149 given operation with a set of potential counts. If the value matches one of 1150 the provided case values the destination for that case value is taken, 1151 otherwise the default destination is taken. 1152 1153 Example: 1154 1155 ```mlir 1156 pdl_interp.switch_operand_count of %op to [10, 2] -> ^10Dest, ^2Dest, ^defaultDest 1157 ``` 1158 }]; 1159 1160 let arguments = (ins PDL_Operation:$inputOp, I32ElementsAttr:$caseValues); 1161 let assemblyFormat = [{ 1162 `of` $inputOp `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 1163 }]; 1164 1165 let builders = [ 1166 OpBuilder<(ins "Value":$inputOp, "ArrayRef<int32_t>":$counts, 1167 "Block *":$defaultDest, "BlockRange":$dests), [{ 1168 build($_builder, $_state, inputOp, $_builder.getI32VectorAttr(counts), 1169 defaultDest, dests); 1170 }]>]; 1171 let hasVerifier = 1; 1172} 1173 1174//===----------------------------------------------------------------------===// 1175// pdl_interp::SwitchOperationNameOp 1176//===----------------------------------------------------------------------===// 1177 1178def PDLInterp_SwitchOperationNameOp 1179 : PDLInterp_SwitchOp<"switch_operation_name", [Pure]> { 1180 let summary = "Switch on the OperationName of an `Operation`"; 1181 let description = [{ 1182 `pdl_interp.switch_operation_name` operations compare the name of a given 1183 operation with a set of known names. If the value matches one of the 1184 provided case values the destination for that case value is taken, otherwise 1185 the default destination is taken. 1186 1187 Example: 1188 1189 ```mlir 1190 pdl_interp.switch_operation_name of %op to ["foo.op", "bar.op"](^fooDest, ^barDest) -> ^defaultDest 1191 ``` 1192 }]; 1193 1194 let arguments = (ins PDL_Operation:$inputOp, 1195 StrArrayAttr:$caseValues); 1196 let assemblyFormat = [{ 1197 `of` $inputOp `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 1198 }]; 1199 1200 let builders = [ 1201 OpBuilder<(ins "Value":$inputOp, "ArrayRef<OperationName>":$names, 1202 "Block *":$defaultDest, "BlockRange":$dests), [{ 1203 auto stringNames = llvm::to_vector<8>(llvm::map_range(names, 1204 [](OperationName name) { return name.getStringRef(); })); 1205 build($_builder, $_state, inputOp, $_builder.getStrArrayAttr(stringNames), 1206 defaultDest, dests); 1207 }]>, 1208 ]; 1209 let hasVerifier = 1; 1210} 1211 1212//===----------------------------------------------------------------------===// 1213// pdl_interp::SwitchResultCountOp 1214//===----------------------------------------------------------------------===// 1215 1216def PDLInterp_SwitchResultCountOp 1217 : PDLInterp_SwitchOp<"switch_result_count", [Pure]> { 1218 let summary = "Switch on the result count of an `Operation`"; 1219 let description = [{ 1220 `pdl_interp.switch_result_count` operations compare the result count of a 1221 given operation with a set of potential counts. If the value matches one of 1222 the provided case values the destination for that case value is taken, 1223 otherwise the default destination is taken. 1224 1225 Example: 1226 1227 ```mlir 1228 pdl_interp.switch_result_count of %op to [0, 2](^0Dest, ^2Dest) -> ^defaultDest 1229 ``` 1230 }]; 1231 1232 let arguments = (ins PDL_Operation:$inputOp, I32ElementsAttr:$caseValues); 1233 let assemblyFormat = [{ 1234 `of` $inputOp `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 1235 }]; 1236 1237 let builders = [ 1238 OpBuilder<(ins "Value":$inputOp, "ArrayRef<int32_t>":$counts, 1239 "Block *":$defaultDest, "BlockRange":$dests), [{ 1240 build($_builder, $_state, inputOp, $_builder.getI32VectorAttr(counts), 1241 defaultDest, dests); 1242 }]>]; 1243 let hasVerifier = 1; 1244} 1245 1246//===----------------------------------------------------------------------===// 1247// pdl_interp::SwitchTypeOp 1248//===----------------------------------------------------------------------===// 1249 1250def PDLInterp_SwitchTypeOp : PDLInterp_SwitchOp<"switch_type", [Pure]> { 1251 let summary = "Switch on a `Type` value"; 1252 let description = [{ 1253 `pdl_interp.switch_type` operations compare a type with a set of statically 1254 known types. If the value matches one of the provided case values the 1255 destination for that case value is taken, otherwise the default destination 1256 is taken. 1257 1258 Example: 1259 1260 ```mlir 1261 pdl_interp.switch_type %type to [i32, i64] -> ^i32Dest, ^i64Dest, ^defaultDest 1262 ``` 1263 }]; 1264 1265 let arguments = (ins PDL_Type:$value, TypeArrayAttr:$caseValues); 1266 let assemblyFormat = [{ 1267 $value `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 1268 }]; 1269 1270 let builders = [ 1271 OpBuilder<(ins "Value":$edge, "ArrayRef<Attribute>":$types, 1272 "Block *":$defaultDest, "BlockRange":$dests), [{ 1273 build($_builder, $_state, edge, $_builder.getArrayAttr(types), 1274 defaultDest, dests); 1275 }]>, 1276 ]; 1277 1278 let extraClassDeclaration = [{ 1279 auto getCaseTypes() { return getCaseValues().getAsValueRange<TypeAttr>(); } 1280 }]; 1281 let hasVerifier = 1; 1282} 1283 1284//===----------------------------------------------------------------------===// 1285// pdl_interp::SwitchTypesOp 1286//===----------------------------------------------------------------------===// 1287 1288def PDLInterp_SwitchTypesOp : PDLInterp_SwitchOp<"switch_types", 1289 [Pure]> { 1290 let summary = "Switch on a range of `Type` values"; 1291 let description = [{ 1292 `pdl_interp.switch_types` operations compare a range of types with a set of 1293 statically known ranges. If the value matches one of the provided case 1294 values the destination for that case value is taken, otherwise the default 1295 destination is taken. 1296 1297 Example: 1298 1299 ```mlir 1300 pdl_interp.switch_types %type is [[i32], [i64, i64]] -> ^i32Dest, ^i64Dest, ^defaultDest 1301 ``` 1302 }]; 1303 1304 let arguments = (ins 1305 PDL_RangeOf<PDL_Type>:$value, 1306 TypedArrayAttrBase<TypeArrayAttr, "type-array array attribute">:$caseValues 1307 ); 1308 let assemblyFormat = [{ 1309 $value `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 1310 }]; 1311 1312 let builders = [ 1313 OpBuilder<(ins "Value":$edge, "ArrayRef<Attribute>":$types, 1314 "Block *":$defaultDest, "BlockRange":$dests), [{ 1315 build($_builder, $_state, edge, $_builder.getArrayAttr(types), 1316 defaultDest, dests); 1317 }]>, 1318 ]; 1319 1320 let extraClassDeclaration = [{ 1321 auto getCaseTypes() { return getCaseValues().getAsRange<ArrayAttr>(); } 1322 }]; 1323 let hasVerifier = 1; 1324} 1325 1326#endif // MLIR_DIALECT_PDLINTERP_IR_PDLINTERPOPS 1327