xref: /llvm-project/mlir/include/mlir/Dialect/PDL/IR/PDLOps.td (revision 8ec28af8eaff5acd0df3e53340159c034f08533d)
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