[all-commits] [llvm/llvm-project] dca32a: [mlir][PDL] Add support for native constraints wit...
Matthias Gehre via All-commits
all-commits at lists.llvm.org
Thu Feb 29 22:30:00 PST 2024
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: dca32a3b594b3c91f9766a9312b5d82534910fa1
https://github.com/llvm/llvm-project/commit/dca32a3b594b3c91f9766a9312b5d82534910fa1
Author: Matthias Gehre <matthias.gehre at amd.com>
Date: 2024-03-01 (Fri, 01 Mar 2024)
Changed paths:
M mlir/include/mlir/Dialect/PDL/IR/PDLOps.td
M mlir/include/mlir/Dialect/PDLInterp/IR/PDLInterpOps.td
M mlir/include/mlir/IR/PDLPatternMatch.h.inc
M mlir/lib/Conversion/PDLToPDLInterp/PDLToPDLInterp.cpp
M mlir/lib/Conversion/PDLToPDLInterp/Predicate.h
M mlir/lib/Conversion/PDLToPDLInterp/PredicateTree.cpp
M mlir/lib/Dialect/PDL/IR/PDL.cpp
M mlir/lib/Rewrite/ByteCode.cpp
M mlir/lib/Tools/PDLL/Parser/Parser.cpp
M mlir/test/Conversion/PDLToPDLInterp/pdl-to-pdl-interp-matcher.mlir
A mlir/test/Conversion/PDLToPDLInterp/use-constraint-result.mlir
M mlir/test/Dialect/PDL/ops.mlir
M mlir/test/Rewrite/pdl-bytecode.mlir
M mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp
M mlir/test/lib/Rewrite/TestPDLByteCode.cpp
M mlir/test/mlir-pdll/Parser/constraint-failure.pdll
M mlir/test/mlir-pdll/Parser/constraint.pdll
M mlir/test/python/dialects/pdl_ops.py
Log Message:
-----------
[mlir][PDL] Add support for native constraints with results (#82760)
>From https://reviews.llvm.org/D153245
This adds support for native PDL (and PDLL) C++ constraints to return
results.
This is useful for situations where a pattern checks for certain
constraints of multiple interdependent attributes and computes a new
attribute value based on them. Currently, for such an example it is
required to escape to C++ during matching to perform the check and after
a successful match again escape to native C++ to perform the computation
during the rewriting part of the pattern. With this work we can do the
computation in C++ during matching and use the result in the rewriting
part of the pattern. Effectively this enables a choice in the trade-off
of memory consumption during matching vs recomputation of values.
This is an example of a situation where this is useful: We have two
operations with certain attributes that have interdependent constraints.
For instance `attr_foo: one_of [0, 2, 4, 8], attr_bar: one_of [0, 2, 4,
8]` and `attr_foo == attr_bar`. The pattern should only match if all
conditions are true. The new operation should be created with a new
attribute which is computed from the two matched attributes e.g.
`attr_baz = attr_foo * attr_bar`. For the check we already escape to
native C++ and have all values at hand so it makes sense to directly
compute the new attribute value as well:
```
Constraint checkAndCompute(attr0: Attr, attr1: Attr) -> Attr;
Pattern example with benefit(1) {
let foo = op<test.foo>() {attr = attr_foo : Attr};
let bar = op<test.bar>(foo) {attr = attr_bar : Attr};
let attr_baz = checkAndCompute(attr_foo, attr_bar);
rewrite bar with {
let baz = op<test.baz> {attr=attr_baz};
replace bar with baz;
};
}
```
To achieve this the following notable changes were necessary:
PDLL:
- Remove check in PDLL parser that prevented native constraints from
returning results
PDL:
- Change PDL definition of pdl.apply_native_constraint to allow variadic
results
PDL_interp:
- Change PDL_interp definition of pdl_interp.apply_constraint to allow
variadic results
PDLToPDLInterp Pass:
The input to the pass is an arbitrary number of PDL patterns. The pass
collects the predicates that are required to match all of the pdl
patterns and establishes an ordering that allows creation of a single
efficient matcher function to match all of them. Values that are matched
and possibly used in the rewriting part of a pattern are represented as
positions. This allows fusion and thus reusing a single position for
multiple matching patterns. Accordingly, we introduce
ConstraintPosition, which records the type and index of the result of
the constraint. The problem is for the corresponding value to be used in
the rewriting part of a pattern it has to be an input to the
pdl_interp.record_match operation, which is generated early during the
pass such that its surrounding block can be referred to by branching
operations. In consequence the value has to be materialized after the
original pdl.apply_native_constraint has been deleted but before we get
the chance to generate the corresponding pdl_interp.apply_constraint
operation. We solve this by emitting a placeholder value when a
ConstraintPosition is evaluated. These placeholder values (due to fusion
there may be multiple for one constraint result) are replaced later when
the actual pdl_interp.apply_constraint operation is created.
Changes since the phabricator review:
- Addressed all comments
- In particular, removed registerConstraintFunctionWithResults and
instead changed registerConstraintFunction so that contraint functions
always have results (empty by default)
- Thus we don't need to reuse `rewriteFunctions` to store constraint
functions with results anymore, and can instead use
`constraintFunctions`
- Perform a stable sort of ConstraintQuestion, so that
ConstraintQuestion appear before other ConstraintQuestion that use their
results.
- Don't create placeholders for pdl_interp::ApplyConstraintOp. Instead
generate the `pdl_interp::ApplyConstraintOp` before generating the
successor block.
- Fixed a test failure in the pdl python bindings
Original code by @martin-luecke
Co-authored-by: martin-luecke <martinpaul.luecke at amd.com>
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list