Add a transform that eliminates dead operations. This is useful after certain transforms (such as fusion) that create/clone new IR but leave the original IR in place.
Differential Revision: https://reviews.llvm.org/D155954
Applying the canonicalizer and CSE in an interleaved fashion is useful after bufferization (and maybe other transforms) to fold away self copies.
Differential Revision: https://reviews.llvm.org/D155933
* Rename op to `transform.get_parent_op`
* Match parents by "is isolated from above" and/or op name, or just the direct parent.
* Deduplication of result payload ops is optional.
Differential Revision: https://reviews.llvm.org/D154071
This op applies CSE to the targeted op. This is similar to `transform.apply_registered_pass "cse"`, but it retains handles in the body of the targeted op.
Differential Revision: https://reviews.llvm.org/D154099
Do not swap the Mappings when entering a region that is isolated from above. Simply push another Mappings struct to the stack and prevent invalid accesses during lookups.
Differential Revision: https://reviews.llvm.org/D153765
Wrapping a warning into a silenceable failure will result in the warning
being interpreted as an error, which it is not.
Reviewed By: nicolasvasilache
Differential Revision: https://reviews.llvm.org/D153546
Similar to operation handles, merging handles for other types can be useful to
avoid repetition of common transformations across a set of parameters.
For example, forming a list of static values for comparison rather than
comparing the parameters one at a time.
Reviewed By: ftynse
Differential Revision: https://reviews.llvm.org/D153240
All `apply` functions now have a `TransformRewriter &` parameter. This rewriter should be used to modify the IR. It has a `TrackingListener` attached and updates the internal handle-payload mappings based on rewrites.
Implementations no longer need to create their own `TrackingListener` and `IRRewriter`. Error checking is integrated into `applyTransform`. Tracking listener errors are reported only for ops with the `ReportTrackingListenerFailuresOpTrait` trait attached, allowing for a gradual migration. Furthermore, errors can be silenced with an op attribute.
Additional API will be added to `TransformRewriter` in subsequent revisions. This revision just adds an "empty" `TransformRewriter` class and updates all `apply` implementations.
Differential Revision: https://reviews.llvm.org/D152427
Add an extra check to make sure that transform IR is not getting modified by this op while it is being interpreted. This generally dangerous and we may want to enforce this for all transform ops that modify the payload in the future.
Users should generally try to apply patterns only to the piece of IR where it is needed (e.g., a matched function) and not the entire module (which may contain the transform IR).
This revision is in response to a crash in a downstream compiler that was caused by a dead `transform.structured.match` op that was removed by the GreedyPatternRewriteDriver's DCE while the enclosing sequence was being interpreted.
Differential Revision: https://reviews.llvm.org/D153113
A TransformRewriter (with attached TrackingListener) will be added to an interface method in a subsequent revision.
Differential Revision: https://reviews.llvm.org/D152426
When looking for replacement ops (`findReplacementOp`) distinguish between "no replacement could be found" and "this op should be dropped from the mapping". The latter case will be utilized in a subsequent revision when a payload op is mapped to a consumed handle.
Differential Revision: https://reviews.llvm.org/D152375
* Remove `transform::PatternRegistry`.
* Add a new op for each currently registered pattern set.
* Change names of vector dialect pattern selector ops, so that they are consistent with the remaining code base.
* Remove redundant `transform.vector.extract_address_computations` op.
Differential Revision: https://reviews.llvm.org/D152249
All vector transform ops are now `PatternDescriptorOpInterface` ops that merely select the patterns. The patterns are applied by the `apply_patterns` op. This is to ensure that ops are properly tracked. (TrackingListener is used in the implementation of `apply_patterns`.) Furthermore, handles are no longer invalidated when applying patterns in the vector tests.
Differential Revision: https://reviews.llvm.org/D152174
Patterns should be selected by adding ops that implement `PatternDescriptorOpInterface` to the region of `apply_pattern` ops. Such ops can have operands, allowing for pattern parameterization. The existing way of selecting patterns from the PatternRegistry is deprecated.
Differential Revision: https://reviews.llvm.org/D152167
Also support replacing payload ops with ConstantLike ops in the TrackingListener, even if the replacement op does not have the same name. (Not supported for ops with multiple results, as this would require splitting the handle.)
Differential Revision: https://reviews.llvm.org/D152127
Add a new transform op that applies patterns to a targeted payload op. Patterns can be registered by transform dialect extensions in a pattern registry.
Differential Revision: https://reviews.llvm.org/D151983
Add a new interface `FindPayloadReplacementOpInterface` to specify ops that should be skipped when looking for payload replacement ops. Such ops are typically metadata-only ops.
With this change, we no longer need to maintain a custom TrackingListener in the tensor dialect.
Note: `CastOpInterface` by itself is not sufficient. Some metadata-only ops such as "tensor.reshape" are not casts, and it would be incorrect for them to implement the `CastOpInterface`.
Differential Revision: https://reviews.llvm.org/D151888
The ability to add attributes to payload IR is useful functionality
independent of any dialect. This is added here through `transform.annotate`
by enabling attributes tied to a `TransformParamTypeInterface` (which
internally refers to an Attribute) to be added to a target operation by
name.
The AnnotateOp does not produce a new handle as no existing handles
should be affected by adding an attribute. Existing attributes on
the payload with the same name will be overwritten.
Differential Revision: https://reviews.llvm.org/D151689
The initial bring-up of the Transform dialect relied on PDL to provide
the default handle type (`!pdl.operation`) and the matching capability.
Both are now provided natively by the Transform dialect removing the
reason to have a hard dependency on the PDL dialect and its interpreter.
Move PDL-related transform operations into a separate extension.
This requires us to introduce a dialect state extension mechanism into
the Transform dialect so it no longer needs to know about PDL constraint
functions that may be injected by extensions similarly to operations and
types. This mechanism will be reused to connect pattern application
drivers and the Transform dialect.
This completes the restructuring of the Transform dialect to remove
overrilance on PDL.
Note to downstreams: flow that are using `!pdl.operation` with Transform
dialect operations will now require `transform::PDLExtension` to be
applied to the transform dialect in order to provide the transform
handle type interface for `!pdl.operation`.
Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D151104
Instead of returning an `ArrayRef<Operation *>`, return at iterator that skips ops that were erased/replaced while iterating over the payload ops.
This fixes an issue in conjuction with TrackingListener, where a tracked op was erased during the iteration. Elements may not be removed from an array while iterating over it; this invalidates the iterator.
When ops are erased/removed via `replacePayloadOp`, they are not immediately removed from the mappings data structure. Instead, they are set to `nullptr`. `nullptr`s are not enumerated by `getPayloadOps`. At the end of each transformation, `nullptr`s are removed from the mapping data structure.
Differential Revision: https://reviews.llvm.org/D149847
The TrackingListener was unnecessarily strict. Existing ops are now allowed when updating payload ops mappings due to `replaceOp` in the TrackingListener.
Differential Revision: https://reviews.llvm.org/D150429
The MLIR classes Type/Attribute/Operation/Op/Value support
cast/dyn_cast/isa/dyn_cast_or_null functionality through llvm's doCast
functionality in addition to defining methods with the same name.
This change begins the migration of uses of the method to the
corresponding function call as has been decided as more consistent.
Note that there still exist classes that only define methods directly,
such as AffineExpr, and this does not include work currently to support
a functional cast/isa call.
Context:
* https://mlir.llvm.org/deprecation/ at "Use the free function variants for dyn_cast/cast/isa/…"
* Original discussion at https://discourse.llvm.org/t/preferred-casting-style-going-forward/68443
Implementation:
This follows a previous patch that updated calls
`op.cast<T>()-> cast<T>(op)`. However some cases could not handle an
unprefixed `cast` call due to occurrences of variables named cast, or
occurring inside of class definitions which would resolve to the method.
All C++ files that did not work automatically with `cast<T>()` are
updated here to `llvm::cast` and similar with the intention that they
can be easily updated after the methods are removed through a
find-replace.
See https://github.com/llvm/llvm-project/compare/main...tpopp:llvm-project:tidy-cast-check
for the clang-tidy check that is used and then update printed
occurrences of the function to include `llvm::` before.
One can then run the following:
```
ninja -C $BUILD_DIR clang-tidy
run-clang-tidy -clang-tidy-binary=$BUILD_DIR/bin/clang-tidy -checks='-*,misc-cast-functions'\
-export-fixes /tmp/cast/casts.yaml mlir/*\
-header-filter=mlir/ -fix
rm -rf $BUILD_DIR/tools/mlir/**/*.inc
```
Differential Revision: https://reviews.llvm.org/D150348
Add options to handle cases where there are not enough or too many payload ops mapped to the given handle.
Differential Revision: https://reviews.llvm.org/D149955
* Rename to `SplitHandleOp`: it splits a single handle.
* Drop `num_result_handles` attribute: it is redundant and can be inferred from the number of results.
* Improve documentation and minor code cleanups.
Differential Revision: https://reviews.llvm.org/D149937
The `transform.split_handles` transform op has an edge case that is
supposed to propagate empty handle state to all resulting handles
regardless of their number. Actually set empty payload for them instead
of leaving them unset.
Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D149652
Add a set of transform operations into the "structured" extension of the
Transform dialect that allow one to select transformation targets more
specifically than the currently available matching. In particular, add
the mechanism for identifying the producers of operands (input and init
in destination-passing style) and users of results, as well as
mechanisms for reasoning about the shape of the iteration space.
Additionally, add several transform operations to manipulate parameters
that could be useful to implement more advanced selectors. Specifically,
new operations let one produce and compare parameter values to implement
shape-driven transformations.
New operations are placed in separate files to decrease compilation
time. Some relayering of the extension is necessary to avoid repeated
generation of enums.
Depends on D148013
Depends on D148014
Depends on D148015
Reviewed By: chelini
Differential Revision: https://reviews.llvm.org/D148017
Add a new transform op combinator that implements an "if-then-else"
style of mechanism for applying transformations. Its main purpose is to
serve as a higher-level driver when applying multiple transform scripts
to potentially overlapping pieces of the payload IR. This is similar to
how the various rewrite drivers operate in C++, but at a higher level
and with more declarative expressions. This is not intended to replace
existing pattern-based rewrites, but to to drive more complex
transformations that are exposed in the transform dialect and are too
complex to be expressed as simple declarative rewrites.
Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D148013
This revision adds additional "expensive-checks" checks to the transform dialect that detect the most common cases of:
* Missing `consumesHandle` side effects on transform ops.
* Patterns that remove operations but do not notify the transform dialect.
In essence, these additional checks are looking for dangling pointers to erased payload ops in the transform dialect state and crash the program execution (by dereferencing free'd memory) or triggering an assertion failure. It is recommended to run these extra checks with ASAN. Otherwise, certain failures may not be detected. The ASAN error message can also be used to find the faulty transform op/pattern.
This change also fixes a few faulty transform ops.
Differential Revision: https://reviews.llvm.org/D147447
Use the argument attribute mechanism for function-like operations to
annotate the arguments of named transform sequences as consuming or only
reading the handles passed as arguments. This makes it possible to
correctly specify handle invalidation for external named sequences by
requiring their declarations to always provide such annotations.
Additionally, these annotations remove the need to analyze the body of
a named sequence to understand its effects on the arguments. Make them
required for named sequences that are called from the same file, in
addition to external sequences.
Provide a convenience pass that infers annotations by analyzing bodies
of named sequences provided they are not called from the same file.
Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D147223
This change makes it possible to use a greedy pattern rewrite as part of a transform op, even if the transform op does not invalidate the target handle (in particular transform ops without `FunctionalStyleTransformOpTrait`) and the targeted op is not isolated from above.
The listener API allows us to track replacements of ops with values, but not ops with ops. Therefore, the TrackingListener is conservative: If an op is replaced with values that all have the same defining op and the defining op is of the same type as the original op, it is safe to assume that the op was replaced with an equivalent op. Otherwise, the op mapping is dropped. When this is not good enough, transforms can track values instead or provide a custom `findReplacementOp` function.
Differential Revision: https://reviews.llvm.org/D147039
Introduce support for external definitions of named sequences in the
transform dialect by letting the TransformInterpreterPassBase read a
"library" MLIR file. This file is expected to contain definitions for
named sequences that are only declared in the main transformation
script. This allows for sharing non-trivial transform combinations
without duplication.
This patch provides only the minimal plumbing for a single textual IR
file. Further changes are possible to support multiple libraries and
bytecode files.
Reviewed By: nicolasvasilache
Differential Revision: https://reviews.llvm.org/D146961
Named sequences introduce an additional abstraction and reuse capability
to the transform dialect. They can be though of as macros parameterized
with handles that can be invoked in places where a transform dialect
operation is expected. Such reuse was previously not possible in the
dialect and required dynamic construction of the transform IR from the
client language. Named sequences are intentionally restricted to
disallow recursion, as it could make the dialect accidentally
Turing-complete, which isn't desired at this point.
Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D146433
When commenting for which parameter a value is passed, the same name
should be used as is used for the real parameter. In this case, the
parameter name is generated from the TransformOps.td file.
This transform op returns a value handle pointing to the specified OpResult of the targeted op.
Differential Revision: https://reviews.llvm.org/D144087