1//===- PDLOps.td - Pattern descriptor operations -----------*- 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 Pattern Descriptor Language dialect operations. 10// 11//===----------------------------------------------------------------------===// 12 13#ifndef MLIR_DIALECT_PDL_IR_PDLOPS 14#define MLIR_DIALECT_PDL_IR_PDLOPS 15 16include "mlir/Dialect/PDL/IR/PDLTypes.td" 17include "mlir/IR/OpAsmInterface.td" 18include "mlir/IR/SymbolInterfaces.td" 19include "mlir/Interfaces/SideEffectInterfaces.td" 20 21//===----------------------------------------------------------------------===// 22// PDL Ops 23//===----------------------------------------------------------------------===// 24 25class PDL_Op<string mnemonic, list<Trait> traits = []> 26 : Op<PDL_Dialect, mnemonic, traits>; 27 28//===----------------------------------------------------------------------===// 29// pdl::ApplyNativeConstraintOp 30//===----------------------------------------------------------------------===// 31 32def PDL_ApplyNativeConstraintOp 33 : PDL_Op<"apply_native_constraint", [HasParent<"pdl::PatternOp">]> { 34 let summary = "Apply a native constraint to a set of provided entities"; 35 let description = [{ 36 `pdl.apply_native_constraint` operations apply a native C++ constraint, that 37 has been registered externally with the consumer of PDL, to a given set of 38 entities and optionally return a number of values. 39 40 Example: 41 42 ```mlir 43 // Apply `myConstraint` to the entities defined by `input`, `attr`, and `op`. 44 pdl.apply_native_constraint "myConstraint"(%input, %attr, %op : !pdl.value, !pdl.attribute, !pdl.operation) 45 // Apply constraint `with_result` to `root`. This constraint returns an attribute. 46 %attr = pdl.apply_native_constraint "with_result"(%root : !pdl.operation) : !pdl.attribute 47 ``` 48 }]; 49 50 let arguments = (ins StrAttr:$name, 51 Variadic<PDL_AnyType>:$args, 52 DefaultValuedAttr<BoolAttr, "false">:$isNegated); 53 let results = (outs Variadic<PDL_AnyType>:$results); 54 let assemblyFormat = [{ 55 $name `(` $args `:` type($args) `)` (`:` type($results)^ )? attr-dict 56 }]; 57 let hasVerifier = 1; 58} 59 60//===----------------------------------------------------------------------===// 61// pdl::ApplyNativeRewriteOp 62//===----------------------------------------------------------------------===// 63 64def PDL_ApplyNativeRewriteOp 65 : PDL_Op<"apply_native_rewrite", [HasParent<"pdl::RewriteOp">]> { 66 let summary = "Apply a native rewrite method inside of pdl.rewrite region"; 67 let description = [{ 68 `pdl.apply_native_rewrite` operations apply a native C++ function, that has 69 been registered externally with the consumer of PDL, to perform a rewrite 70 and optionally return a number of values. The native function may accept any 71 number of arguments. This operation is used within a pdl.rewrite region to enable 72 the interleaving of native rewrite methods with other pdl constructs. 73 74 Example: 75 76 ```mlir 77 // Apply a native rewrite method that returns an attribute. 78 %ret = pdl.apply_native_rewrite "myNativeFunc"(%arg0, %attr1) : !pdl.attribute 79 ``` 80 81 ```c++ 82 // The native rewrite as defined in C++: 83 static Attribute myNativeFunc(PatternRewriter &rewriter, Value arg0, Attribute arg1) { 84 // Just return the second arg. 85 return arg1; 86 } 87 88 void registerNativeRewrite(PDLPatternModule &pdlModule) { 89 pdlModule.registerRewriteFunction("myNativeFunc", myNativeFunc); 90 } 91 ``` 92 }]; 93 94 let arguments = (ins StrAttr:$name, Variadic<PDL_AnyType>:$args); 95 let results = (outs Variadic<PDL_AnyType>:$results); 96 let assemblyFormat = [{ 97 $name (`(` $args^ `:` type($args) `)`)? (`:` type($results)^)? attr-dict 98 }]; 99 let hasVerifier = 1; 100} 101 102//===----------------------------------------------------------------------===// 103// pdl::AttributeOp 104//===----------------------------------------------------------------------===// 105 106def PDL_AttributeOp : PDL_Op<"attribute"> { 107 let summary = "Define an input attribute in a pattern"; 108 let description = [{ 109 `pdl.attribute` operations capture named attribute edges into an operation. 110 Instances of this operation define, and partially constrain, attributes of a 111 given operation. A `pdl.attribute` may partially constrain the input by 112 specifying an expected attribute value type (via a `pdl.type` operation), or 113 a constant value for the attribute (via `val`). Only one of these may be set 114 for a given input, as the type of the constant value provides the type. When 115 defined within a `pdl.rewrite` region, the constant value must be specified. 116 117 Example: 118 119 ```mlir 120 // Define an attribute: 121 %attr = pdl.attribute 122 123 // Define an attribute with an expected type: 124 %type = pdl.type : i32 125 %attr = pdl.attribute : %type 126 127 // Define an attribute with a constant value: 128 %attr = pdl.attribute = "hello" 129 ``` 130 }]; 131 132 let arguments = (ins Optional<PDL_Type>:$valueType, 133 OptionalAttr<AnyAttr>:$value); 134 let results = (outs PDL_Attribute:$attr); 135 let assemblyFormat = "(`:` $valueType^)? (`=` $value^)? attr-dict-with-keyword"; 136 137 let builders = [ 138 OpBuilder<(ins CArg<"Value", "Value()">:$type), [{ 139 build($_builder, $_state, $_builder.getType<AttributeType>(), type, 140 Attribute()); 141 }]>, 142 OpBuilder<(ins "Attribute":$attr), [{ 143 build($_builder, $_state, $_builder.getType<AttributeType>(), Value(), attr); 144 }]>, 145 ]; 146 let hasVerifier = 1; 147} 148 149//===----------------------------------------------------------------------===// 150// pdl::EraseOp 151//===----------------------------------------------------------------------===// 152 153def PDL_EraseOp : PDL_Op<"erase", [HasParent<"pdl::RewriteOp">]> { 154 let summary = "Mark an input operation as `erased`"; 155 let description = [{ 156 `pdl.erase` operations are used within `pdl.rewrite` regions to specify that 157 an input operation should be marked as erased. The semantics of this 158 operation correspond with the `eraseOp` method on a `PatternRewriter`. 159 160 Example: 161 162 ```mlir 163 pdl.erase %root 164 ``` 165 }]; 166 let arguments = (ins PDL_Operation:$opValue); 167 let assemblyFormat = "$opValue attr-dict"; 168} 169 170//===----------------------------------------------------------------------===// 171// pdl::OperandOp 172//===----------------------------------------------------------------------===// 173 174def PDL_OperandOp 175 : PDL_Op<"operand", [HasParent<"pdl::PatternOp">]> { 176 let summary = "Define an external input operand in a pattern"; 177 let description = [{ 178 `pdl.operand` operations capture external operand edges into an operation 179 node that originate from operations or block arguments not otherwise 180 specified within the pattern (i.e. via `pdl.result` or `pdl.results`). These 181 operations define individual operands of a given operation. A `pdl.operand` 182 may partially constrain an operand by specifying an expected value type 183 (via a `pdl.type` operation). 184 185 Example: 186 187 ```mlir 188 // Define an external operand: 189 %operand = pdl.operand 190 191 // Define an external operand with an expected type: 192 %type = pdl.type : i32 193 %operand = pdl.operand : %type 194 ``` 195 }]; 196 197 let arguments = (ins Optional<PDL_Type>:$valueType); 198 let results = (outs PDL_Value:$value); 199 let assemblyFormat = "(`:` $valueType^)? attr-dict"; 200 201 let builders = [ 202 OpBuilder<(ins), [{ 203 build($_builder, $_state, $_builder.getType<ValueType>(), Value()); 204 }]>, 205 ]; 206 let hasVerifier = 1; 207} 208 209//===----------------------------------------------------------------------===// 210// pdl::OperandsOp 211//===----------------------------------------------------------------------===// 212 213def PDL_OperandsOp 214 : PDL_Op<"operands", [HasParent<"pdl::PatternOp">]> { 215 let summary = "Define a range of input operands in a pattern"; 216 let description = [{ 217 `pdl.operands` operations capture external operand range edges into an 218 operation node that originate from operations or block arguments not 219 otherwise specified within the pattern (i.e. via `pdl.result` or 220 `pdl.results`). These operations define groups of input operands into a 221 given operation. A `pdl.operands` may partially constrain a set of input 222 operands by specifying expected value types (via `pdl.types` operations). 223 224 Example: 225 226 ```mlir 227 // Define a range of input operands: 228 %operands = pdl.operands 229 230 // Define a range of input operands with expected types: 231 %types = pdl.types : [i32, i64, i32] 232 %typed_operands = pdl.operands : %types 233 ``` 234 }]; 235 236 let arguments = (ins Optional<PDL_RangeOf<PDL_Type>>:$valueType); 237 let results = (outs PDL_RangeOf<PDL_Value>:$value); 238 let assemblyFormat = "(`:` $valueType^)? attr-dict"; 239 240 let builders = [ 241 OpBuilder<(ins), [{ 242 build($_builder, $_state, RangeType::get($_builder.getType<ValueType>()), 243 Value()); 244 }]>, 245 ]; 246 let hasVerifier = 1; 247} 248 249//===----------------------------------------------------------------------===// 250// pdl::OperationOp 251//===----------------------------------------------------------------------===// 252 253def PDL_OperationOp : PDL_Op<"operation", [AttrSizedOperandSegments]> { 254 let summary = "Define an operation within a pattern"; 255 let description = [{ 256 `pdl.operation` operations define operation nodes within a pattern. Within 257 a match sequence, i.e. when directly nested within a `pdl.pattern`, these 258 operations correspond to input operations, or those that already existing 259 within the MLIR module. Inside of a `pdl.rewrite`, these operations 260 correspond to operations that should be created as part of the replacement 261 sequence. 262 263 `pdl.operation`s are composed of a name, and a set of attribute, operand, 264 and result type values, that map to what those that would be on a 265 constructed instance of that operation. The results of a `pdl.operation` are 266 a handle to the operation itself. Handles to the results of the operation 267 can be extracted via `pdl.result`. 268 269 Example: 270 271 ```mlir 272 // Define an instance of a `foo.op` operation. 273 %op = pdl.operation "foo.op"(%arg0, %arg1 : !pdl.value, !pdl.value) 274 {"attrA" = %attr0} -> (%type, %type : !pdl.type, !pdl.type) 275 ``` 276 277 When used within a matching context, the name of the operation may be 278 omitted. 279 280 When used within a rewriting context, i.e. when defined within a 281 `pdl.rewrite`, all of the result types must be "inferable". This means that 282 the type must be attributable to either a constant type value or the result 283 type of another entity, such as an attribute, the result of a 284 `apply_native_rewrite`, or the result type of another operation. If the 285 result type value does not meet any of these criteria, the operation must 286 override the `InferTypeOpInterface` to ensure that the result types can be 287 inferred. 288 289 The operands of the operation are interpreted in the following ways: 290 291 1) A single !pdl.range<value>: 292 293 In this case, the single range is treated as all of the operands of the 294 operation. 295 296 ```mlir 297 // Define an instance with single range of operands. 298 %op = pdl.operation "func.return"(%allArgs : !pdl.range<value>) 299 ``` 300 301 2) A variadic number of either !pdl.value or !pdl.range<value>: 302 303 In this case, the inputs are expected to correspond with the operand groups 304 defined on the operation in ODS. 305 306 ```tablgen 307 // Given the following operation definition in ODS: 308 def MyIndirectCallOp { 309 let results = (outs FunctionType:$call, Variadic<AnyType>:$args); 310 } 311 ``` 312 313 ```mlir 314 // We can match the operands as so: 315 %op = pdl.operation "my.indirect_call"(%call, %args : !pdl.value, !pdl.range<value>) 316 ``` 317 318 The results of the operation are interpreted in the following ways: 319 320 1) A single !pdl.range<type>: 321 322 In this case, the single range is treated as all of the result types of the 323 operation. 324 325 ```mlir 326 // Define an instance with single range of types. 327 %allResultTypes = pdl.types 328 %op = pdl.operation "builtin.unrealized_conversion_cast" -> (%allResultTypes : !pdl.types) 329 ``` 330 331 2) A variadic number of either !pdl.type or !pdl.range<type>: 332 333 In this case, the inputs are expected to correspond with the result groups 334 defined on the operation in ODS. 335 336 ```tablgen 337 // Given the following operation definition in ODS: 338 def MyOp { 339 let results = (outs SomeType:$result, Variadic<SomeType>:$otherResults); 340 } 341 ``` 342 343 ```mlir 344 // We can match the results as so: 345 %result = pdl.type 346 %otherResults = pdl.types 347 %op = pdl.operation "foo.op" -> (%result, %otherResults : !pdl.type, !pdl.range<type>) 348 ``` 349 }]; 350 351 let arguments = (ins OptionalAttr<StrAttr>:$opName, 352 Variadic<PDL_InstOrRangeOf<PDL_Value>>:$operandValues, 353 Variadic<PDL_Attribute>:$attributeValues, 354 StrArrayAttr:$attributeValueNames, 355 Variadic<PDL_InstOrRangeOf<PDL_Type>>:$typeValues); 356 let results = (outs PDL_Operation:$op); 357 let assemblyFormat = [{ 358 ($opName^)? (`(` $operandValues^ `:` type($operandValues) `)`)? 359 custom<OperationOpAttributes>($attributeValues, $attributeValueNames) 360 (`->` `(` $typeValues^ `:` type($typeValues) `)`)? attr-dict 361 }]; 362 363 let builders = [ 364 OpBuilder<(ins CArg<"std::optional<StringRef>", "std::nullopt">:$name, 365 CArg<"ValueRange", "std::nullopt">:$operandValues, 366 CArg<"ArrayRef<StringRef>", "std::nullopt">:$attrNames, 367 CArg<"ValueRange", "std::nullopt">:$attrValues, 368 CArg<"ValueRange", "std::nullopt">:$resultTypes), [{ 369 auto nameAttr = name ? $_builder.getStringAttr(*name) : StringAttr(); 370 build($_builder, $_state, $_builder.getType<OperationType>(), nameAttr, 371 operandValues, attrValues, $_builder.getStrArrayAttr(attrNames), 372 resultTypes); 373 }]>, 374 ]; 375 let extraClassDeclaration = [{ 376 /// Returns true if the operation type referenced supports result type 377 /// inference. 378 bool hasTypeInference(); 379 380 /// Returns true if the operation type referenced might support result type 381 /// inference, i.e. it supports type reference or is currently not 382 /// registered in the context. Returns false if the root operation name 383 /// has not been set. 384 bool mightHaveTypeInference(); 385 }]; 386 let hasVerifier = 1; 387} 388 389//===----------------------------------------------------------------------===// 390// pdl::PatternOp 391//===----------------------------------------------------------------------===// 392 393def PDL_PatternOp : PDL_Op<"pattern", [ 394 IsolatedFromAbove, SingleBlock, Symbol, 395 DeclareOpInterfaceMethods<OpAsmOpInterface, ["getDefaultDialect"]> 396 ]> { 397 let summary = "Define a rewrite pattern"; 398 let description = [{ 399 `pdl.pattern` operations provide a transformable representation for a 400 `RewritePattern`. The attributes on this operation correspond to the various 401 metadata on a `RewritePattern`, such as the benefit. The match section of 402 the pattern is specified within the region body, with the rewrite provided 403 by a terminating `pdl.rewrite`. 404 405 Example: 406 407 ```mlir 408 // Provide a pattern matching "foo.op" that replaces the root with its 409 // operand. 410 pdl.pattern : benefit(1) { 411 %resultType = pdl.type 412 %inputOperand = pdl.operand 413 %root = pdl.operation "foo.op"(%inputOperand) -> (%resultType) 414 pdl.rewrite %root { 415 pdl.replace %root with (%inputOperand) 416 } 417 } 418 ``` 419 }]; 420 421 let arguments = (ins ConfinedAttr<I16Attr, [IntNonNegative]>:$benefit, 422 OptionalAttr<SymbolNameAttr>:$sym_name); 423 let regions = (region SizedRegion<1>:$bodyRegion); 424 let assemblyFormat = [{ 425 ($sym_name^)? `:` `benefit` `(` $benefit `)` attr-dict-with-keyword $bodyRegion 426 }]; 427 428 let builders = [ 429 OpBuilder<(ins CArg<"std::optional<uint16_t>", "1">:$benefit, 430 CArg<"std::optional<StringRef>", "std::nullopt">:$name)>, 431 ]; 432 let extraClassDeclaration = [{ 433 //===------------------------------------------------------------------===// 434 // SymbolOpInterface Methods 435 //===------------------------------------------------------------------===// 436 437 /// A PatternOp may optionally define a symbol. 438 bool isOptionalSymbol() { return true; } 439 440 /// Returns the rewrite operation of this pattern. 441 RewriteOp getRewriter(); 442 }]; 443 let hasRegionVerifier = 1; 444} 445 446//===----------------------------------------------------------------------===// 447// pdl::RangeOp 448//===----------------------------------------------------------------------===// 449 450def PDL_RangeOp : PDL_Op<"range", [Pure, HasParent<"pdl::RewriteOp">]> { 451 let summary = "Construct a range of pdl entities"; 452 let description = [{ 453 `pdl.range` operations construct a range from a given set of PDL entities, 454 which all share the same underlying element type. For example, a 455 `!pdl.range<value>` may be constructed from a list of `!pdl.value` 456 or `!pdl.range<value>` entities. 457 458 Example: 459 460 ```mlir 461 // Construct a range of values. 462 %valueRange = pdl.range %inputValue, %inputRange : !pdl.value, !pdl.range<value> 463 464 // Construct a range of types. 465 %typeRange = pdl.range %inputType, %inputRange : !pdl.type, !pdl.range<type> 466 467 // Construct an empty range of types. 468 %valueRange = pdl.range : !pdl.range<type> 469 ``` 470 471 TODO: Range construction is currently limited to rewrites, but it could 472 be extended to constraints under certain circustances; i.e., if we can 473 determine how to extract the underlying elements. If we can't, e.g. if 474 there are multiple sub ranges used for construction, we won't be able 475 to determine their sizes during constraint time. 476 }]; 477 478 let arguments = (ins Variadic<PDL_AnyType>:$arguments); 479 let results = (outs PDL_RangeOf<AnyTypeOf<[PDL_Type, PDL_Value]>>:$result); 480 let assemblyFormat = [{ 481 ($arguments^ `:` type($arguments))? 482 custom<RangeType>(ref(type($arguments)), type($result)) 483 attr-dict 484 }]; 485 let hasVerifier = 1; 486} 487 488//===----------------------------------------------------------------------===// 489// pdl::ReplaceOp 490//===----------------------------------------------------------------------===// 491 492def PDL_ReplaceOp : PDL_Op<"replace", [ 493 AttrSizedOperandSegments, HasParent<"pdl::RewriteOp"> 494 ]> { 495 let summary = "Mark an input operation as `replaced`"; 496 let description = [{ 497 `pdl.replace` operations are used within `pdl.rewrite` regions to specify 498 that an input operation should be marked as replaced. The semantics of this 499 operation correspond with the `replaceOp` method on a `PatternRewriter`. The 500 set of replacement values can be either: 501 * a single `Operation` (`replOperation` should be populated) 502 - The operation will be replaced with the results of this operation. 503 * a set of `Value`s (`replValues` should be populated) 504 - The operation will be replaced with these values. 505 506 Example: 507 508 ```mlir 509 // Replace root node with 2 values: 510 pdl.replace %root with (%val0, %val1 : !pdl.value, !pdl.value) 511 512 // Replace root node with a range of values: 513 pdl.replace %root with (%vals : !pdl.range<value>) 514 515 // Replace root with another operation: 516 pdl.replace %root with %otherOp 517 ``` 518 }]; 519 let arguments = (ins PDL_Operation:$opValue, 520 Optional<PDL_Operation>:$replOperation, 521 Variadic<PDL_InstOrRangeOf<PDL_Value>>:$replValues); 522 let assemblyFormat = [{ 523 $opValue `with` (`(` $replValues^ `:` type($replValues) `)`)? 524 ($replOperation^)? attr-dict 525 }]; 526 let hasVerifier = 1; 527} 528 529//===----------------------------------------------------------------------===// 530// pdl::ResultOp 531//===----------------------------------------------------------------------===// 532 533def PDL_ResultOp : PDL_Op<"result", [Pure]> { 534 let summary = "Extract a result from an operation"; 535 let description = [{ 536 `pdl.result` operations extract result edges from an operation node within 537 a pattern or rewrite region. The provided index is zero-based, and 538 represents the concrete result to extract, i.e. this is not the result index 539 as defined by the ODS definition of the operation. 540 541 Example: 542 543 ```mlir 544 // Extract a result: 545 %operation = pdl.operation ... 546 %pdl_result = pdl.result 1 of %operation 547 548 // Imagine the following IR being matched: 549 %result_0, %result_1 = foo.op ... 550 551 // If the example pattern snippet above were matching against `foo.op` in 552 // the IR snippet, `%pdl_result` would correspond to `%result_1`. 553 ``` 554 }]; 555 556 let arguments = (ins PDL_Operation:$parent, I32Attr:$index); 557 let results = (outs PDL_Value:$val); 558 let assemblyFormat = "$index `of` $parent attr-dict"; 559} 560 561//===----------------------------------------------------------------------===// 562// pdl::ResultsOp 563//===----------------------------------------------------------------------===// 564 565def PDL_ResultsOp : PDL_Op<"results", [Pure]> { 566 let summary = "Extract a result group from an operation"; 567 let description = [{ 568 `pdl.results` operations extract a result group from an operation within a 569 pattern or rewrite region. If an index is provided, this operation extracts 570 a result group as defined by the ODS definition of the operation. In this 571 case the result of this operation may be either a single `pdl.value` or 572 a `pdl.range<value>`, depending on the constraint of the result in ODS. If 573 no index is provided, this operation extracts the full result range of the 574 operation. 575 576 Example: 577 578 ```mlir 579 // Extract all of the results of an operation: 580 %operation = pdl.operation ... 581 %results = pdl.results of %operation 582 583 // Extract the results in the first result group of an operation, which is 584 // variadic: 585 %operation = pdl.operation ... 586 %results = pdl.results 0 of %operation -> !pdl.range<value> 587 588 // Extract the results in the second result group of an operation, which is 589 // not variadic: 590 %operation = pdl.operation ... 591 %results = pdl.results 1 of %operation -> !pdl.value 592 ``` 593 }]; 594 595 let arguments = (ins PDL_Operation:$parent, OptionalAttr<I32Attr>:$index); 596 let results = (outs PDL_InstOrRangeOf<PDL_Value>:$val); 597 let assemblyFormat = [{ 598 ($index^)? `of` $parent custom<ResultsValueType>(ref($index), type($val)) 599 attr-dict 600 }]; 601 let hasVerifier = 1; 602} 603 604//===----------------------------------------------------------------------===// 605// pdl::RewriteOp 606//===----------------------------------------------------------------------===// 607 608def PDL_RewriteOp : PDL_Op<"rewrite", [ 609 Terminator, HasParent<"pdl::PatternOp">, NoTerminator, NoRegionArguments, 610 SingleBlock, AttrSizedOperandSegments, 611 DeclareOpInterfaceMethods<OpAsmOpInterface, ["getDefaultDialect"]> 612 ]> { 613 let summary = "Specify the rewrite of a matched pattern"; 614 let description = [{ 615 `pdl.rewrite` operations terminate the region of a `pdl.pattern` and specify 616 the main rewrite of a `pdl.pattern`, on the optional root operation. The 617 rewrite is specified either via a string name (`name`) to a native 618 rewrite function, or via the region body. The rewrite region, if specified, 619 must contain a single block. If the rewrite is external it functions 620 similarly to `pdl.apply_native_rewrite`, and takes a set of additional 621 positional values defined within the matcher as arguments. If the rewrite is 622 external, the root operation is passed to the native function as the leading 623 arguments. The root operation, if provided, specifies the starting point in 624 the pattern for the subgraph isomorphism search. Pattern matching will proceed 625 from this node downward (towards the defining operation) or upward 626 (towards the users) until all the operations in the pattern have been matched. 627 If the root is omitted, the pdl_interp lowering will automatically select 628 the best root of the pdl.rewrite among all the operations in the pattern. 629 630 Example: 631 632 ```mlir 633 // Specify an external rewrite function: 634 pdl.rewrite %root with "myExternalRewriter"(%value : !pdl.value) 635 636 // Specify a rewrite inline using PDL with the given root: 637 pdl.rewrite %root { 638 %op = pdl.operation "foo.op"(%arg0, %arg1) 639 pdl.replace %root with %op 640 } 641 642 // Specify a rewrite inline using PDL, automatically selecting root: 643 pdl.rewrite { 644 %op1 = pdl.operation "foo.op"(%arg0, %arg1) 645 %op2 = pdl.operation "bar.op"(%arg0, %arg1) 646 pdl.replace %root1 with %op1 647 pdl.replace %root2 with %op2 648 } 649 ``` 650 }]; 651 652 let arguments = (ins Optional<PDL_Operation>:$root, 653 OptionalAttr<StrAttr>:$name, 654 Variadic<PDL_AnyType>:$externalArgs); 655 let regions = (region AnyRegion:$bodyRegion); 656 let assemblyFormat = [{ 657 ($root^)? (`with` $name^ (`(` $externalArgs^ `:` type($externalArgs) `)`)?)? 658 ($bodyRegion^)? 659 attr-dict-with-keyword 660 }]; 661 let hasRegionVerifier = 1; 662} 663 664//===----------------------------------------------------------------------===// 665// pdl::TypeOp 666//===----------------------------------------------------------------------===// 667 668def PDL_TypeOp : PDL_Op<"type"> { 669 let summary = "Define a type handle within a pattern"; 670 let description = [{ 671 `pdl.type` operations capture result type constraints of `Attributes`, 672 `Values`, and `Operations`. Instances of this operation define, and 673 partially constrain, results types of a given entity. A `pdl.type` may 674 partially constrain the result by specifying a constant `Type`. 675 676 Example: 677 678 ```mlir 679 // Define a type: 680 %type = pdl.type 681 682 // Define a type with a constant value: 683 %type = pdl.type : i32 684 ``` 685 }]; 686 687 let arguments = (ins OptionalAttr<TypeAttr>:$constantType); 688 let results = (outs PDL_Type:$result); 689 let assemblyFormat = "attr-dict (`:` $constantType^)?"; 690 let hasVerifier = 1; 691} 692 693//===----------------------------------------------------------------------===// 694// pdl::TypesOp 695//===----------------------------------------------------------------------===// 696 697def PDL_TypesOp : PDL_Op<"types"> { 698 let summary = "Define a range of type handles within a pattern"; 699 let description = [{ 700 `pdl.types` operations capture result type constraints of `Value`s, and 701 `Operation`s. Instances of this operation define results types of a given 702 entity. A `pdl.types` may partially constrain the results by specifying 703 an array of `Type`s. 704 705 Example: 706 707 ```mlir 708 // Define a range of types: 709 %types = pdl.types 710 711 // Define a range of types with a range of constant values: 712 %types = pdl.types : [i32, i64, i32] 713 ``` 714 }]; 715 716 let arguments = (ins OptionalAttr<TypeArrayAttr>:$constantTypes); 717 let results = (outs PDL_RangeOf<PDL_Type>:$result); 718 let assemblyFormat = "attr-dict (`:` $constantTypes^)?"; 719 let hasVerifier = 1; 720} 721 722#endif // MLIR_DIALECT_PDL_IR_PDLOPS 723