diff --git a/mlir/docs/PatternRewriter.md b/mlir/docs/PatternRewriter.md --- a/mlir/docs/PatternRewriter.md +++ b/mlir/docs/PatternRewriter.md @@ -186,6 +186,15 @@ `RewritePattern::create` utility method. This method ensures that the pattern is properly initialized and prepared for insertion into a `RewritePatternSet`. +## Defining Patterns with PDLL + +In addition to the C++ pattern definitions detailed in the +[section above](#defining-patterns), MLIR also provides a custom language for +defining patterns declaratively via PDLL. PDLL is a language built from the +ground up for supporting MLIR pattern rewrites, with a focus on expressability +and developer tooling. See the main [PDLL documentation](PDLL.md) for details +on defining patterns this way. + ## Pattern Rewriter A `PatternRewriter` is a special class that allows for a pattern to communicate diff --git a/mlir/docs/Tutorials/Toy/Ch-3.md b/mlir/docs/Tutorials/Toy/Ch-3.md --- a/mlir/docs/Tutorials/Toy/Ch-3.md +++ b/mlir/docs/Tutorials/Toy/Ch-3.md @@ -16,11 +16,10 @@ [Generic DAG Rewriter](../../PatternRewriter.md). There are two methods that can be used to implement pattern-match -transformations: 1. Imperative, C++ pattern-match and rewrite 2. Declarative, -rule-based pattern-match and rewrite using table-driven -[Declarative Rewrite Rules](../../DeclarativeRewrites.md) (DRR). Note that the -use of DRR requires that the operations be defined using ODS, as described in -[Chapter 2](Ch-2.md). +transformations: + +1. Imperatively: C++ pattern-match and rewrite +1. Declaratively: Pattern-match and rewrite using [PDLL](../../PDLL.md). ## Optimize Transpose using C++ style pattern-match and rewrite @@ -108,8 +107,8 @@ [canonicalization pass](../../Canonicalization.md) applies transformations defined by operations in a greedy, iterative manner. To ensure that the canonicalization pass applies our new transform, we set -[hasCanonicalizer = 1](../../OpDefinitions.md/#hascanonicalizer) and register the -pattern with the canonicalization framework. +[hasCanonicalizer = 1](../../OpDefinitions.md/#hascanonicalizer) and register +the pattern with the canonicalization framework. ```c++ // Register our patterns for rewrite by the Canonicalization framework. @@ -128,8 +127,9 @@ pm.addNestedPass(mlir::createCanonicalizerPass()); ``` -Finally, we can run `toyc-ch3 test/Examples/Toy/Ch3/transpose_transpose.toy --emit=mlir -opt` and observe our pattern in action: +Finally, we can run +`toyc-ch3 test/Examples/Toy/Ch3/transpose_transpose.toy -emit=mlir -opt` and +observe our pattern in action: ```mlir toy.func @transpose_transpose(%arg0: tensor<*xf64>) -> tensor<*xf64> { @@ -160,60 +160,109 @@ Perfect! No `transpose` operation is left - the code is optimal. -In the next section, we use DRR for pattern match optimizations associated with +In the next section, we use PDLL for pattern match optimizations associated with the Reshape op. -## Optimize Reshapes using DRR +## Optimize Reshapes using PDLL -Declarative, rule-based pattern-match and rewrite (DRR) is an operation -DAG-based declarative rewriter that provides a table-based syntax for -pattern-match and rewrite rules: +PDLL provides a declarative language with which to define our pattern rewrites, +with a syntax designed to mimic the IR we want to transform. A redundant reshape +optimization similar to SimplifyRedundantTranspose can be expressed more simply +using PDLL as follows: -```tablegen -class Pattern< - dag sourcePattern, list resultPatterns, - list additionalConstraints = [], - dag benefitsAdded = (addBenefit 0)>; +```pdll +#include "toy/Ops.td" + +// Reshape(Reshape(x)) = Reshape(x) +Pattern ReshapeReshapeOptPattern { + replace op(op(arg: Value)) + with op(arg); +} ``` -A redundant reshape optimization similar to SimplifyRedundantTranspose can be -expressed more simply using DRR as follows: +There are a few pieces to unpack here, let's walk through them. Firstly, at the +top of the pattern we include our Toy operation definitions. This isn't strictly +necessary, but it gives PDLL access to our ODS operations, interfaces, and more. +This allows for more powerful error handling, tooling, and more. -```tablegen +For the pattern itself, each `op` represents an +["Operation Expression"](../../PDLL.md#operation-expression), which is what we +use to describe the IR we are matching and to define what operations we want to +create. The structure of these expressions matches nearly 1-1 with the generic +format of our toy operations, with a little bit of sugar on top. The +`arg: Value` represents an +[inline variable definition](../../PDLL.md#inline-variable-definition) of a +Value, which in this case is an unknown input operand to the inner reshape. + +The structure of the pattern is a bit more clear if we outline each step into +separate variables: + +```pdll // Reshape(Reshape(x)) = Reshape(x) -def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), - (ReshapeOp $arg)>; +Pattern ReshapeReshapeOptPattern { + let arg: Value; + let innerReshape = op(arg); + let reshape = op(innerReshape); + replace reshape with op(arg); +} ``` -The automatically generated C++ code corresponding to each of the DRR patterns -can be found under `path/to/BUILD/tools/mlir/examples/toy/Ch3/ToyCombine.inc`. - -DRR also provides a method for adding argument constraints when the -transformation is conditional on some properties of the arguments and results. -An example is a transformation that eliminates reshapes when they are redundant, -i.e. when the input and output shapes are identical. +Let's compare that to the .mlir form of what we want to match: -```tablegen -def TypesAreIdentical : Constraint>; -def RedundantReshapeOptPattern : Pat< - (ReshapeOp:$res $arg), (replaceWithValue $arg), - [(TypesAreIdentical $res, $arg)]>; +```mlir +// arg is some value defined elsewhere, we don't care where it comes from +// for this pattern. +%arg = ... +%innerReshape = "toy.reshape"(%arg) : (tensor<...>) -> (tensor<...>) +%reshape = "toy.reshape"(%innerReshape) : (tensor<...>) -> (tensor<...>) ``` -Some optimizations may require additional transformations on instruction -arguments. This is achieved using NativeCodeCall, which allows for more complex -transformations either by calling into a C++ helper function or by using inline -C++. An example of such an optimization is FoldConstantReshape, where we -optimize Reshape of a constant value by reshaping the constant in place and -eliminating the reshape operation. +You can likely see now that our pattern in PDLL is mostly just a sugared version +of the exact IR that we want to match. -```tablegen -def ReshapeConstant : NativeCodeCall<"$0.reshape(($1.getType()).cast())">; -def FoldConstantReshapeOptPattern : Pat< - (ReshapeOp:$res (ConstantOp $arg)), - (ConstantOp (ReshapeConstant $arg, $res))>; +With our PDLL pattern defined, we can generate some corresponding C++ code that +we can use within our toy code. The automatically generated C++ code +corresponding to each of the PDLL patterns can be found under +`path/to/BUILD/tools/mlir/examples/toy/Ch3/ToyCombine.inc`. + +Outside of our simple pattern above, PDLL provides many more power capabilities +layered on top. For example below is a transformation that eliminates reshapes +when they are redundant, i.e. when the input and output shapes are identical. + +```pdll +Pattern RedundantReshapeOptPattern { + replace op(arg: Value) -> (type) + with arg; +} ``` +Each use of a variable within the match portion of the PDLL pattern is +constrained to be equal, thus in the above pattern we constrain the input and +result type to be the same `type`. + +Each pattern above has been written using pure PDLL, but some optimizations may +require more complex logic that PDLL can't natively support. In these cases, we +can define custom constraints and rewrites that call into a C++ helper function +or by inline C++. An example of such an optimization is FoldConstantReshape, +where we optimize Reshape of a constant value by reshaping the constant in place +and eliminating the reshape operation. + +```pdll +Rewrite ReshapeConstant(attr: F64ElementsAttr, type: F64Tensor) -> Attr [{ + return attr.reshape(type); +}]; +Pattern FoldConstantReshapeOptPattern { + replace op(op {value = cstValue: Attr}) -> (result: Type) + with op {value = ReshapeConstant(cstValue, result)}; +} +``` + +In the above, we define a new rewrite function that contains a bit of inline C++ +to reshape the attribute value of the input constant. When defining the +arguments to the rewrite, we use the exact same constraints as we do in ODS to +allow for the inline C++ code to interact with the same C++ types that our +operations do. + We demonstrate these reshape optimizations using the following trivial_reshape.toy program: @@ -239,8 +288,9 @@ } ``` -We can try to run `toyc-ch3 test/Examples/Toy/Ch3/trivial_reshape.toy -emit=mlir --opt` and observe our pattern in action: +We can try to run +`toyc-ch3 test/Examples/Toy/Ch3/trivial_reshape.toy -emit=mlir -opt` and observe +our pattern in action: ```mlir module { @@ -254,8 +304,13 @@ As expected, no reshape operations remain after canonicalization. -Further details on the declarative rewrite method can be found at -[Table-driven Declarative Rewrite Rule (DRR)](../../DeclarativeRewrites.md). +See the main documentation of [PDLL](../../PDLL.md) for much more information on +what it can do. Also checkout the +[PDLL language server](../../Tools/MLIRLSP.md#pdll-lsp-language-server--mlir-pdll-lsp-server), +which paired with an IDE like +[VSCode](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-mlir), +gives you many modern programming language features when interacting with PDLL; +such as code completion, go-to-definition, and more. In this chapter, we saw how to use certain core transformations through always available hooks. In the [next chapter](Ch-4.md), we will see how to use generic diff --git a/mlir/examples/toy/Ch3/CMakeLists.txt b/mlir/examples/toy/Ch3/CMakeLists.txt --- a/mlir/examples/toy/Ch3/CMakeLists.txt +++ b/mlir/examples/toy/Ch3/CMakeLists.txt @@ -6,9 +6,10 @@ Support ) -set(LLVM_TARGET_DEFINITIONS mlir/ToyCombine.td) -mlir_tablegen(ToyCombine.inc -gen-rewriters) -add_public_tablegen_target(ToyCh3CombineIncGen) +add_mlir_pdll_library(ToyCh3CombineIncGen + mlir/ToyCombine.pdll + ToyCombine.inc +) add_toy_chapter(toyc-ch3 toyc.cpp diff --git a/mlir/examples/toy/Ch3/include/toy/Ops.td b/mlir/examples/toy/Ch3/include/toy/Ops.td --- a/mlir/examples/toy/Ch3/include/toy/Ops.td +++ b/mlir/examples/toy/Ch3/include/toy/Ops.td @@ -22,6 +22,7 @@ def Toy_Dialect : Dialect { let name = "toy"; let cppNamespace = "::mlir::toy"; + let dependentDialects = ["pdl::PDLDialect", "pdl_interp::PDLInterpDialect"]; } // Base class for toy dialect operations. This operation inherits from the base diff --git a/mlir/examples/toy/Ch3/mlir/Dialect.cpp b/mlir/examples/toy/Ch3/mlir/Dialect.cpp --- a/mlir/examples/toy/Ch3/mlir/Dialect.cpp +++ b/mlir/examples/toy/Ch3/mlir/Dialect.cpp @@ -13,6 +13,8 @@ #include "toy/Dialect.h" +#include "mlir/Dialect/PDL/IR/PDL.h" +#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/FunctionImplementation.h" diff --git a/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp b/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp --- a/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp +++ b/mlir/examples/toy/Ch3/mlir/ToyCombine.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Parser/Parser.h" #include "toy/Dialect.h" #include using namespace mlir; diff --git a/mlir/examples/toy/Ch5/mlir/ToyCombine.td b/mlir/examples/toy/Ch3/mlir/ToyCombine.pdll rename from mlir/examples/toy/Ch5/mlir/ToyCombine.td rename to mlir/examples/toy/Ch3/mlir/ToyCombine.pdll --- a/mlir/examples/toy/Ch5/mlir/ToyCombine.td +++ b/mlir/examples/toy/Ch3/mlir/ToyCombine.pdll @@ -1,4 +1,4 @@ -//===- ToyCombine.td - Pattern Match Optimizations for Toy -*- tablegen -*-===// +//===- ToyCombine.pdll - Pattern Match Optimizations for Toy ----*- pdll -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,32 +6,22 @@ // //===----------------------------------------------------------------------===// // -// Defines language-specific pattern match optimizations for Toy using -// Declarative Rewrite Rules (DRR) specified using TableGen records. +// This file defins language-specific pattern match optimizations for Toy using +// PDLL. // //===----------------------------------------------------------------------===// -#ifndef TOY_COMBINE -#define TOY_COMBINE - -include "mlir/IR/PatternBase.td" -include "toy/Ops.td" - -/// Note: The DRR definition used for defining patterns is shown below: -/// -/// class Pattern< -/// dag sourcePattern, list resultPatterns, -/// list additionalConstraints = [], -/// dag benefitsAdded = (addBenefit 0) -/// >; +#include "toy/Ops.td" //===----------------------------------------------------------------------===// // Basic Pattern-Match and Rewrite //===----------------------------------------------------------------------===// // Reshape(Reshape(x)) = Reshape(x) -def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), - (ReshapeOp $arg)>; +Pattern ReshapeReshapeOptPattern { + replace op(op(arg: Value)) + with op(arg); +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite using Native Code Call @@ -41,23 +31,20 @@ // C++ and C++ helper functions. // Reshape(Constant(x)) = x' -def ReshapeConstant : - NativeCodeCall<"$0.reshape(($1.getType()).cast())">; -def FoldConstantReshapeOptPattern : Pat< - (ReshapeOp:$res (ConstantOp $arg)), - (ConstantOp (ReshapeConstant $arg, $res))>; +Rewrite ReshapeConstant(attr: F64ElementsAttr, type: F64Tensor) -> Attr [{ + return attr.reshape(type); +}]; +Pattern FoldConstantReshapeOptPattern { + replace op(op {value = cst: Attr}) -> (res: Type) + with op {value = ReshapeConstant(cst, res)}; +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite with Constraints //===----------------------------------------------------------------------===// -// DRR allows for constraint checking when the transformation is conditional -// on operand properties. - // Reshape(x) = x, where input and output shapes are identical -def TypesAreIdentical : Constraint>; -def RedundantReshapeOptPattern : Pat< - (ReshapeOp:$res $arg), (replaceWithValue $arg), - [(TypesAreIdentical $res, $arg)]>; - -#endif // TOY_COMBINE +Pattern RedundantReshapeOptPattern { + replace op(arg: Value) -> (type) + with arg; +} diff --git a/mlir/examples/toy/Ch4/CMakeLists.txt b/mlir/examples/toy/Ch4/CMakeLists.txt --- a/mlir/examples/toy/Ch4/CMakeLists.txt +++ b/mlir/examples/toy/Ch4/CMakeLists.txt @@ -6,9 +6,10 @@ Support ) -set(LLVM_TARGET_DEFINITIONS mlir/ToyCombine.td) -mlir_tablegen(ToyCombine.inc -gen-rewriters) -add_public_tablegen_target(ToyCh4CombineIncGen) +add_mlir_pdll_library(ToyCh4CombineIncGen + mlir/ToyCombine.pdll + ToyCombine.inc +) add_toy_chapter(toyc-ch4 toyc.cpp diff --git a/mlir/examples/toy/Ch4/include/toy/Ops.td b/mlir/examples/toy/Ch4/include/toy/Ops.td --- a/mlir/examples/toy/Ch4/include/toy/Ops.td +++ b/mlir/examples/toy/Ch4/include/toy/Ops.td @@ -25,6 +25,7 @@ def Toy_Dialect : Dialect { let name = "toy"; let cppNamespace = "::mlir::toy"; + let dependentDialects = ["pdl::PDLDialect", "pdl_interp::PDLInterpDialect"]; } // Base class for toy dialect operations. This operation inherits from the base diff --git a/mlir/examples/toy/Ch4/mlir/Dialect.cpp b/mlir/examples/toy/Ch4/mlir/Dialect.cpp --- a/mlir/examples/toy/Ch4/mlir/Dialect.cpp +++ b/mlir/examples/toy/Ch4/mlir/Dialect.cpp @@ -13,6 +13,8 @@ #include "toy/Dialect.h" +#include "mlir/Dialect/PDL/IR/PDL.h" +#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/FunctionImplementation.h" diff --git a/mlir/examples/toy/Ch4/mlir/ToyCombine.cpp b/mlir/examples/toy/Ch4/mlir/ToyCombine.cpp --- a/mlir/examples/toy/Ch4/mlir/ToyCombine.cpp +++ b/mlir/examples/toy/Ch4/mlir/ToyCombine.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Parser/Parser.h" #include "toy/Dialect.h" #include using namespace mlir; diff --git a/mlir/examples/toy/Ch3/mlir/ToyCombine.td b/mlir/examples/toy/Ch4/mlir/ToyCombine.pdll rename from mlir/examples/toy/Ch3/mlir/ToyCombine.td rename to mlir/examples/toy/Ch4/mlir/ToyCombine.pdll --- a/mlir/examples/toy/Ch3/mlir/ToyCombine.td +++ b/mlir/examples/toy/Ch4/mlir/ToyCombine.pdll @@ -1,4 +1,4 @@ -//===- ToyCombine.td - Pattern Match Optimizations for Toy -*- tablegen -*-===// +//===- ToyCombine.pdll - Pattern Match Optimizations for Toy ----*- pdll -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,32 +6,22 @@ // //===----------------------------------------------------------------------===// // -// Defines language-specific pattern match optimizations for Toy using -// Declarative Rewrite Rules (DRR) specified using TableGen records. +// This file defins language-specific pattern match optimizations for Toy using +// PDLL. // //===----------------------------------------------------------------------===// -#ifndef TOY_COMBINE -#define TOY_COMBINE - -include "mlir/IR/PatternBase.td" -include "toy/Ops.td" - -/// Note: The DRR definition used for defining patterns is shown below: -/// -/// class Pattern< -/// dag sourcePattern, list resultPatterns, -/// list additionalConstraints = [], -/// dag benefitsAdded = (addBenefit 0) -/// >; +#include "toy/Ops.td" //===----------------------------------------------------------------------===// // Basic Pattern-Match and Rewrite //===----------------------------------------------------------------------===// // Reshape(Reshape(x)) = Reshape(x) -def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), - (ReshapeOp $arg)>; +Pattern ReshapeReshapeOptPattern { + replace op(op(arg: Value)) + with op(arg); +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite using Native Code Call @@ -41,23 +31,20 @@ // C++ and C++ helper functions. // Reshape(Constant(x)) = x' -def ReshapeConstant : - NativeCodeCall<"$0.reshape(($1.getType()).cast())">; -def FoldConstantReshapeOptPattern : Pat< - (ReshapeOp:$res (ConstantOp $arg)), - (ConstantOp (ReshapeConstant $arg, $res))>; +Rewrite ReshapeConstant(attr: F64ElementsAttr, type: F64Tensor) -> Attr [{ + return attr.reshape(type); +}]; +Pattern FoldConstantReshapeOptPattern { + replace op(op {value = cst: Attr}) -> (res: Type) + with op {value = ReshapeConstant(cst, res)}; +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite with Constraints //===----------------------------------------------------------------------===// -// DRR allows for constraint checking when the transformation is conditional -// on operand properties. - // Reshape(x) = x, where input and output shapes are identical -def TypesAreIdentical : Constraint>; -def RedundantReshapeOptPattern : Pat< - (ReshapeOp:$res $arg), (replaceWithValue $arg), - [(TypesAreIdentical $res, $arg)]>; - -#endif // TOY_COMBINE +Pattern RedundantReshapeOptPattern { + replace op(arg: Value) -> (type) + with arg; +} diff --git a/mlir/examples/toy/Ch5/CMakeLists.txt b/mlir/examples/toy/Ch5/CMakeLists.txt --- a/mlir/examples/toy/Ch5/CMakeLists.txt +++ b/mlir/examples/toy/Ch5/CMakeLists.txt @@ -6,9 +6,10 @@ Support ) -set(LLVM_TARGET_DEFINITIONS mlir/ToyCombine.td) -mlir_tablegen(ToyCombine.inc -gen-rewriters) -add_public_tablegen_target(ToyCh5CombineIncGen) +add_mlir_pdll_library(ToyCh5CombineIncGen + mlir/ToyCombine.pdll + ToyCombine.inc +) add_toy_chapter(toyc-ch5 toyc.cpp diff --git a/mlir/examples/toy/Ch5/include/toy/Ops.td b/mlir/examples/toy/Ch5/include/toy/Ops.td --- a/mlir/examples/toy/Ch5/include/toy/Ops.td +++ b/mlir/examples/toy/Ch5/include/toy/Ops.td @@ -25,6 +25,7 @@ def Toy_Dialect : Dialect { let name = "toy"; let cppNamespace = "::mlir::toy"; + let dependentDialects = ["pdl::PDLDialect", "pdl_interp::PDLInterpDialect"]; } // Base class for toy dialect operations. This operation inherits from the base diff --git a/mlir/examples/toy/Ch5/mlir/Dialect.cpp b/mlir/examples/toy/Ch5/mlir/Dialect.cpp --- a/mlir/examples/toy/Ch5/mlir/Dialect.cpp +++ b/mlir/examples/toy/Ch5/mlir/Dialect.cpp @@ -13,6 +13,8 @@ #include "toy/Dialect.h" +#include "mlir/Dialect/PDL/IR/PDL.h" +#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/FunctionImplementation.h" diff --git a/mlir/examples/toy/Ch5/mlir/ToyCombine.cpp b/mlir/examples/toy/Ch5/mlir/ToyCombine.cpp --- a/mlir/examples/toy/Ch5/mlir/ToyCombine.cpp +++ b/mlir/examples/toy/Ch5/mlir/ToyCombine.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Parser/Parser.h" #include "toy/Dialect.h" #include using namespace mlir; diff --git a/mlir/examples/toy/Ch6/mlir/ToyCombine.td b/mlir/examples/toy/Ch5/mlir/ToyCombine.pdll rename from mlir/examples/toy/Ch6/mlir/ToyCombine.td rename to mlir/examples/toy/Ch5/mlir/ToyCombine.pdll --- a/mlir/examples/toy/Ch6/mlir/ToyCombine.td +++ b/mlir/examples/toy/Ch5/mlir/ToyCombine.pdll @@ -1,4 +1,4 @@ -//===- ToyCombine.td - Pattern Match Optimizations for Toy -*- tablegen -*-===// +//===- ToyCombine.pdll - Pattern Match Optimizations for Toy ----*- pdll -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,32 +6,22 @@ // //===----------------------------------------------------------------------===// // -// Defines language-specific pattern match optimizations for Toy using -// Declarative Rewrite Rules (DRR) specified using TableGen records. +// This file defins language-specific pattern match optimizations for Toy using +// PDLL. // //===----------------------------------------------------------------------===// -#ifndef TOY_COMBINE -#define TOY_COMBINE - -include "mlir/IR/PatternBase.td" -include "toy/Ops.td" - -/// Note: The DRR definition used for defining patterns is shown below: -/// -/// class Pattern< -/// dag sourcePattern, list resultPatterns, -/// list additionalConstraints = [], -/// dag benefitsAdded = (addBenefit 0) -/// >; +#include "toy/Ops.td" //===----------------------------------------------------------------------===// // Basic Pattern-Match and Rewrite //===----------------------------------------------------------------------===// // Reshape(Reshape(x)) = Reshape(x) -def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), - (ReshapeOp $arg)>; +Pattern ReshapeReshapeOptPattern { + replace op(op(arg: Value)) + with op(arg); +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite using Native Code Call @@ -41,23 +31,20 @@ // C++ and C++ helper functions. // Reshape(Constant(x)) = x' -def ReshapeConstant : - NativeCodeCall<"$0.reshape(($1.getType()).cast())">; -def FoldConstantReshapeOptPattern : Pat< - (ReshapeOp:$res (ConstantOp $arg)), - (ConstantOp (ReshapeConstant $arg, $res))>; +Rewrite ReshapeConstant(attr: F64ElementsAttr, type: F64Tensor) -> Attr [{ + return attr.reshape(type); +}]; +Pattern FoldConstantReshapeOptPattern { + replace op(op {value = cst: Attr}) -> (res: Type) + with op {value = ReshapeConstant(cst, res)}; +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite with Constraints //===----------------------------------------------------------------------===// -// DRR allows for constraint checking when the transformation is conditional -// on operand properties. - // Reshape(x) = x, where input and output shapes are identical -def TypesAreIdentical : Constraint>; -def RedundantReshapeOptPattern : Pat< - (ReshapeOp:$res $arg), (replaceWithValue $arg), - [(TypesAreIdentical $res, $arg)]>; - -#endif // TOY_COMBINE +Pattern RedundantReshapeOptPattern { + replace op(arg: Value) -> (type) + with arg; +} diff --git a/mlir/examples/toy/Ch6/CMakeLists.txt b/mlir/examples/toy/Ch6/CMakeLists.txt --- a/mlir/examples/toy/Ch6/CMakeLists.txt +++ b/mlir/examples/toy/Ch6/CMakeLists.txt @@ -9,9 +9,10 @@ OrcJIT ) -set(LLVM_TARGET_DEFINITIONS mlir/ToyCombine.td) -mlir_tablegen(ToyCombine.inc -gen-rewriters) -add_public_tablegen_target(ToyCh6CombineIncGen) +add_mlir_pdll_library(ToyCh6CombineIncGen + mlir/ToyCombine.pdll + ToyCombine.inc +) add_toy_chapter(toyc-ch6 toyc.cpp diff --git a/mlir/examples/toy/Ch6/include/toy/Ops.td b/mlir/examples/toy/Ch6/include/toy/Ops.td --- a/mlir/examples/toy/Ch6/include/toy/Ops.td +++ b/mlir/examples/toy/Ch6/include/toy/Ops.td @@ -25,6 +25,7 @@ def Toy_Dialect : Dialect { let name = "toy"; let cppNamespace = "::mlir::toy"; + let dependentDialects = ["pdl::PDLDialect", "pdl_interp::PDLInterpDialect"]; } // Base class for toy dialect operations. This operation inherits from the base diff --git a/mlir/examples/toy/Ch6/mlir/Dialect.cpp b/mlir/examples/toy/Ch6/mlir/Dialect.cpp --- a/mlir/examples/toy/Ch6/mlir/Dialect.cpp +++ b/mlir/examples/toy/Ch6/mlir/Dialect.cpp @@ -13,6 +13,8 @@ #include "toy/Dialect.h" +#include "mlir/Dialect/PDL/IR/PDL.h" +#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/FunctionImplementation.h" diff --git a/mlir/examples/toy/Ch6/mlir/ToyCombine.cpp b/mlir/examples/toy/Ch6/mlir/ToyCombine.cpp --- a/mlir/examples/toy/Ch6/mlir/ToyCombine.cpp +++ b/mlir/examples/toy/Ch6/mlir/ToyCombine.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Parser/Parser.h" #include "toy/Dialect.h" #include using namespace mlir; diff --git a/mlir/examples/toy/Ch4/mlir/ToyCombine.td b/mlir/examples/toy/Ch6/mlir/ToyCombine.pdll rename from mlir/examples/toy/Ch4/mlir/ToyCombine.td rename to mlir/examples/toy/Ch6/mlir/ToyCombine.pdll --- a/mlir/examples/toy/Ch4/mlir/ToyCombine.td +++ b/mlir/examples/toy/Ch6/mlir/ToyCombine.pdll @@ -1,4 +1,4 @@ -//===- ToyCombine.td - Pattern Match Optimizations for Toy -*- tablegen -*-===// +//===- ToyCombine.pdll - Pattern Match Optimizations for Toy ----*- pdll -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,32 +6,22 @@ // //===----------------------------------------------------------------------===// // -// Defines language-specific pattern match optimizations for Toy using -// Declarative Rewrite Rules (DRR) specified using TableGen records. +// This file defins language-specific pattern match optimizations for Toy using +// PDLL. // //===----------------------------------------------------------------------===// -#ifndef TOY_COMBINE -#define TOY_COMBINE - -include "mlir/IR/PatternBase.td" -include "toy/Ops.td" - -/// Note: The DRR definition used for defining patterns is shown below: -/// -/// class Pattern< -/// dag sourcePattern, list resultPatterns, -/// list additionalConstraints = [], -/// dag benefitsAdded = (addBenefit 0) -/// >; +#include "toy/Ops.td" //===----------------------------------------------------------------------===// // Basic Pattern-Match and Rewrite //===----------------------------------------------------------------------===// // Reshape(Reshape(x)) = Reshape(x) -def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), - (ReshapeOp $arg)>; +Pattern ReshapeReshapeOptPattern { + replace op(op(arg: Value)) + with op(arg); +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite using Native Code Call @@ -41,23 +31,20 @@ // C++ and C++ helper functions. // Reshape(Constant(x)) = x' -def ReshapeConstant : - NativeCodeCall<"$0.reshape(($1.getType()).cast())">; -def FoldConstantReshapeOptPattern : Pat< - (ReshapeOp:$res (ConstantOp $arg)), - (ConstantOp (ReshapeConstant $arg, $res))>; +Rewrite ReshapeConstant(attr: F64ElementsAttr, type: F64Tensor) -> Attr [{ + return attr.reshape(type); +}]; +Pattern FoldConstantReshapeOptPattern { + replace op(op {value = cst: Attr}) -> (res: Type) + with op {value = ReshapeConstant(cst, res)}; +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite with Constraints //===----------------------------------------------------------------------===// -// DRR allows for constraint checking when the transformation is conditional -// on operand properties. - // Reshape(x) = x, where input and output shapes are identical -def TypesAreIdentical : Constraint>; -def RedundantReshapeOptPattern : Pat< - (ReshapeOp:$res $arg), (replaceWithValue $arg), - [(TypesAreIdentical $res, $arg)]>; - -#endif // TOY_COMBINE +Pattern RedundantReshapeOptPattern { + replace op(arg: Value) -> (type) + with arg; +} diff --git a/mlir/examples/toy/Ch7/CMakeLists.txt b/mlir/examples/toy/Ch7/CMakeLists.txt --- a/mlir/examples/toy/Ch7/CMakeLists.txt +++ b/mlir/examples/toy/Ch7/CMakeLists.txt @@ -9,9 +9,10 @@ OrcJIT ) -set(LLVM_TARGET_DEFINITIONS mlir/ToyCombine.td) -mlir_tablegen(ToyCombine.inc -gen-rewriters) -add_public_tablegen_target(ToyCh7CombineIncGen) +add_mlir_pdll_library(ToyCh7CombineIncGen + mlir/ToyCombine.pdll + ToyCombine.inc +) add_toy_chapter(toyc-ch7 toyc.cpp diff --git a/mlir/examples/toy/Ch7/include/toy/Ops.td b/mlir/examples/toy/Ch7/include/toy/Ops.td --- a/mlir/examples/toy/Ch7/include/toy/Ops.td +++ b/mlir/examples/toy/Ch7/include/toy/Ops.td @@ -25,6 +25,7 @@ def Toy_Dialect : Dialect { let name = "toy"; let cppNamespace = "::mlir::toy"; + let dependentDialects = ["pdl::PDLDialect", "pdl_interp::PDLInterpDialect"]; // We set this bit to generate a declaration of the `materializeConstant` // method so that we can materialize constants for our toy operations. diff --git a/mlir/examples/toy/Ch7/mlir/Dialect.cpp b/mlir/examples/toy/Ch7/mlir/Dialect.cpp --- a/mlir/examples/toy/Ch7/mlir/Dialect.cpp +++ b/mlir/examples/toy/Ch7/mlir/Dialect.cpp @@ -13,6 +13,8 @@ #include "toy/Dialect.h" +#include "mlir/Dialect/PDL/IR/PDL.h" +#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/DialectImplementation.h" diff --git a/mlir/examples/toy/Ch7/mlir/ToyCombine.cpp b/mlir/examples/toy/Ch7/mlir/ToyCombine.cpp --- a/mlir/examples/toy/Ch7/mlir/ToyCombine.cpp +++ b/mlir/examples/toy/Ch7/mlir/ToyCombine.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Parser/Parser.h" #include "toy/Dialect.h" #include using namespace mlir; diff --git a/mlir/examples/toy/Ch5/mlir/ToyCombine.td b/mlir/examples/toy/Ch7/mlir/ToyCombine.pdll rename from mlir/examples/toy/Ch5/mlir/ToyCombine.td rename to mlir/examples/toy/Ch7/mlir/ToyCombine.pdll --- a/mlir/examples/toy/Ch5/mlir/ToyCombine.td +++ b/mlir/examples/toy/Ch7/mlir/ToyCombine.pdll @@ -1,4 +1,4 @@ -//===- ToyCombine.td - Pattern Match Optimizations for Toy -*- tablegen -*-===// +//===- ToyCombine.pdll - Pattern Match Optimizations for Toy ----*- pdll -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,32 +6,22 @@ // //===----------------------------------------------------------------------===// // -// Defines language-specific pattern match optimizations for Toy using -// Declarative Rewrite Rules (DRR) specified using TableGen records. +// This file defins language-specific pattern match optimizations for Toy using +// PDLL. // //===----------------------------------------------------------------------===// -#ifndef TOY_COMBINE -#define TOY_COMBINE - -include "mlir/IR/PatternBase.td" -include "toy/Ops.td" - -/// Note: The DRR definition used for defining patterns is shown below: -/// -/// class Pattern< -/// dag sourcePattern, list resultPatterns, -/// list additionalConstraints = [], -/// dag benefitsAdded = (addBenefit 0) -/// >; +#include "toy/Ops.td" //===----------------------------------------------------------------------===// // Basic Pattern-Match and Rewrite //===----------------------------------------------------------------------===// // Reshape(Reshape(x)) = Reshape(x) -def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), - (ReshapeOp $arg)>; +Pattern ReshapeReshapeOptPattern { + replace op(op(arg: Value)) + with op(arg); +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite using Native Code Call @@ -41,23 +31,20 @@ // C++ and C++ helper functions. // Reshape(Constant(x)) = x' -def ReshapeConstant : - NativeCodeCall<"$0.reshape(($1.getType()).cast())">; -def FoldConstantReshapeOptPattern : Pat< - (ReshapeOp:$res (ConstantOp $arg)), - (ConstantOp (ReshapeConstant $arg, $res))>; +Rewrite ReshapeConstant(attr: F64ElementsAttr, type: F64Tensor) -> Attr [{ + return attr.reshape(type); +}]; +Pattern FoldConstantReshapeOptPattern { + replace op(op {value = cst: Attr}) -> (res: Type) + with op {value = ReshapeConstant(cst, res)}; +} //===----------------------------------------------------------------------===// // Pattern-Match and Rewrite with Constraints //===----------------------------------------------------------------------===// -// DRR allows for constraint checking when the transformation is conditional -// on operand properties. - // Reshape(x) = x, where input and output shapes are identical -def TypesAreIdentical : Constraint>; -def RedundantReshapeOptPattern : Pat< - (ReshapeOp:$res $arg), (replaceWithValue $arg), - [(TypesAreIdentical $res, $arg)]>; - -#endif // TOY_COMBINE +Pattern RedundantReshapeOptPattern { + replace op(arg: Value) -> (type) + with arg; +} diff --git a/mlir/examples/toy/Ch7/mlir/ToyCombine.td b/mlir/examples/toy/Ch7/mlir/ToyCombine.td deleted file mode 100644 --- a/mlir/examples/toy/Ch7/mlir/ToyCombine.td +++ /dev/null @@ -1,63 +0,0 @@ -//===- ToyCombine.td - Pattern Match Optimizations for Toy -*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Defines language-specific pattern match optimizations for Toy using -// Declarative Rewrite Rules (DRR) specified using TableGen records. -// -//===----------------------------------------------------------------------===// - -#ifndef TOY_COMBINE -#define TOY_COMBINE - -include "mlir/IR/PatternBase.td" -include "toy/Ops.td" - -/// Note: The DRR definition used for defining patterns is shown below: -/// -/// class Pattern< -/// dag sourcePattern, list resultPatterns, -/// list additionalConstraints = [], -/// dag benefitsAdded = (addBenefit 0) -/// >; - -//===----------------------------------------------------------------------===// -// Basic Pattern-Match and Rewrite -//===----------------------------------------------------------------------===// - -// Reshape(Reshape(x)) = Reshape(x) -def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), - (ReshapeOp $arg)>; - -//===----------------------------------------------------------------------===// -// Pattern-Match and Rewrite using Native Code Call -//===----------------------------------------------------------------------===// - -// Native Code Calls may be used for more complex transformations using inline -// C++ and C++ helper functions. - -// Reshape(Constant(x)) = x' -def ReshapeConstant : - NativeCodeCall<"$0.reshape(($1.getType()).cast())">; -def FoldConstantReshapeOptPattern : Pat< - (ReshapeOp:$res (ConstantOp $arg)), - (ConstantOp (ReshapeConstant $arg, $res))>; - -//===----------------------------------------------------------------------===// -// Pattern-Match and Rewrite with Constraints -//===----------------------------------------------------------------------===// - -// DRR allows for constraint checking when the transformation is conditional -// on operand properties. - -// Reshape(x) = x, where input and output shapes are identical -def TypesAreIdentical : Constraint>; -def RedundantReshapeOptPattern : Pat< - (ReshapeOp:$res $arg), (replaceWithValue $arg), - [(TypesAreIdentical $res, $arg)]>; - -#endif // TOY_COMBINE diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h --- a/mlir/include/mlir/IR/PatternMatch.h +++ b/mlir/include/mlir/IR/PatternMatch.h @@ -12,6 +12,7 @@ #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/TypeName.h" namespace mlir {