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/PDLBase.td" 17include "mlir/Interfaces/SideEffectInterfaces.td" 18include "mlir/IR/SymbolInterfaces.td" 19 20//===----------------------------------------------------------------------===// 21// PDL Ops 22//===----------------------------------------------------------------------===// 23 24class PDL_Op<string mnemonic, list<OpTrait> traits = []> 25 : Op<PDL_Dialect, mnemonic, traits> { 26 let printer = [{ ::print(p, *this); }]; 27 let parser = [{ return ::parse$cppClass(parser, result); }]; 28 let verifier = [{ return ::verify(*this); }]; 29} 30 31//===----------------------------------------------------------------------===// 32// pdl::ApplyConstraintOp 33//===----------------------------------------------------------------------===// 34 35def PDL_ApplyConstraintOp 36 : PDL_Op<"apply_constraint", [HasParent<"pdl::PatternOp">]> { 37 let summary = "Apply a generic constraint to a set of provided entities"; 38 let description = [{ 39 `apply_constraint` operations apply a generic constraint, that has been 40 registered externally with the consumer of PDL, to a given set of entities. 41 The constraint is permitted to accept any number of constant valued 42 parameters. 43 44 Example: 45 46 ```mlir 47 // Apply `myConstraint` to the entities defined by `input`, `attr`, and 48 // `op`. `42`, `"abc"`, and `i32` are constant parameters passed to the 49 // constraint. 50 pdl.apply_constraint "myConstraint"[42, "abc", i32](%input, %attr, %op : !pdl.value, !pdl.attribute, !pdl.operation) 51 ``` 52 }]; 53 54 let arguments = (ins StrAttr:$name, 55 Variadic<PDL_PositionalValue>:$args, 56 OptionalAttr<ArrayAttr>:$constParams); 57 let assemblyFormat = [{ 58 $name ($constParams^)? `(` $args `:` type($args) `)` attr-dict 59 }]; 60 61 let builders = [ 62 OpBuilderDAG<(ins "StringRef":$name, CArg<"ValueRange", "{}">:$args, 63 CArg<"ArrayRef<Attribute>", "{}">:$params), [{ 64 build($_builder, $_state, $_builder.getStringAttr(name), args, 65 params.empty() ? ArrayAttr() : $_builder.getArrayAttr(params)); 66 }]>, 67 ]; 68} 69 70//===----------------------------------------------------------------------===// 71// pdl::AttributeOp 72//===----------------------------------------------------------------------===// 73 74def PDL_AttributeOp : PDL_Op<"attribute"> { 75 let summary = "Define an input attribute in a pattern"; 76 let description = [{ 77 `pdl.attribute` operations capture named attribute edges into an operation. 78 Instances of this operation define, and partially constrain, attributes of a 79 given operation. A `pdl.attribute` may partially constrain the input by 80 specifying an expected attribute value type (via a `pdl.type` operation), or 81 a constant value for the attribute (via `val`). Only one of these may be set 82 for a given input, as the type of the constant value provides the type. When 83 defined within a `pdl.rewrite` region, the constant value must be specified. 84 85 Example: 86 87 ```mlir 88 // Define an attribute: 89 %attr = pdl.attribute 90 91 // Define an attribute with an expected type: 92 %type = pdl.type : i32 93 %attr = pdl.attribute : %type 94 95 // Define an attribute with a constant value: 96 %attr = pdl.attribute "hello" 97 ``` 98 }]; 99 100 let arguments = (ins Optional<PDL_Type>:$type, 101 OptionalAttr<AnyAttr>:$value); 102 let results = (outs PDL_Attribute:$attr); 103 let assemblyFormat = "attr-dict (`:` $type^)? ($value^)?"; 104 105 let builders = [ 106 OpBuilderDAG<(ins CArg<"Value", "Value()">:$type), [{ 107 build($_builder, $_state, $_builder.getType<AttributeType>(), type, 108 Attribute()); 109 }]>, 110 OpBuilderDAG<(ins "Attribute":$attr), [{ 111 build($_builder, $_state, $_builder.getType<AttributeType>(), Value(), attr); 112 }]>, 113 ]; 114} 115 116//===----------------------------------------------------------------------===// 117// pdl::CreateNativeOp 118//===----------------------------------------------------------------------===// 119 120def PDL_CreateNativeOp 121 : PDL_Op<"create_native", [HasParent<"pdl::RewriteOp">]> { 122 let summary = "Call a native creation method to construct an `Attribute`, " 123 "`Operation`, `Type`, or `Value`"; 124 let description = [{ 125 `pdl.create_native` operations invoke a native C++ function, that has been 126 registered externally with the consumer of PDL, to create an `Attribute`, 127 `Operation`, `Type`, or `Value`. The native function must produce a value 128 of the specified return type, and may accept any number of positional 129 arguments and constant attribute parameters. 130 131 Example: 132 133 ```mlir 134 %ret = pdl.create_native "myNativeFunc"[42, "gt"](%arg0, %arg1) : !pdl.attribute 135 ``` 136 }]; 137 138 let arguments = (ins StrAttr:$name, 139 Variadic<PDL_PositionalValue>:$args, 140 OptionalAttr<ArrayAttr>:$constParams); 141 let results = (outs PDL_PositionalValue:$result); 142 let assemblyFormat = [{ 143 $name ($constParams^)? (`(` $args^ `:` type($args) `)`)? `:` type($result) 144 attr-dict 145 }]; 146 let verifier = ?; 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:$operation); 167 let assemblyFormat = "$operation attr-dict"; 168 let verifier = ?; 169} 170 171//===----------------------------------------------------------------------===// 172// pdl::InputOp 173//===----------------------------------------------------------------------===// 174 175def PDL_InputOp : PDL_Op<"input", [HasParent<"pdl::PatternOp">]> { 176 let summary = "Define an input value in a pattern"; 177 let description = [{ 178 `pdl.input` operations capture external operand edges into an operation 179 node that originate from operations or block arguments not otherwise 180 specified within the pattern (e.g. via `pdl.operation`). These operations 181 define, and partially constrain, input operands of a given operation. 182 A `pdl.input` may partially constrain an input operand by specifying an 183 expected value type (via a `pdl.type` operation). 184 185 Example: 186 187 ```mlir 188 // Define an input operand: 189 %operand = pdl.input 190 191 // Define an input operand with an expected type: 192 %type = pdl.type : i32 193 %attr = pdl.input : %type 194 ``` 195 }]; 196 197 let arguments = (ins Optional<PDL_Type>:$type); 198 let results = (outs PDL_Value:$val); 199 let assemblyFormat = "(`:` $type^)? attr-dict"; 200 201 let builders = [ 202 OpBuilderDAG<(ins), [{ 203 build($_builder, $_state, $_builder.getType<ValueType>(), Value()); 204 }]>, 205 ]; 206} 207 208//===----------------------------------------------------------------------===// 209// pdl::OperationOp 210//===----------------------------------------------------------------------===// 211 212def PDL_OperationOp 213 : PDL_Op<"operation", [AttrSizedOperandSegments, NoSideEffect]> { 214 let summary = "Define an operation within a pattern"; 215 let description = [{ 216 `pdl.operation` operations define operation nodes within a pattern. Within 217 a match sequence, i.e. when directly nested within a `pdl.pattern`, these 218 operations correspond to input operations, or those that already existing 219 within the MLIR module. Inside of a `pdl.rewrite`, these operations 220 correspond to operations that should be created as part of the replacement 221 sequence. 222 223 `pdl.operation`s are composed of a name, and a set of attribute, operand, 224 and result type values, that map to what those that would be on a 225 constructed instance of that operation. The results of a `pdl.operation` are 226 a handle to the operation itself, and a handle to each of the operation 227 result values. 228 229 When used within a matching context, the name of the operation may be 230 omitted. 231 232 When used within a rewriting context, i.e. when defined within a 233 `pdl.rewrite`, all of the result types must be "inferable". This means that 234 the type must be attributable to either a constant type value or the result 235 type of another entity, such as an attribute, the result of a 236 `createNative`, or the result type of another operation. If the result type 237 value does not meet any of these criteria, the operation must provide the 238 `InferTypeOpInterface` to ensure that the result types can be inferred. 239 240 Example: 241 242 ```mlir 243 // Define an instance of a `foo.op` operation. 244 %op, %results:4 = pdl.operation "foo.op"(%arg0, %arg1) {"attrA" = %attr0} -> %type, %type, %type, %type 245 ``` 246 }]; 247 248 let arguments = (ins OptionalAttr<StrAttr>:$name, 249 Variadic<PDL_Value>:$operands, 250 Variadic<PDL_Attribute>:$attributes, 251 StrArrayAttr:$attributeNames, 252 Variadic<PDL_Type>:$types); 253 let results = (outs PDL_Operation:$op, 254 Variadic<PDL_Value>:$results); 255 let builders = [ 256 OpBuilderDAG<(ins CArg<"Optional<StringRef>", "llvm::None">:$name, 257 CArg<"ValueRange", "llvm::None">:$operandValues, 258 CArg<"ArrayRef<StringRef>", "llvm::None">:$attrNames, 259 CArg<"ValueRange", "llvm::None">:$attrValues, 260 CArg<"ValueRange", "llvm::None">:$resultTypes), [{ 261 auto nameAttr = name ? StringAttr() : $_builder.getStringAttr(*name); 262 build($_builder, $_state, $_builder.getType<OperationType>(), {}, nameAttr, 263 operandValues, attrValues, $_builder.getStrArrayAttr(attrNames), 264 resultTypes); 265 $_state.types.append(resultTypes.size(), $_builder.getType<ValueType>()); 266 }]>, 267 ]; 268 let extraClassDeclaration = [{ 269 /// Returns true if the operation type referenced supports result type 270 /// inference. 271 bool hasTypeInference(); 272 }]; 273} 274 275//===----------------------------------------------------------------------===// 276// pdl::PatternOp 277//===----------------------------------------------------------------------===// 278 279def PDL_PatternOp : PDL_Op<"pattern", [IsolatedFromAbove, Symbol]> { 280 let summary = "Define a rewrite pattern"; 281 let description = [{ 282 `pdl.pattern` operations provide a transformable representation for a 283 `RewritePattern`. The attributes on this operation correspond to the various 284 metadata on a `RewritePattern`, such as the benefit. The match section of 285 the pattern is specified within the region body, with the rewrite provided 286 by a terminating `pdl.rewrite`. 287 288 Example: 289 290 ```mlir 291 // Provide a pattern matching "foo.op" that replaces the root with its 292 // input. 293 pdl.pattern : benefit(1) { 294 %resultType = pdl.type 295 %inputOperand = pdl.input 296 %root, %results = pdl.operation "foo.op"(%inputOperand) -> (%resultType) 297 pdl.rewrite %root { 298 pdl.replace %root with (%inputOperand) 299 } 300 } 301 ``` 302 }]; 303 304 let arguments = (ins OptionalAttr<StrAttr>:$rootKind, 305 Confined<I16Attr, [IntNonNegative]>:$benefit, 306 OptionalAttr<SymbolNameAttr>:$sym_name); 307 let regions = (region SizedRegion<1>:$body); 308 let assemblyFormat = [{ 309 ($sym_name^)? `:` `benefit` `(` $benefit `)` 310 (`,` `root` `(` $rootKind^ `)`)? attr-dict-with-keyword $body 311 }]; 312 313 let builders = [ 314 OpBuilderDAG<(ins CArg<"Optional<StringRef>", "llvm::None">:$rootKind, 315 CArg<"Optional<uint16_t>", "1">:$benefit, 316 CArg<"Optional<StringRef>", "llvm::None">:$name)>, 317 ]; 318 let extraClassDeclaration = [{ 319 //===------------------------------------------------------------------===// 320 // SymbolOpInterface Methods 321 //===------------------------------------------------------------------===// 322 323 /// A PatternOp may optionally define a symbol. 324 bool isOptionalSymbol() { return true; } 325 326 /// Returns the rewrite operation of this pattern. 327 RewriteOp getRewriter(); 328 329 /// Return the root operation kind that this pattern matches, or None if 330 /// there isn't a specific root. 331 Optional<StringRef> getRootKind(); 332 }]; 333} 334 335//===----------------------------------------------------------------------===// 336// pdl::ReplaceOp 337//===----------------------------------------------------------------------===// 338 339def PDL_ReplaceOp : PDL_Op<"replace", [ 340 AttrSizedOperandSegments, HasParent<"pdl::RewriteOp"> 341 ]> { 342 let summary = "Mark an input operation as `replaced`"; 343 let description = [{ 344 `pdl.replace` operations are used within `pdl.rewrite` regions to specify 345 that an input operation should be marked as replaced. The semantics of this 346 operation correspond with the `replaceOp` method on a `PatternRewriter`. The 347 set of replacement values can be either: 348 * a single `Operation` (`replOperation` should be populated) 349 - The operation will be replaced with the results of this operation. 350 * a set of `Value`s (`replValues` should be populated) 351 - The operation will be replaced with these values. 352 353 Example: 354 355 ```mlir 356 // Replace root node with 2 values: 357 pdl.replace %root with (%val0, %val1) 358 359 // Replace root with another operation: 360 pdl.replace %root with %otherOp 361 ``` 362 }]; 363 let arguments = (ins PDL_Operation:$operation, 364 Optional<PDL_Operation>:$replOperation, 365 Variadic<PDL_Value>:$replValues); 366 let assemblyFormat = [{ 367 $operation `with` (`(` $replValues^ `)`)? ($replOperation^)? attr-dict 368 }]; 369} 370 371//===----------------------------------------------------------------------===// 372// pdl::RewriteOp 373//===----------------------------------------------------------------------===// 374 375def PDL_RewriteOp : PDL_Op<"rewrite", [ 376 Terminator, HasParent<"pdl::PatternOp">, 377 SingleBlockImplicitTerminator<"pdl::RewriteEndOp"> 378 ]> { 379 let summary = "Specify the rewrite of a matched pattern"; 380 let description = [{ 381 `pdl.rewrite` operations terminate the region of a `pdl.pattern` and specify 382 the rewrite of a `pdl.pattern`, on the specified root operation. The 383 rewrite is specified either via a string name (`name`) to an external 384 rewrite function, or via the region body. The rewrite region, if specified, 385 must contain a single block and terminate via the `pdl.rewrite_end` 386 operation. If the rewrite is external, it also takes a set of constant 387 parameters and a set of additional positional values defined within the 388 matcher as arguments. 389 390 Example: 391 392 ```mlir 393 // Specify an external rewrite function: 394 pdl.rewrite %root with "myExternalRewriter"(%value : !pdl.value) 395 396 // Specify the rewrite inline using PDL: 397 pdl.rewrite %root { 398 %op = pdl.operation "foo.op"(%arg0, %arg1) 399 pdl.replace %root with %op 400 } 401 ``` 402 }]; 403 404 let arguments = (ins PDL_Operation:$root, 405 OptionalAttr<StrAttr>:$name, 406 Variadic<PDL_PositionalValue>:$externalArgs, 407 OptionalAttr<ArrayAttr>:$externalConstParams); 408 let regions = (region AnyRegion:$body); 409 let assemblyFormat = [{ 410 $root (`with` $name^ ($externalConstParams^)? 411 (`(` $externalArgs^ `:` type($externalArgs) `)`)?)? 412 ($body^)? 413 attr-dict-with-keyword 414 }]; 415} 416 417def PDL_RewriteEndOp : PDL_Op<"rewrite_end", [Terminator, 418 HasParent<"pdl::RewriteOp">]> { 419 let summary = "Implicit terminator of a `pdl.rewrite` region"; 420 let description = [{ 421 `pdl.rewrite_end` operations terminate the region of a `pdl.rewrite`. 422 }]; 423 let assemblyFormat = "attr-dict"; 424 let verifier = ?; 425} 426 427//===----------------------------------------------------------------------===// 428// pdl::TypeOp 429//===----------------------------------------------------------------------===// 430 431def PDL_TypeOp : PDL_Op<"type"> { 432 let summary = "Define a type handle within a pattern"; 433 let description = [{ 434 `pdl.type` operations capture result type constraints of an `Attributes`, 435 `Values`, and `Operations`. Instances of this operation define, and 436 partially constrain, results types of a given entity. A `pdl.type` may 437 partially constrain the result by specifying a constant `Type`. 438 439 Example: 440 441 ```mlir 442 // Define a type: 443 %attr = pdl.type 444 445 // Define a type with a constant value: 446 %attr = pdl.type : i32 447 ``` 448 }]; 449 450 let arguments = (ins OptionalAttr<TypeAttr>:$type); 451 let results = (outs PDL_Type:$result); 452 let assemblyFormat = "attr-dict (`:` $type^)?"; 453 454 let builders = [ 455 OpBuilderDAG<(ins CArg<"Type", "Type()">:$ty), [{ 456 build($_builder, $_state, $_builder.getType<AttributeType>(), 457 ty ? TypeAttr::get(ty) : TypeAttr()); 458 }]>, 459 ]; 460} 461 462#endif // MLIR_DIALECT_PDL_IR_PDLOPS 463