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/PDLBase.td" 17include "mlir/Interfaces/SideEffectInterfaces.td" 18 19//===----------------------------------------------------------------------===// 20// PDLInterp Dialect 21//===----------------------------------------------------------------------===// 22 23def PDLInterp_Dialect : Dialect { 24 let summary = "Interpreted pattern execution dialect"; 25 let description = [{ 26 The PDL Interpreter dialect provides a lower level abstraction compared to 27 the PDL dialect, and is targeted towards low level optimization and 28 interpreter code generation. The dialect operations encapsulates 29 low-level pattern match and rewrite "primitives", such as navigating the 30 IR (Operation::getOperand), creating new operations (OpBuilder::create), 31 etc. Many of the operations within this dialect also fuse branching control 32 flow with some form of a predicate comparison operation. This type of fusion 33 reduces the amount of work that an interpreter must do when executing. 34 }]; 35 36 let name = "pdl_interp"; 37 let cppNamespace = "::mlir::pdl_interp"; 38 let dependentDialects = ["pdl::PDLDialect"]; 39 let extraClassDeclaration = [{ 40 /// Returns the name of the function containing the matcher code. This 41 /// function is called by the interpreter when matching an operation. 42 static StringRef getMatcherFunctionName() { return "matcher"; } 43 44 /// Returns the name of the module containing the rewrite functions. These 45 /// functions are invoked by distinct patterns within the matcher function 46 /// to rewrite the IR after a successful match. 47 static StringRef getRewriterModuleName() { return "rewriters"; } 48 }]; 49} 50 51//===----------------------------------------------------------------------===// 52// PDLInterp Operations 53//===----------------------------------------------------------------------===// 54 55// Generic interpreter operation. 56class PDLInterp_Op<string mnemonic, list<OpTrait> traits = []> : 57 Op<PDLInterp_Dialect, mnemonic, traits>; 58 59//===----------------------------------------------------------------------===// 60// PDLInterp_PredicateOp 61 62// Check operations evaluate a predicate on a positional value and then 63// conditionally branch on the result. 64class PDLInterp_PredicateOp<string mnemonic, list<OpTrait> traits = []> : 65 PDLInterp_Op<mnemonic, !listconcat([Terminator], traits)> { 66 let successors = (successor AnySuccessor:$trueDest, AnySuccessor:$falseDest); 67} 68 69//===----------------------------------------------------------------------===// 70// PDLInterp_SwitchOp 71 72// Switch operations evaluate a predicate on a positional value and then 73// conditionally branch on the result. 74class PDLInterp_SwitchOp<string mnemonic, list<OpTrait> traits = []> : 75 PDLInterp_Op<mnemonic, !listconcat([Terminator], traits)> { 76 let successors = (successor AnySuccessor:$defaultDest, 77 VariadicSuccessor<AnySuccessor>:$cases); 78 79 let verifier = [{ 80 // Verify that the number of case destinations matches the number of case 81 // values. 82 size_t numDests = cases().size(); 83 size_t numValues = caseValues().size(); 84 if (numDests != numValues) { 85 return emitOpError("expected number of cases to match the number of case " 86 "values, got ") 87 << numDests << " but expected " << numValues; 88 } 89 return success(); 90 }]; 91} 92 93//===----------------------------------------------------------------------===// 94// pdl_interp::ApplyConstraintOp 95//===----------------------------------------------------------------------===// 96 97def PDLInterp_ApplyConstraintOp : PDLInterp_PredicateOp<"apply_constraint"> { 98 let summary = "Apply a constraint to a set of positional values"; 99 let description = [{ 100 `pdl_interp.apply_constraint` operations apply a generic constraint, that 101 has been registered with the interpreter, with a given set of positional 102 values. The constraint may have any number of constant parameters. On 103 success, this operation branches to the true destination, otherwise the 104 false destination is taken. 105 106 Example: 107 108 ```mlir 109 // Apply `myConstraint` to the entities defined by `input`, `attr`, and 110 // `op`. 111 pdl_interp.apply_constraint "myConstraint"[42, "abc", i32](%input, %attr, %op : !pdl.value, !pdl.attribute, !pdl.operation) -> ^matchDest, ^failureDest 112 ``` 113 }]; 114 115 let arguments = (ins StrAttr:$name, 116 Variadic<PDL_PositionalValue>:$args, 117 OptionalAttr<ArrayAttr>:$constParams); 118 let assemblyFormat = [{ 119 $name ($constParams^)? `(` $args `:` type($args) `)` attr-dict `->` 120 successors 121 }]; 122} 123 124//===----------------------------------------------------------------------===// 125// pdl_interp::ApplyRewriteOp 126//===----------------------------------------------------------------------===// 127 128def PDLInterp_ApplyRewriteOp : PDLInterp_Op<"apply_rewrite"> { 129 let summary = "Invoke and apply an externally registered rewrite method"; 130 let description = [{ 131 `pdl_interp.apply_rewrite` operations invoke an external rewriter that has 132 been registered with the interpreter to perform the rewrite after a 133 successful match. The rewrite is passed the root operation being matched, a 134 set of additional positional arguments generated within the matcher, and a 135 set of constant parameters. 136 137 Example: 138 139 ```mlir 140 // Rewriter operating solely on the root operation. 141 pdl_interp.apply_rewrite "rewriter" on %root 142 143 // Rewriter operating on the root operation along with additional arguments 144 // from the matcher. 145 pdl_interp.apply_rewrite "rewriter"(%value : !pdl.value) on %root 146 147 // Rewriter operating on the root operation along with additional arguments 148 // and constant parameters. 149 pdl_interp.apply_rewrite "rewriter"[42](%value : !pdl.value) on %root 150 ``` 151 }]; 152 let arguments = (ins StrAttr:$name, 153 PDL_Operation:$root, 154 Variadic<PDL_PositionalValue>:$args, 155 OptionalAttr<ArrayAttr>:$constParams); 156 let assemblyFormat = [{ 157 $name ($constParams^)? (`(` $args^ `:` type($args) `)`)? `on` $root 158 attr-dict 159 }]; 160} 161 162//===----------------------------------------------------------------------===// 163// pdl_interp::AreEqualOp 164//===----------------------------------------------------------------------===// 165 166def PDLInterp_AreEqualOp 167 : PDLInterp_PredicateOp<"are_equal", [NoSideEffect, SameTypeOperands]> { 168 let summary = "Check if two positional values are equivalent"; 169 let description = [{ 170 `pdl_interp.are_equal` operations compare two positional values for 171 equality. On success, this operation branches to the true destination, 172 otherwise the false destination is taken. 173 174 Example: 175 176 ```mlir 177 pdl_interp.are_equal %result1, %result2 : !pdl.value -> ^matchDest, ^failureDest 178 ``` 179 }]; 180 181 let arguments = (ins PDL_PositionalValue:$lhs, 182 PDL_PositionalValue:$rhs); 183 let assemblyFormat = "operands `:` type($lhs) attr-dict `->` successors"; 184} 185 186//===----------------------------------------------------------------------===// 187// pdl_interp::BranchOp 188//===----------------------------------------------------------------------===// 189 190def PDLInterp_BranchOp : PDLInterp_Op<"branch", [NoSideEffect, Terminator]> { 191 let summary = "General branch operation"; 192 let description = [{ 193 `pdl_interp.branch` operations expose general branch functionality to the 194 interpreter, and are generally used to branch from one pattern match 195 sequence to another. 196 197 Example: 198 199 ```mlir 200 pdl_interp.branch ^dest 201 ``` 202 }]; 203 204 let successors = (successor AnySuccessor:$dest); 205 let assemblyFormat = "$dest attr-dict"; 206} 207 208//===----------------------------------------------------------------------===// 209// pdl_interp::CheckAttributeOp 210//===----------------------------------------------------------------------===// 211 212def PDLInterp_CheckAttributeOp 213 : PDLInterp_PredicateOp<"check_attribute", [NoSideEffect]> { 214 let summary = "Check the value of an `Attribute`"; 215 let description = [{ 216 `pdl_interp.check_attribute` operations compare the value of a given 217 attribute with a constant value. On success, this operation branches to the 218 true destination, otherwise the false destination is taken. 219 220 Example: 221 222 ```mlir 223 pdl_interp.check_attribute %attr is 10 -> ^matchDest, ^failureDest 224 ``` 225 }]; 226 227 let arguments = (ins PDL_Attribute:$attribute, AnyAttr:$constantValue); 228 let assemblyFormat = [{ 229 $attribute `is` $constantValue attr-dict `->` successors 230 }]; 231} 232 233//===----------------------------------------------------------------------===// 234// pdl_interp::CheckOperandCountOp 235//===----------------------------------------------------------------------===// 236 237def PDLInterp_CheckOperandCountOp 238 : PDLInterp_PredicateOp<"check_operand_count", [NoSideEffect]> { 239 let summary = "Check the number of operands of an `Operation`"; 240 let description = [{ 241 `pdl_interp.check_operand_count` operations compare the number of operands 242 of a given operation value with a constant. On success, this operation 243 branches to the true destination, otherwise the false destination is taken. 244 245 Example: 246 247 ```mlir 248 pdl_interp.check_operand_count of %op is 2 -> ^matchDest, ^failureDest 249 ``` 250 }]; 251 252 let arguments = (ins PDL_Operation:$operation, 253 Confined<I32Attr, [IntNonNegative]>:$count); 254 let assemblyFormat = "`of` $operation `is` $count attr-dict `->` successors"; 255} 256 257//===----------------------------------------------------------------------===// 258// pdl_interp::CheckOperationNameOp 259//===----------------------------------------------------------------------===// 260 261def PDLInterp_CheckOperationNameOp 262 : PDLInterp_PredicateOp<"check_operation_name", [NoSideEffect]> { 263 let summary = "Check the OperationName of an `Operation`"; 264 let description = [{ 265 `pdl_interp.check_operation_name` operations compare the name of a given 266 operation with a known name. On success, this operation branches to the true 267 destination, otherwise the false destination is taken. 268 269 Example: 270 271 ```mlir 272 pdl_interp.check_operation_name of %op is "foo.op" -> ^matchDest, ^failureDest 273 ``` 274 }]; 275 276 let arguments = (ins PDL_Operation:$operation, StrAttr:$name); 277 let assemblyFormat = "`of` $operation `is` $name attr-dict `->` successors"; 278} 279 280//===----------------------------------------------------------------------===// 281// pdl_interp::CheckResultCountOp 282//===----------------------------------------------------------------------===// 283 284def PDLInterp_CheckResultCountOp 285 : PDLInterp_PredicateOp<"check_result_count", [NoSideEffect]> { 286 let summary = "Check the number of results of an `Operation`"; 287 let description = [{ 288 `pdl_interp.check_result_count` operations compare the number of results 289 of a given operation value with a constant. On success, this operation 290 branches to the true destination, otherwise the false destination is taken. 291 292 Example: 293 294 ```mlir 295 pdl_interp.check_result_count of %op is 0 -> ^matchDest, ^failureDest 296 ``` 297 }]; 298 299 let arguments = (ins PDL_Operation:$operation, 300 Confined<I32Attr, [IntNonNegative]>:$count); 301 let assemblyFormat = "`of` $operation `is` $count attr-dict `->` successors"; 302} 303 304//===----------------------------------------------------------------------===// 305// pdl_interp::CheckTypeOp 306//===----------------------------------------------------------------------===// 307 308def PDLInterp_CheckTypeOp 309 : PDLInterp_PredicateOp<"check_type", [NoSideEffect]> { 310 let summary = "Compare a type to a known value"; 311 let description = [{ 312 `pdl_interp.check_type` operations compare a type with a statically known 313 type. On success, this operation branches to the true destination, otherwise 314 the false destination is taken. 315 316 Example: 317 318 ```mlir 319 pdl_interp.check_type %type is i32 -> ^matchDest, ^failureDest 320 ``` 321 }]; 322 323 let arguments = (ins PDL_Type:$value, TypeAttr:$type); 324 let assemblyFormat = "$value `is` $type attr-dict `->` successors"; 325} 326 327//===----------------------------------------------------------------------===// 328// pdl_interp::CreateAttributeOp 329//===----------------------------------------------------------------------===// 330 331def PDLInterp_CreateAttributeOp 332 : PDLInterp_Op<"create_attribute", [NoSideEffect]> { 333 let summary = "Create an interpreter handle to a constant `Attribute`"; 334 let description = [{ 335 `pdl_interp.create_attribute` operations generate a handle within the 336 interpreter for a specific constant attribute value. 337 338 Example: 339 340 ```mlir 341 %attr = pdl_interp.create_attribute 10 : i64 342 ``` 343 }]; 344 345 let arguments = (ins AnyAttr:$value); 346 let results = (outs PDL_Attribute:$attribute); 347 let assemblyFormat = "$value attr-dict"; 348 349 let builders = [ 350 OpBuilderDAG<(ins "Attribute":$value), [{ 351 build($_builder, $_state, $_builder.getType<pdl::AttributeType>(), value); 352 }]>]; 353} 354 355//===----------------------------------------------------------------------===// 356// pdl_interp::CreateNativeOp 357//===----------------------------------------------------------------------===// 358 359def PDLInterp_CreateNativeOp : PDLInterp_Op<"create_native"> { 360 let summary = "Call a native creation method to construct an `Attribute`, " 361 "`Operation`, `Type`, or `Value`"; 362 let description = [{ 363 `pdl_interp.create_native` operations invoke a native C++ function, that has 364 been registered externally with the consumer of PDL, to create an 365 `Attribute`, `Operation`, `Type`, or `Value`. The native function must 366 produce a value of the specified return type, and may accept any number of 367 positional arguments and constant attribute parameters. 368 369 Example: 370 371 ```mlir 372 %ret = pdl_interp.create_native "myNativeFunc"[42, "gt"](%arg0, %arg1 : !pdl.value, !pdl.value) : !pdl.attribute 373 ``` 374 }]; 375 376 let arguments = (ins StrAttr:$name, 377 Variadic<PDL_PositionalValue>:$args, 378 OptionalAttr<ArrayAttr>:$constParams); 379 let results = (outs PDL_PositionalValue:$result); 380 let assemblyFormat = [{ 381 $name ($constParams^)? (`(` $args^ `:` type($args) `)`)? `:` type($result) 382 attr-dict 383 }]; 384 let verifier = ?; 385} 386 387//===----------------------------------------------------------------------===// 388// pdl_interp::CreateOperationOp 389//===----------------------------------------------------------------------===// 390 391def PDLInterp_CreateOperationOp 392 : PDLInterp_Op<"create_operation", [AttrSizedOperandSegments]> { 393 let summary = "Create an instance of a specific `Operation`"; 394 let description = [{ 395 `pdl_interp.create_operation` operations create an `Operation` instance with 396 the specified attributes, operands, and result types. 397 398 Example: 399 400 ```mlir 401 // Create an instance of a `foo.op` operation. 402 %op = pdl_interp.create_operation "foo.op"(%arg0) {"attrA" = %attr0} -> %type, %type 403 ``` 404 }]; 405 406 let arguments = (ins StrAttr:$name, 407 Variadic<PDL_Value>:$operands, 408 Variadic<PDL_Attribute>:$attributes, 409 StrArrayAttr:$attributeNames, 410 Variadic<PDL_Type>:$types); 411 let results = (outs PDL_Operation:$operation); 412 413 let builders = [ 414 OpBuilderDAG<(ins "StringRef":$name, "ValueRange":$types, 415 "ValueRange":$operands, "ValueRange":$attributes, 416 "ArrayAttr":$attributeNames), [{ 417 build($_builder, $_state, $_builder.getType<pdl::OperationType>(), name, 418 operands, attributes, attributeNames, types); 419 }]>]; 420 let parser = [{ return ::parseCreateOperationOp(parser, result); }]; 421 let printer = [{ ::print(p, *this); }]; 422} 423 424//===----------------------------------------------------------------------===// 425// pdl_interp::CreateTypeOp 426//===----------------------------------------------------------------------===// 427 428def PDLInterp_CreateTypeOp : PDLInterp_Op<"create_type", [NoSideEffect]> { 429 let summary = "Create an interpreter handle to a constant `Type`"; 430 let description = [{ 431 `pdl_interp.create_type` operations generate a handle within the interpreter 432 for a specific constant type value. 433 434 Example: 435 436 ```mlir 437 pdl_interp.create_type i64 438 ``` 439 }]; 440 441 let arguments = (ins TypeAttr:$value); 442 let results = (outs PDL_Type:$result); 443 let assemblyFormat = "$value attr-dict"; 444 445 let builders = [ 446 OpBuilderDAG<(ins "TypeAttr":$type), [{ 447 build($_builder, $_state, $_builder.getType<pdl::TypeType>(), type); 448 }]> 449 ]; 450} 451 452//===----------------------------------------------------------------------===// 453// pdl_interp::EraseOp 454//===----------------------------------------------------------------------===// 455 456def PDLInterp_EraseOp : PDLInterp_Op<"erase"> { 457 let summary = "Mark an operation as `erased`"; 458 let description = [{ 459 `pdl.erase` operations are used to specify that an operation should be 460 marked as erased. The semantics of this operation correspond with the 461 `eraseOp` method on a `PatternRewriter`. 462 463 Example: 464 465 ```mlir 466 pdl_interp.erase %root 467 ``` 468 }]; 469 470 let arguments = (ins PDL_Operation:$operation); 471 let assemblyFormat = "$operation attr-dict"; 472} 473 474//===----------------------------------------------------------------------===// 475// pdl_interp::FinalizeOp 476//===----------------------------------------------------------------------===// 477 478def PDLInterp_FinalizeOp 479 : PDLInterp_Op<"finalize", [NoSideEffect, Terminator]> { 480 let summary = "Finalize a pattern match or rewrite sequence"; 481 let description = [{ 482 `pdl_interp.finalize` is used to denote the termination of a match or 483 rewrite sequence. 484 485 Example: 486 487 ```mlir 488 pdl_interp.finalize 489 ``` 490 }]; 491 let assemblyFormat = "attr-dict"; 492} 493 494//===----------------------------------------------------------------------===// 495// pdl_interp::GetAttributeOp 496//===----------------------------------------------------------------------===// 497 498def PDLInterp_GetAttributeOp : PDLInterp_Op<"get_attribute", [NoSideEffect]> { 499 let summary = "Get a specified attribute value from an `Operation`"; 500 let description = [{ 501 `pdl_interp.get_attribute` operations try to get a specific attribute from 502 an operation. If the operation does not have that attribute, a null value is 503 returned. 504 505 Example: 506 507 ```mlir 508 %attr = pdl_interp.get_attribute "attr" of %op 509 ``` 510 }]; 511 512 let arguments = (ins PDL_Operation:$operation, 513 StrAttr:$name); 514 let results = (outs PDL_Attribute:$attribute); 515 let assemblyFormat = "$name `of` $operation attr-dict"; 516} 517 518//===----------------------------------------------------------------------===// 519// pdl_interp::GetAttributeTypeOp 520//===----------------------------------------------------------------------===// 521 522def PDLInterp_GetAttributeTypeOp 523 : PDLInterp_Op<"get_attribute_type", [NoSideEffect]> { 524 let summary = "Get the result type of a specified `Attribute`"; 525 let description = [{ 526 `pdl_interp.get_attribute_type` operations get the resulting type of a 527 specific attribute. 528 529 Example: 530 531 ```mlir 532 %type = pdl_interp.get_attribute_type of %attr 533 ``` 534 }]; 535 536 let arguments = (ins PDL_Attribute:$value); 537 let results = (outs PDL_Type:$result); 538 let assemblyFormat = "`of` $value attr-dict"; 539 540 let builders = [ 541 OpBuilderDAG<(ins "Value":$value), [{ 542 build($_builder, $_state, $_builder.getType<pdl::TypeType>(), value); 543 }]> 544 ]; 545} 546 547//===----------------------------------------------------------------------===// 548// pdl_interp::GetDefiningOpOp 549//===----------------------------------------------------------------------===// 550 551def PDLInterp_GetDefiningOpOp 552 : PDLInterp_Op<"get_defining_op", [NoSideEffect]> { 553 let summary = "Get the defining operation of a `Value`"; 554 let description = [{ 555 `pdl_interp.get_defining_op` operations try to get the defining operation 556 of a specific value. If the value is not an operation result, null is 557 returned. 558 559 Example: 560 561 ```mlir 562 %op = pdl_interp.get_defining_op of %value 563 ``` 564 }]; 565 566 let arguments = (ins PDL_Value:$value); 567 let results = (outs PDL_Operation:$operation); 568 let assemblyFormat = "`of` $value attr-dict"; 569} 570 571//===----------------------------------------------------------------------===// 572// pdl_interp::GetOperandOp 573//===----------------------------------------------------------------------===// 574 575def PDLInterp_GetOperandOp : PDLInterp_Op<"get_operand", [NoSideEffect]> { 576 let summary = "Get a specified operand from an `Operation`"; 577 let description = [{ 578 `pdl_interp.get_operand` operations try to get a specific operand from an 579 operation If the operation does not have an operand for the given index, a 580 null value is returned. 581 582 Example: 583 584 ```mlir 585 %operand = pdl_interp.get_operand 1 of %op 586 ``` 587 }]; 588 589 let arguments = (ins PDL_Operation:$operation, 590 Confined<I32Attr, [IntNonNegative]>:$index); 591 let results = (outs PDL_Value:$value); 592 let assemblyFormat = "$index `of` $operation attr-dict"; 593} 594 595//===----------------------------------------------------------------------===// 596// pdl_interp::GetResultOp 597//===----------------------------------------------------------------------===// 598 599def PDLInterp_GetResultOp : PDLInterp_Op<"get_result", [NoSideEffect]> { 600 let summary = "Get a specified result from an `Operation`"; 601 let description = [{ 602 `pdl_interp.get_result` operations try to get a specific result from an 603 operation. If the operation does not have a result for the given index, a 604 null value is returned. 605 606 Example: 607 608 ```mlir 609 %result = pdl_interp.get_result 1 of %op 610 ``` 611 }]; 612 613 let arguments = (ins PDL_Operation:$operation, 614 Confined<I32Attr, [IntNonNegative]>:$index); 615 let results = (outs PDL_Value:$value); 616 let assemblyFormat = "$index `of` $operation attr-dict"; 617} 618 619//===----------------------------------------------------------------------===// 620// pdl_interp::GetValueTypeOp 621//===----------------------------------------------------------------------===// 622 623// Get a type from the root operation, held in the rewriter context. 624def PDLInterp_GetValueTypeOp : PDLInterp_Op<"get_value_type", [NoSideEffect]> { 625 let summary = "Get the result type of a specified `Value`"; 626 let description = [{ 627 `pdl_interp.get_value_type` operations get the resulting type of a specific 628 value. 629 630 Example: 631 632 ```mlir 633 %type = pdl_interp.get_value_type of %value 634 ``` 635 }]; 636 637 let arguments = (ins PDL_Value:$value); 638 let results = (outs PDL_Type:$result); 639 let assemblyFormat = "`of` $value attr-dict"; 640 641 let builders = [ 642 OpBuilderDAG<(ins "Value":$value), [{ 643 build($_builder, $_state, $_builder.getType<pdl::TypeType>(), value); 644 }]> 645 ]; 646} 647 648//===----------------------------------------------------------------------===// 649// pdl_interp::InferredTypeOp 650//===----------------------------------------------------------------------===// 651 652def PDLInterp_InferredTypeOp : PDLInterp_Op<"inferred_type"> { 653 let summary = "Generate a handle to a Type that is \"inferred\""; 654 let description = [{ 655 `pdl_interp.inferred_type` operations generate a handle to a type that 656 should be inferred. This signals to other operations, such as 657 `pdl_interp.create_operation`, that this type should be inferred. 658 659 Example: 660 661 ```mlir 662 pdl_interp.inferred_type 663 ``` 664 }]; 665 let results = (outs PDL_Type:$type); 666 let assemblyFormat = "attr-dict"; 667 668 let builders = [ 669 OpBuilderDAG<(ins), [{ 670 build($_builder, $_state, $_builder.getType<pdl::TypeType>()); 671 }]>, 672 ]; 673} 674 675//===----------------------------------------------------------------------===// 676// pdl_interp::IsNotNullOp 677//===----------------------------------------------------------------------===// 678 679def PDLInterp_IsNotNullOp 680 : PDLInterp_PredicateOp<"is_not_null", [NoSideEffect]> { 681 let summary = "Check if a positional value is non-null"; 682 let description = [{ 683 `pdl_interp.is_not_null` operations check that a positional value exists. On 684 success, this operation branches to the true destination. Otherwise, the 685 false destination is taken. 686 687 Example: 688 689 ```mlir 690 pdl_interp.is_not_null %value : !pdl.value -> ^matchDest, ^failureDest 691 ``` 692 }]; 693 694 let arguments = (ins PDL_PositionalValue:$value); 695 let assemblyFormat = "$value `:` type($value) attr-dict `->` successors"; 696} 697 698//===----------------------------------------------------------------------===// 699// pdl_interp::RecordMatchOp 700//===----------------------------------------------------------------------===// 701 702def PDLInterp_RecordMatchOp 703 : PDLInterp_Op<"record_match", [AttrSizedOperandSegments, Terminator]> { 704 let summary = "Record the metadata for a successful pattern match"; 705 let description = [{ 706 `pdl_interp.record_match` operations record a successful pattern match with 707 the interpreter and branch to the next part of the matcher. The metadata 708 recorded by these operations correspond to a specific `pdl.pattern`, as well 709 as what values were used during that match that should be propagated to the 710 rewriter. 711 712 Example: 713 714 ```mlir 715 pdl_interp.record_match @rewriters::myRewriter(%root : !pdl.operation) : benefit(1), loc([%root, %op1]), root("foo.op") -> ^nextDest 716 ``` 717 }]; 718 719 let arguments = (ins Variadic<PDL_PositionalValue>:$inputs, 720 Variadic<PDL_Operation>:$matchedOps, 721 SymbolRefAttr:$rewriter, 722 OptionalAttr<StrAttr>:$rootKind, 723 OptionalAttr<StrArrayAttr>:$generatedOps, 724 Confined<I16Attr, [IntNonNegative]>:$benefit); 725 let successors = (successor AnySuccessor:$dest); 726 let assemblyFormat = [{ 727 $rewriter (`(` $inputs^ `:` type($inputs) `)`)? `:` 728 `benefit` `(` $benefit `)` `,` 729 (`generatedOps` `(` $generatedOps^ `)` `,`)? 730 `loc` `(` `[` $matchedOps `]` `)` 731 (`,` `root` `(` $rootKind^ `)`)? attr-dict `->` $dest 732 }]; 733} 734 735//===----------------------------------------------------------------------===// 736// pdl_interp::ReplaceOp 737//===----------------------------------------------------------------------===// 738 739def PDLInterp_ReplaceOp : PDLInterp_Op<"replace"> { 740 let summary = "Mark an operation as `replace`d"; 741 let description = [{ 742 `pdl_interp.replaced` operations are used to specify that an operation 743 should be marked as replaced. The semantics of this operation correspond 744 with the `replaceOp` method on a `PatternRewriter`. The set of replacement 745 values must match the number of results specified by the operation. 746 747 Example: 748 749 ```mlir 750 // Replace root node with 2 values: 751 pdl_interp.replace %root with (%val0, %val1) 752 ``` 753 }]; 754 let arguments = (ins PDL_Operation:$operation, 755 Variadic<PDL_Value>:$replValues); 756 let assemblyFormat = "$operation `with` `(` $replValues `)` attr-dict"; 757} 758 759//===----------------------------------------------------------------------===// 760// pdl_interp::SwitchAttributeOp 761//===----------------------------------------------------------------------===// 762 763def PDLInterp_SwitchAttributeOp 764 : PDLInterp_SwitchOp<"switch_attribute", [NoSideEffect]> { 765 let summary = "Switch on the value of an `Attribute`"; 766 let description = [{ 767 `pdl_interp.switch_attribute` operations compare the value of a given 768 attribute with a set of constant attributes. If the value matches one of the 769 provided case values the destination for that case value is taken, otherwise 770 the default destination is taken. 771 772 Example: 773 774 ```mlir 775 pdl_interp.switch_attribute %attr to [10, true](^10Dest, ^trueDest) -> ^defaultDest 776 ``` 777 }]; 778 let arguments = (ins PDL_Attribute:$attribute, ArrayAttr:$caseValues); 779 let assemblyFormat = [{ 780 $attribute `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 781 }]; 782 783 let builders = [ 784 OpBuilderDAG<(ins "Value":$attribute, "ArrayRef<Attribute>":$caseValues, 785 "Block *":$defaultDest, "BlockRange":$dests), [{ 786 build($_builder, $_state, attribute, $_builder.getArrayAttr(caseValues), 787 defaultDest, dests); 788 }]>]; 789} 790 791//===----------------------------------------------------------------------===// 792// pdl_interp::SwitchOperandCountOp 793//===----------------------------------------------------------------------===// 794 795def PDLInterp_SwitchOperandCountOp 796 : PDLInterp_SwitchOp<"switch_operand_count", [NoSideEffect]> { 797 let summary = "Switch on the operand count of an `Operation`"; 798 let description = [{ 799 `pdl_interp.switch_operand_count` operations compare the operand count of a 800 given operation with a set of potential counts. If the value matches one of 801 the provided case values the destination for that case value is taken, 802 otherwise the default destination is taken. 803 804 Example: 805 806 ```mlir 807 pdl_interp.switch_operand_count of %op to [10, 2] -> ^10Dest, ^2Dest, ^defaultDest 808 ``` 809 }]; 810 811 let arguments = (ins PDL_Operation:$operation, I32ElementsAttr:$caseValues); 812 let assemblyFormat = [{ 813 `of` $operation `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 814 }]; 815 816 let builders = [ 817 OpBuilderDAG<(ins "Value":$operation, "ArrayRef<int32_t>":$counts, 818 "Block *":$defaultDest, "BlockRange":$dests), [{ 819 build($_builder, $_state, operation, $_builder.getI32VectorAttr(counts), 820 defaultDest, dests); 821 }]>]; 822} 823 824//===----------------------------------------------------------------------===// 825// pdl_interp::SwitchOperationNameOp 826//===----------------------------------------------------------------------===// 827 828def PDLInterp_SwitchOperationNameOp 829 : PDLInterp_SwitchOp<"switch_operation_name", [NoSideEffect]> { 830 let summary = "Switch on the OperationName of an `Operation`"; 831 let description = [{ 832 `pdl_interp.switch_operation_name` operations compare the name of a given 833 operation with a set of known names. If the value matches one of the 834 provided case values the destination for that case value is taken, otherwise 835 the default destination is taken. 836 837 Example: 838 839 ```mlir 840 pdl_interp.switch_operation_name of %op to ["foo.op", "bar.op"](^fooDest, ^barDest) -> ^defaultDest 841 ``` 842 }]; 843 844 let arguments = (ins PDL_Operation:$operation, 845 StrArrayAttr:$caseValues); 846 let assemblyFormat = [{ 847 `of` $operation `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 848 }]; 849 850 let builders = [ 851 OpBuilderDAG<(ins "Value":$operation, "ArrayRef<OperationName>":$names, 852 "Block *":$defaultDest, "BlockRange":$dests), [{ 853 auto stringNames = llvm::to_vector<8>(llvm::map_range(names, 854 [](OperationName name) { return name.getStringRef(); })); 855 build($_builder, $_state, operation, $_builder.getStrArrayAttr(stringNames), 856 defaultDest, dests); 857 }]>, 858 ]; 859} 860 861//===----------------------------------------------------------------------===// 862// pdl_interp::SwitchResultCountOp 863//===----------------------------------------------------------------------===// 864 865def PDLInterp_SwitchResultCountOp 866 : PDLInterp_SwitchOp<"switch_result_count", [NoSideEffect]> { 867 let summary = "Switch on the result count of an `Operation`"; 868 let description = [{ 869 `pdl_interp.switch_result_count` operations compare the result count of a 870 given operation with a set of potential counts. If the value matches one of 871 the provided case values the destination for that case value is taken, 872 otherwise the default destination is taken. 873 874 Example: 875 876 ```mlir 877 pdl_interp.switch_result_count of %op to [0, 2](^0Dest, ^2Dest) -> ^defaultDest 878 ``` 879 }]; 880 881 let arguments = (ins PDL_Operation:$operation, I32ElementsAttr:$caseValues); 882 let assemblyFormat = [{ 883 `of` $operation `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 884 }]; 885 886 let builders = [ 887 OpBuilderDAG<(ins "Value":$operation, "ArrayRef<int32_t>":$counts, 888 "Block *":$defaultDest, "BlockRange":$dests), [{ 889 build($_builder, $_state, operation, $_builder.getI32VectorAttr(counts), 890 defaultDest, dests); 891 }]>]; 892} 893 894//===----------------------------------------------------------------------===// 895// pdl_interp::SwitchTypeOp 896//===----------------------------------------------------------------------===// 897 898def PDLInterp_SwitchTypeOp : PDLInterp_SwitchOp<"switch_type", [NoSideEffect]> { 899 let summary = "Switch on a `Type` value"; 900 let description = [{ 901 `pdl_interp.switch_type` operations compare a type with a set of statically 902 known types. If the value matches one of the provided case values the 903 destination for that case value is taken, otherwise the default destination 904 is taken. 905 906 Example: 907 908 ```mlir 909 pdl_interp.switch_type %type to [i32, i64] -> ^i32Dest, ^i64Dest, ^defaultDest 910 ``` 911 }]; 912 913 let arguments = (ins PDL_Type:$value, TypeArrayAttr:$caseValues); 914 let assemblyFormat = [{ 915 $value `to` $caseValues `(` $cases `)` attr-dict `->` $defaultDest 916 }]; 917 918 let builders = [ 919 OpBuilderDAG<(ins "Value":$edge, "TypeRange":$types, "Block *":$defaultDest, 920 "BlockRange":$dests), [{ 921 build($_builder, $_state, edge, $_builder.getTypeArrayAttr(types), 922 defaultDest, dests); 923 }]>, 924 ]; 925 926 let extraClassDeclaration = [{ 927 auto getCaseTypes() { return caseValues().getAsValueRange<TypeAttr>(); } 928 }]; 929} 930 931#endif // MLIR_DIALECT_PDLINTERP_IR_PDLINTERPOPS 932