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