1# Table-driven Declarative Rewrite Rule (DRR)
2
3In addition to subclassing the `mlir::RewritePattern` C++ class, MLIR also
4supports defining rewrite rules in a declarative manner. Similar to
5[Op Definition Specification](OpDefinitions.md) (ODS), this is achieved via
6[TableGen][TableGen], which is a language to maintain records of domain-specific
7information. The rewrite rules are specified concisely in a TableGen record,
8which will be expanded into an equivalent `mlir::RewritePattern` subclass at
9compiler build time.
10
11This manual explains in detail all of the available mechanisms for defining
12rewrite rules in such a declarative manner. It aims to be a specification
13instead of a tutorial. Please refer to
14[Quickstart tutorial to adding MLIR graph rewrite](Tutorials/QuickstartRewrites.md)
15for the latter.
16
17Given that declarative rewrite rules depend on op definition specification, this
18manual assumes knowledge of the [ODS](OpDefinitions.md) doc.
19
20## Benefits
21
22Compared to the hand-written C++ classes, this declarative approach has several
23benefits, including but not limited to:
24
25*   **Being declarative**: The pattern creator just needs to state the rewrite
26    pattern declaratively, without worrying about the concrete C++ methods to
27    call.
28*   **Removing boilerplate and showing the very essence of the rewrite**:
29    `mlir::RewritePattern` is already good at hiding boilerplate for defining a
30    rewrite rule. But we still need to write the class and function structures
31    required by the C++ programming language, inspect ops for matching, and call
32    op `build()` methods for constructing. These statements are typically quite
33    simple and similar, so they can be further condensed with auto-generation.
34    Because we reduce the boilerplate to the bare minimum, the declarative
35    rewrite rule will just contain the very essence of the rewrite. This makes
36    it very easy to understand the pattern.
37
38## Strengths and Limitations
39
40The declarative rewrite rule is **operation-based**: it describes a rule to
41match against a directed acyclic graph (DAG) of operations and generate DAGs of
42operations. This gives DRR both its strengths and limitations: it is good at
43expressing op to op conversions, but not that well suited for, say, converting
44an op into a loop nest.
45
46Per the current implementation, DRR does not have good support for the following
47features:
48
49*   Matching and generating ops with regions.
50*   Matching and generating ops with block arguments.
51*   Matching multi-result ops in nested patterns.
52*   Matching and generating variadic operand/result ops in nested patterns.
53*   Packing and unpacking variadic operands/results during generation.
54*   [`NativeCodeCall`](#nativecodecall-transforming-the-generated-op) returning
55    more than one results.
56
57## Rule Definition
58
59The core construct for defining a rewrite rule is defined in
60[`OpBase.td`][OpBase] as
61
62```tablegen
63class Pattern<
64    dag sourcePattern, list<dag> resultPatterns,
65    list<dag> additionalConstraints = [],
66    dag benefitsAdded = (addBenefit 0)>;
67```
68
69A declarative rewrite rule contains two main components:
70
71*   A *source pattern*, which is used for matching a DAG of operations.
72*   One or more *result patterns*, which are used for generating DAGs of
73    operations to replace the matched DAG of operations.
74
75We allow multiple result patterns to support
76[multi-result ops](#supporting-multi-result-ops) and
77[auxiliary ops](#supporting-auxiliary-ops), but frequently we just want to
78convert one DAG of operations to another DAG of operations. There is a handy
79wrapper of `Pattern`, `Pat`, which takes a single result pattern:
80
81```tablegen
82class Pat<
83    dag sourcePattern, dag resultPattern,
84    list<dag> additionalConstraints = [],
85    dag benefitsAdded = (addBenefit 0)> :
86  Pattern<sourcePattern, [resultPattern], additionalConstraints, benefitAdded>;
87```
88
89Each pattern is specified as a TableGen `dag` object with the syntax of
90`(operator arg0, arg1, ...)`.
91
92`operator` is typically an MLIR op, but it can also be other
93[directives](#rewrite-directives). `argN` is for matching (if used in source
94pattern) or generating (if used in result pattern) the `N`-th argument for
95`operator`. If the `operator` is some MLIR operation, it means the `N`-th
96argument as specified in the `arguments` list of the op's definition. Therefore,
97we say op argument specification in pattern is **position-based**: the position
98where they appear matters.
99
100`argN` can be a `dag` object itself, thus we can have nested `dag` tree to model
101the def-use relationship between ops.
102
103### Source pattern
104
105The source pattern is for matching a DAG of operations. Arguments in the `dag`
106object are intended to **capture** the op arguments. They can also be used to
107**further limit** the match criteria. The capturing is done by specifying a
108symbol starting with the `$` sign, while further constraints are introduced by
109specifying a `TypeConstraint` (for an operand) or a `AttrConstraint` (for an
110attribute).
111
112#### Binding op arguments and limiting the match
113
114For example,
115
116```tablegen
117def AOp : Op<"a_op"> {
118    let arguments = (ins
119      AnyType:$a_input,
120      AnyAttr:$a_attr
121    );
122
123    let results = (outs
124      AnyType:$a_output
125    );
126}
127
128def : Pat<(AOp $input, F32Attr:$attr), ...>;
129```
130
131In the above, we are matching an `AOp` whose `$input` can be anything valid as
132defined by the op and whose `$attr` must be a float attribute. If the match
133succeeds, we bind the `$input` symbol to the op's only input (`$a_input`) and
134`$attr` to the only attribute (`$a_attr`); we can reference them using `$input`
135and `$attr` in result patterns and additional constraints.
136
137The pattern is position-based: the symbol names used for capturing here do not
138need to match with the op definition as shown in the above example. As another
139example, the pattern can be written as `def : Pat<(AOp $a, F32Attr:$b), ...>;`
140and use `$a` and `$b` to refer to the captured input and attribute. But using
141the ODS name directly in the pattern is also allowed. Operands in the source
142pattern can have the same name. This bounds one operand to the name while
143verifying the rest are all equal.
144
145Also note that we only need to add `TypeConstraint` or `AttributeConstraint`
146when we need to further limit the match criteria. If all valid cases to the op
147are acceptable, then we can leave the constraint unspecified.
148
149`$_` is a special symbol to mean ignore capturing an argument. For example,
150`def : Pat<(AOp $_, $b), ...>` means only `$b` is interesting to capture and
151will be referenced later in result patterns. It's still possible to place
152additional constraints even if the symbol is not to be captured; for such case,
153you can simply use just the `TypeConstraint` or `AttributeConstraint` without a
154bound symbol, for example, `def : Pat<(AOp $a, F32Attr), ...>`.
155
156#### Matching DAG of operations
157
158To match a DAG of ops, use nested `dag` objects:
159
160```tablegen
161
162def BOp : Op<"b_op"> {
163    let arguments = (ins);
164
165    let results = (outs
166      AnyType:$b_output
167    );
168}
169
170
171def : Pat<(AOp (BOp), $attr), ...>;
172```
173
174The above pattern matches an `AOp` whose only operand is generated by a `BOp`,
175that is, the following MLIR code:
176
177```mlir
178%0 = "b_op"() : () -> (...)
179%1 = "a_op"(%0) {attr: ...} : () -> (...)
180```
181
182#### Binding op results
183
184To bind a symbol to the results of a matched op for later reference, attach the
185symbol to the op itself:
186
187```tablegen
188def : Pat<(AOp (BOp:$b_result), $attr), ...>;
189```
190
191The above will bind `$b_result` to the matched `BOp`'s result. (There are more
192details regarding multi-result ops, which is covered
193[later](#supporting-multi-result-ops).)
194
195### Result pattern
196
197The result pattern is for generating a DAG of operations. Arguments in the `dag`
198object are intended to **reference** values captured in the source pattern and
199potentially **apply transformations**.
200
201#### Referencing bound symbols
202
203For example,
204
205```tablegen
206def COp : Op<"c_op"> {
207    let arguments = (ins
208      AnyType:$c_input,
209      AnyAttr:$c_attr
210    );
211
212    let results = (outs
213      AnyType:$c_output
214    );
215}
216
217def : Pat<(AOp $input, $attr), (COp $input, $attr)>;
218```
219
220In the above, `AOp`'s only operand and attribute are bound to `$input` and
221`$attr`, respectively. We then reference them in the result pattern for
222generating the `COp` by passing them in as arguments to `COp`'s `build()`
223method.
224
225We can also reference symbols bound to matched op's results:
226
227```tablegen
228def : Pat<(AOp (BOp:$b_result) $attr), (COp $b_result $attr)>;
229```
230
231In the above, we are using `BOp`'s result for building `COp`.
232
233#### Building operations
234
235Given that `COp` was specified with table-driven op definition, there will be
236several `build()` methods generated for it. One of them has aggregated
237parameters for result types, operands, and attributes in the signature: `void
238COp::build(..., ArrayRef<Type> resultTypes, Array<Value> operands,
239ArrayRef<NamedAttribute> attr)`. The pattern in the above calls this `build()`
240method for constructing the `COp`.
241
242In general, arguments in the result pattern will be passed directly to the
243`build()` method to leverage the auto-generated `build()` method, list them in
244the pattern by following the exact same order as the ODS `arguments` definition.
245Otherwise, a custom `build()` method that matches the argument list is required.
246
247Right now all ODS-generated `build()` methods require specifying the result
248type(s), unless the op has known traits like `SameOperandsAndResultType` that we
249can use to auto-generate a `build()` method with result type deduction. When
250generating an op to replace the result of the matched root op, we can use the
251matched root op's result type when calling the ODS-generated builder. Otherwise
252(e.g., generating an [auxiliary op](#supporting-auxiliary-ops) or generating an
253op with a nested result pattern), DRR will not be able to deduce the result
254type(s). The pattern author will need to define a custom builder that has result
255type deduction ability via `OpBuilder` in ODS. For example, in the following
256pattern
257
258```tablegen
259def : Pat<(AOp $input, $attr), (COp (AOp $input, $attr) $attr)>;
260```
261
262`AOp` is generated via a nested result pattern; DRR won't be able to deduce the
263result type for it. A custom builder for `AOp` should be defined and it should
264deduce the result type by itself. The builder should have the separate parameter
265for each operand and attribute and deduce the result type internally by itself.
266For example, for the above `AOp`, a possible builder is:
267
268```c++
269
270void AOp::build(OpBuilder &builder, OperationState &state,
271                Value input, Attribute attr) {
272  state.addOperands({input});
273  state.addAttribute("a_attr", attr);
274  Type type = ...; // Deduce result type here
275  state.addTypes({type});
276}
277```
278
279Failing to define such a builder will result in an error at C++ compilation time
280saying the call to `AOp::build()` cannot be resolved because of the number of
281parameters mismatch.
282
283#### Generating DAG of operations
284
285`dag` objects can be nested to generate a DAG of operations:
286
287```tablegen
288def : Pat<(AOp $input, $attr), (COp (BOp), $attr)>;
289```
290
291In the above, we generate a `BOp`, and then use its result to generate the `COp`
292to replace the matched `AOp`.
293
294#### Binding op results
295
296In the result pattern, we can bind to the result(s) of a newly built op by
297attaching symbols to the op. (But we **cannot** bind to op arguments given that
298they are referencing previously bound symbols.) This is useful for reusing newly
299created results where suitable. For example,
300
301```tablegen
302def DOp : Op<"d_op"> {
303    let arguments = (ins
304      AnyType:$d_input1,
305      AnyType:$d_input2,
306    );
307
308    let results = (outs
309      AnyType:$d_output
310    );
311}
312
313def : Pat<(AOp $input, $ignored_attr), (DOp (BOp:$b_result) $b_result)>;
314```
315
316In this pattern, an `AOp` is matched and replaced with a `DOp` whose two
317operands are from the result of a single `BOp`. This is only possible by binding
318the result of the `BOp` to a name and reuse it for the second operand of the
319`DOp`
320
321#### `NativeCodeCall`: transforming the generated op
322
323Sometimes the captured arguments are not exactly what we want so they cannot be
324directly fed in as arguments to build the new op. For such cases, we can apply
325transformations on the arguments by calling into C++ helper functions. This is
326achieved by `NativeCodeCall`.
327
328For example, if we want to capture some op's attributes and group them as an
329array attribute to construct a new op:
330
331```tablegen
332
333def TwoAttrOp : Op<"two_attr_op"> {
334    let arguments = (ins
335      AnyAttr:$op_attr1,
336      AnyAttr:$op_attr2
337    );
338
339    let results = (outs
340      AnyType:$op_output
341    );
342}
343
344def OneAttrOp : Op<"one_attr_op"> {
345    let arguments = (ins
346      ArrayAttr:$op_attr
347    );
348
349    let results = (outs
350      AnyType:$op_output
351    );
352}
353```
354
355We can write a C++ helper function:
356
357```c++
358ArrayAttr createArrayAttr(Builder &builder, Attribute a, Attribute b) {
359  return builder.getArrayAttr({a, b});
360}
361```
362
363And then write the pattern as:
364
365```tablegen
366def createArrayAttr : NativeCodeCall<"createArrayAttr($_builder, $0, $1)">;
367
368def : Pat<(TwoAttrOp $attr1, $attr2),
369          (OneAttrOp (createArrayAttr $attr1, $attr2))>;
370```
371
372And make sure the generated C++ code from the above pattern has access to the
373definition of the C++ helper function.
374
375In the above example, we are using a string to specialize the `NativeCodeCall`
376template. The string can be an arbitrary C++ expression that evaluates into some
377C++ object expected at the `NativeCodeCall` site (here it would be expecting an
378array attribute). Typically the string should be a function call.
379
380##### `NativeCodeCall` placeholders
381
382In `NativeCodeCall`, we can use placeholders like `$_builder`, `$N` and `$N...`.
383The former is called *special placeholder*, while the latter is called
384*positional placeholder* and *positional range placeholder*.
385
386`NativeCodeCall` right now only supports three special placeholders:
387`$_builder`, `$_loc`, and `$_self`:
388
389*   `$_builder` will be replaced by the current `mlir::PatternRewriter`.
390*   `$_loc` will be replaced by the fused location or custom location (as
391    determined by location directive).
392*   `$_self` will be replaced by the defining operation in a source pattern.
393
394We have seen how `$_builder` can be used in the above; it allows us to pass a
395`mlir::Builder` (`mlir::PatternRewriter` is a subclass of `mlir::OpBuilder`,
396which is a subclass of `mlir::Builder`) to the C++ helper function to use the
397handy methods on `mlir::Builder`.
398
399Here's an example how we should use `$_self` in source pattern,
400
401```tablegen
402
403def : Pat<(OneAttrOp (NativeCodeCall<"Foo($_self, &$0)"> I32Attr:$val)),
404          (TwoAttrOp $val, $val)>;
405```
406
407In the above, `$_self` is substituted by the defining operation of the first
408operand of OneAttrOp. Note that we don't support binding name to
409`NativeCodeCall` in the source pattern. To carry some return values from a
410helper function, put the names (constraint is optional) in the parameter list
411and they will be bound to the variables with corresponding type. Then these names
412must be either passed by reference or pointer to the variable used as argument
413so that the matched value can be returned. In the same example, `$val` will be
414bound to a variable with `Attribute` type (as `I32Attr`) and the type of the
415second argument in `Foo()` could be `Attribute&` or `Attribute*`. Names with
416attribute constraints will be captured as `Attribute`s while everything else
417will be treated as `Value`s.
418
419Positional placeholders will be substituted by the `dag` object parameters at
420the `NativeCodeCall` use site. For example, if we define `SomeCall :
421NativeCodeCall<"someFn($1, $2, $0)">` and use it like `(SomeCall $in0, $in1,
422$in2)`, then this will be translated into C++ call `someFn($in1, $in2, $in0)`.
423
424Positional range placeholders will be substituted by multiple `dag` object
425parameters at the `NativeCodeCall` use site. For example, if we define
426`SomeCall : NativeCodeCall<"someFn($1...)">` and use it like `(SomeCall $in0,
427$in1, $in2)`, then this will be translated into C++ call `someFn($in1, $in2)`.
428
429##### `NativeCodeCall` binding multi-results
430
431To bind multi-results and access the N-th result with `$<name>__N`, specify the
432number of return values in the template. Note that only `Value` type is
433supported for multiple results binding. For example,
434
435```tablegen
436
437def PackAttrs : NativeCodeCall<"packAttrs($0, $1)", 2>;
438def : Pattern<(TwoResultOp $attr1, $attr2),
439              [(OneResultOp (PackAttr:$res__0, $attr1, $attr2)),
440               (OneResultOp $res__1)]>;
441
442```
443
444Use `NativeCodeCallVoid` for cases with no return value.
445
446The correct number of returned value specified in NativeCodeCall is important.
447It will be used to verify the consistency of the number of return values.
448Additionally, `mlir-tblgen` will try to capture the return values of
449`NativeCodeCall` in the generated code so that it will trigger a later
450compilation error if a `NativeCodeCall` that doesn't return any result isn't
451labeled with 0 returns.
452
453##### Customizing entire op building
454
455`NativeCodeCall` is not only limited to transforming arguments for building an
456op; it can be also used to specify how to build an op entirely. An example:
457
458If we have a C++ function for building an op:
459
460```c++
461Operation *createMyOp(OpBuilder builder, Value input, Attribute attr);
462```
463
464We can wrap it up and invoke it like:
465
466```tablegen
467def createMyOp : NativeCodeCall<"createMyOp($_builder, $0, $1)">;
468
469def : Pat<(... $input, $attr), (createMyOp $input, $attr)>;
470```
471
472### Supporting auxiliary ops
473
474A declarative rewrite rule supports multiple result patterns. One of the
475purposes is to allow generating *auxiliary ops*. Auxiliary ops are operations
476used for building the replacement ops; but they are not directly used for
477replacement themselves.
478
479For the case of uni-result ops, if there are multiple result patterns, only the
480value generated from the last result pattern will be used to replace the matched
481root op's result; all other result patterns will be considered as generating
482auxiliary ops.
483
484Normally we want to specify ops as nested `dag` objects if their def-use
485relationship can be expressed in the way that an op's result can feed as the
486argument to consuming op. But that is not always possible. For example, if we
487want to allocate memory and store some computation (in pseudocode):
488
489```mlir
490%dst = arith.addi %lhs, %rhs
491```
492
493into
494
495```mlir
496%shape = shape %lhs
497%mem = memref.alloc %shape
498%sum = arith.addi %lhs, %rhs
499memref.store %mem, %sum
500%dst = memref.load %mem
501```
502
503We cannot fit in with just one result pattern given `store` does not return a
504value. Instead we can use multiple result patterns:
505
506```tablegen
507def : Pattern<(AddIOp $lhs, $rhs),
508              [(StoreOp (AllocOp:$mem (ShapeOp $lhs)), (AddIOp $lhs, $rhs)),
509               (LoadOp $mem)];
510```
511
512In the above we use the first result pattern to generate the first four ops, and
513use the last pattern to generate the last op, which is used to replace the
514matched op.
515
516### Supporting multi-result ops
517
518Multi-result ops bring extra complexity to declarative rewrite rules. We use
519TableGen `dag` objects to represent ops in patterns; there is no native way to
520indicate that an op generates multiple results. The approach adopted is based on
521**naming convention**: a `__N` suffix is added to a symbol to indicate the
522`N`-th result.
523
524#### `__N` suffix
525
526The `__N` suffix is specifying the `N`-th result as a whole (which can be
527[variadic](#supporting-variadic-ops)). For example, we can bind a symbol to some
528multi-result op and reference a specific result later:
529
530```tablegen
531def ThreeResultOp : Op<"three_result_op"> {
532    let arguments = (ins ...);
533
534    let results = (outs
535      AnyTensor:$output1,
536      AnyTensor:$output2,
537      AnyTensor:$output3
538    );
539}
540
541def : Pattern<(ThreeResultOp:$results ...),
542              [(... $results__0), ..., (... $results__2), ...]>;
543```
544
545In the above pattern we bind `$results` to all the results generated by
546`ThreeResultOp` and references its `$output1` and `$output3` later in the result
547patterns.
548
549We can also bind a symbol and reference one of its specific result at the same
550time, which is typically useful when generating multi-result ops:
551
552```tablegen
553// TwoResultOp has similar definition as ThreeResultOp, but only has two
554// results.
555
556def : Pattern<(TwoResultOp ...),
557              [(ThreeResultOp:$results__2, ...),
558               (replaceWithValue $results__0)]>;
559```
560
561In the above, we created a `ThreeResultOp` and bind `results` to its results,
562and uses its last result (`$output3`) and first result (`$output1`) to replace
563the `TwoResultOp`'s two results, respectively.
564
565#### Replacing multi-result ops
566
567The above example also shows how to replace a matched multi-result op.
568
569To replace an `N`-result op, the result patterns must generate at least `N`
570declared values (see [Declared vs. actual value](#declared-vs-actual-value) for
571definition). If there are more than `N` declared values generated, only the last
572`N` declared values will be used to replace the matched op. Note that because of
573the existence of multi-result op, one result pattern **may** generate multiple
574declared values. So it means we do not necessarily need `N` result patterns to
575replace an `N`-result op. For example, to replace an op with three results, you
576can have
577
578```tablegen
579// ThreeResultOp/TwoResultOp/OneResultOp generates three/two/one result(s),
580// respectively.
581
582// Replace each result with a result generated from an individual op.
583def : Pattern<(ThreeResultOp ...),
584              [(OneResultOp ...), (OneResultOp ...), (OneResultOp ...)]>;
585
586// Replace the first two results with two results generated from the same op.
587def : Pattern<(ThreeResultOp ...),
588              [(TwoResultOp ...), (OneResultOp ...)]>;
589
590// Replace all three results with three results generated from the same op.
591def : Pat<(ThreeResultOp ...), (ThreeResultOp ...)>;
592
593def : Pattern<(ThreeResultOp ...),
594              [(AuxiliaryOp ...), (ThreeResultOp ...)]>;
595```
596
597But using a single op to serve as both auxiliary op and replacement op is
598forbidden, i.e., the following is not allowed because that the first
599`TwoResultOp` generates two results but only the second result is used for
600replacing the matched op's result:
601
602```tablegen
603def : Pattern<(ThreeResultOp ...),
604              [(TwoResultOp ...), (TwoResultOp ...)]>;
605```
606
607### Supporting variadic ops
608
609#### Declared vs. actual value
610
611Before going into details on variadic op support, we need to define a few terms
612regarding an op's values.
613
614*   *Value*: either an operand or a result
615*   *Declared operand/result/value*: an operand/result/value statically declared
616    in ODS of the op
617*   *Actual operand/result/value*: an operand/result/value of an op instance at
618    runtime
619
620The above terms are needed because ops can have multiple results, and some of
621the results can also be variadic. For example,
622
623```tablegen
624def MultiVariadicOp : Op<"multi_variadic_op"> {
625    let arguments = (ins
626      AnyTensor:$input1,
627      Variadic<AnyTensor>:$input2,
628      AnyTensor:$input3
629    );
630
631    let results = (outs
632      AnyTensor:$output1,
633      Variadic<AnyTensor>:$output2,
634      AnyTensor:$output3
635    );
636}
637```
638
639We say the above op has 3 declared operands and 3 declared results. But at
640runtime, an instance can have 3 values corresponding to `$input2` and 2 values
641correspond to `$output2`; we say it has 5 actual operands and 4 actual results.
642A variadic operand/result is a considered as a declared value that can
643correspond to multiple actual values.
644
645[TODO]
646
647### Supplying additional constraints
648
649Constraints can be placed on op arguments when matching. But sometimes we need
650to also place constraints on the matched op's results or sometimes need to limit
651the matching with some constraints that cover both the arguments and the
652results. The third parameter to `Pattern` (and `Pat`) is for this purpose.
653
654For example, we can write
655
656```tablegen
657def HasNoUseOf: Constraint<CPred<"$_self.use_empty()">, "has no use">;
658
659def HasSameElementType : Constraint<
660    CPred<"$0.cast<ShapedType>().getElementType() == "
661          "$1.cast<ShapedType>().getElementType()">,
662    "has same element type">;
663
664def : Pattern<(TwoResultOp:$results $input),
665              [(...), (...)],
666              [(F32Tensor:$results__0), (HasNoUseOf:$results__1),
667               (HasSameElementShape $results__0, $input)]>;
668```
669
670You can
671
672*   Use normal `TypeConstraint`s on previous bound symbols (the first result of
673    `TwoResultOp` must be a float tensor);
674*   Define new `Constraint` for previous bound symbols (the second result of
675    `TwoResultOp` must has no use);
676*   Apply constraints on multiple bound symbols (`$input` and `TwoResultOp`'s
677    first result must have the same element type).
678
679### Adjusting benefits
680
681The benefit of a `Pattern` is an integer value indicating the benefit of
682matching the pattern. It determines the priorities of patterns inside the
683pattern rewrite driver. A pattern with a higher benefit is applied before one
684with a lower benefit.
685
686In DRR, a rule is set to have a benefit of the number of ops in the source
687pattern. This is based on the heuristics and assumptions that:
688
689*   Larger matches are more beneficial than smaller ones.
690*   If a smaller one is applied first the larger one may not apply anymore.
691
692The fourth parameter to `Pattern` (and `Pat`) allows to manually tweak a
693pattern's benefit. Just supply `(addBenefit N)` to add `N` to the benefit value.
694
695## Rewrite directives
696
697### `location`
698
699By default the C++ pattern expanded from a DRR pattern uses the fused location
700of all source ops as the location for all generated ops. This is not always the
701best location mapping relationship. For such cases, DRR provides the `location`
702directive to provide finer control.
703
704`location` is of the following syntax:
705
706```tablegen
707(location $symbol0, $symbol1, ...)
708```
709
710where all `$symbol` should be bound previously in the pattern and one optional
711string may be specified as an attribute. The following locations are created:
712
713*   If only 1 symbol is specified then that symbol's location is used,
714*   If multiple are specified then a fused location is created;
715*   If no symbol is specified then string must be specified and a NamedLoc is
716    created instead;
717
718`location` must be used as a trailing argument to an op creation. For example,
719
720```tablegen
721def : Pat<(LocSrc1Op:$src1 (LocSrc2Op:$src2 ...),
722          (LocDst1Op (LocDst2Op ..., (location $src2)), (location "outer"))>;
723```
724
725In the above pattern, the generated `LocDst2Op` will use the matched location of
726`LocSrc2Op` while the root `LocDst1Op` node will used the named location
727`outer`.
728
729### `replaceWithValue`
730
731The `replaceWithValue` directive is used to eliminate a matched op by replacing
732all of its uses with a captured value. It is of the following syntax:
733
734```tablegen
735(replaceWithValue $symbol)
736```
737
738where `$symbol` should be a symbol bound previously in the pattern.
739
740For example,
741
742```tablegen
743def : Pat<(Foo $input), (replaceWithValue $input)>;
744```
745
746The above pattern removes the `Foo` and replaces all uses of `Foo` with
747`$input`.
748
749### `returnType`
750
751The `returnType` directive allows patterns to directly specify return types for
752replacement ops that lack return type inference with op traits or user-defined
753builders with return type deduction.
754
755The `returnType` directive must be used as a trailing argument to a node
756describing a replacement op. The directive comes in three forms:
757
758*   `(returnType $value)`: copy the type of the operand or result bound to
759    `value`.
760*   `(returnType "$_builder.getI32Type()")`: a string literal embedding C++. The
761    embedded snippet is expected to return a `Type` or a `TypeRange`.
762*   `(returnType (NativeCodeCall<"myFunc($0)"> $value))`: a DAG node with a
763    native code call that can be passed any bound variables arguments.
764
765Specify multiple return types with a mix of any of the above. Example:
766
767```tablegen
768def : Pat<(SourceOp $arg0, $arg1),
769          (OpA $arg0, (TwoResultOp:$res__1 $arg1,
770                         (returnType $arg1, "$_builder.getI64Type()")))>;
771```
772
773Explicitly-specified return types will take precedence over return types
774inferred from op traits or user-defined builders. The return types of values
775replacing root op results cannot be overridden.
776
777### `either`
778
779The `either` directive is used to specify the operands may be matched in either
780order.
781
782```tablegen
783def : Pat<(TwoArgOp (either $firstArg, (AnOp $secondArg))),
784          (...)>;
785```
786
787The above pattern will accept either `"test.TwoArgOp"(%I32Arg, %AnOpArg)` and
788`"test.TwoArgOp"(%AnOpArg, %I32Arg)`.
789
790Only operand is supported with `either` and note that an operation with
791`Commutative` trait doesn't imply that it'll have the same behavior than
792`either` while pattern matching.
793
794## Debugging Tips
795
796### Run `mlir-tblgen` to see the generated content
797
798TableGen syntax sometimes can be obscure; reading the generated content can be a
799very helpful way to understand and debug issues. To build `mlir-tblgen`, run
800`cmake --build . --target mlir-tblgen` in your build directory and find the
801`mlir-tblgen` binary in the `bin/` subdirectory. All the supported generators
802can be found via `mlir-tblgen --help`.
803
804To see the generated code, invoke `mlir-tblgen` with a specific generator by
805providing include paths via `-I`. For example,
806
807```sh
808# To see all the C++ pattern rewrite classes
809mlir-tblgen --gen-rewriters -I /path/to/mlir/include /path/to/input/td/file
810```
811
812### Compilation error: no matching member function for call to 'build'
813
814This is because DRR is failing to call a `build()` method with result type
815deduction ability. See [building operations](#building-operations) for more
816details.
817
818[TableGen]: https://llvm.org/docs/TableGen/index.html
819[OpBase]: https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/IR/OpBase.td
820