43 Commits

Author SHA1 Message Date
Alex Zinenko
984c2c8cb3 [mlir] verify against nullptr payload in transform dialect
When establishing the correspondence between transform values and
payload operations or parameters, check that the latter are non-null and
report errors. This was previously allowed for exotic cases of partially
successfull transformations with "apply each" trait, but was dangerous.
The "apply each" implementation was reworked to remove the need for this
functionality, so this can now be hardned to avoid null pointer
dereferences.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D141142
2023-01-09 14:03:35 +01:00
Alex Zinenko
4b455a71b7 [mlir] adapt TransformEachOpTrait to parameter values
Adapt the implementation of TransformEachOpTrait to the existence of
parameter values recently introduced into the transform dialect. In
particular, allow `applyToOne` hooks to return a list containing a mix
of `Operation *` that will be associated with handles and `Attribute`
that will be associated with parameter values by the trait
implementation of the transform interface's `apply` method.

Disentangle the "transposition" of the list of per-payload op partial
results to decrease its overall complexity and detemplatize the code
that doesn't really need templates. This removes the poorly documented
special handling for single-result ops with TransformEachOpTrait that
could have assigned null pointer values to handles.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D140979
2023-01-06 12:23:41 +00:00
Alex Zinenko
97c05062af [mlir] NFC: rename TransformTypeInterface to TransformHandleTypeInterface
This makes it more consistent with the recently added
TransformParamTypeInterface.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D140977
2023-01-06 12:23:33 +00:00
Alex Zinenko
ed02fa81fd [mlir] introduce parameters into the transofrm dialect
Introduce a new kind of values into the transform dialect -- parameter
values. These values have a type implementing the new
`TransformParamTypeInterface` and are associated with lists of
attributes rather than lists of payload operations. This mechanism
allows one to wrap numeric calculations, typically heuristics, into
transform operations separate from those at actually applying the
transformation. For example, tile size computation can be now separated
from tiling itself, and not hardcoded in the transform dialect. This
further improves the separation of concerns between transform choice and
implementation.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D140976
2023-01-06 12:23:29 +00:00
Alex Zinenko
4299be1a08 [mlir] optionally allow repeated handles in transform dialect
Some operations may be able to deal with handles pointing to the same
operation when the handle is consumed. For example, merge handles with
deduplication doesn't actually destroy payload operations and is
specifically intended to remove the situation with duplicates. Add a
method to the transform interface to allow ops to declare they can
support repeated handles.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D140124
2022-12-19 09:02:03 +00:00
Alex Zinenko
df969f66ef [mlir] fixes to transform::SequenceOp
Harden the verifier to check that the block argument type matches the
operand type, when present. This was overlooked when transform dialect
types were introduced.

Fix the builders to preserve the insertion point before creating the
block, otherwise the insertion point is updated to be within the block
by `createBlock` and never reset to be after the sequence op itself,
leading all following operations to be created in the unexpected to
the caller place.

Reviewed By: chelini, springerm

Differential Revision: https://reviews.llvm.org/D139427
2022-12-12 10:20:38 +01:00
Hanhan Wang
0a1569a400 [mlir][NFC] Remove trailing whitespaces from *.td and *.mlir files.
This is generated by running

```
sed --in-place 's/[[:space:]]\+$//' mlir/**/*.td
sed --in-place 's/[[:space:]]\+$//' mlir/**/*.mlir
```

Reviewed By: rriddle, dcaballe

Differential Revision: https://reviews.llvm.org/D138866
2022-11-28 15:26:30 -08:00
Nicolas Vasilache
aa6a6c56d8 [mlir][Transform] Fix transform.sequence crash in the presence of propagated silenceable errors and yield operations
Differential Revision: https://reviews.llvm.org/D137708
2022-11-09 05:42:43 -08:00
Matthias Springer
4b428364e2 [mlir][transform] Add PrintOp to transform dialect
This op dumps the associated payload IR to stderr. It has proven useful for printf-style debugging.

Differential Revision: https://reviews.llvm.org/D137151
2022-11-02 10:12:05 +01:00
Alex Zinenko
b0bf7ffffc [mlir] add utilites for DiagnosedSilenceableFailure
This class adds helper functions similar to `emitError` for the
DiagnosedSilenceableFailure class in both the silenceable and definite
failure cases. These helpers simplify the use of said class and make
tranfsorm op application code idiomatic.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D136072
2022-10-17 15:31:28 +00:00
Nicolas Vasilache
d8cab3f407 [mlir][Transform] Fix dropReverseMapping early exit condition
Previously, the erasure would not trigger and result in surprising behavior.

Differential Revision: https://reviews.llvm.org/D135881
2022-10-13 08:30:45 -07:00
Alex Zinenko
32f0bde548 [mlir] add transform dialect entry point
Introduce `transform::applyTransforms` as a top-level entry point to the
Transform dialect-driven transformation infrastructure, by analogy with
`applyFull/PartialConversion`. Clients are expected to use this function
and no longer need to maintain the transformation state. Make the
constructor of the TransformState private for that purpose.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D135681
2022-10-12 08:16:28 +00:00
Alex Zinenko
59bb8af4c3 [mlir] switch the transform loop extension to use types
Add types to the Loop (SCF) extension of the transform dialect.

See https://discourse.llvm.org/t/rfc-type-system-for-the-transform-dialect/65702

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D135587
2022-10-11 09:55:23 +00:00
Alex Zinenko
3e1f6d02f7 [mlir] add OperationType to the Transform dialect
Add a new OperationType handle type to the Transform dialect. This
transform type is parameterized by the name of the payload operation it
can point to. It is intended as a constraint on transformations that are
only applicable to a specific kind of payload operations. If a
transformation is applicable to a small set of operation classes, it can
be wrapped into a transform op by using a disjunctive constraint, such
as `Type<Or<[Transform_ConcreteOperation<"foo">.predicate,
Transform_ConcreteOperation<"bar">.predicate]>>` for its operand without
modifying this type. Broader sets of accepted operations should be
modeled as specific types.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D135586
2022-10-11 09:55:19 +00:00
Alex Zinenko
6fe0309602 [mlir] switch transform dialect ops to use TransformTypeInterface
Use the recently introduced TransformTypeInterface instead of hardcoding
the PDLOperationType. This will allow the operations to use more
specific transform types to express pre/post-conditions in the future.
It requires the syntax and Python op construction API to be updated.
Dialect extensions will be switched separately.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D135584
2022-10-11 09:55:13 +00:00
Alex Zinenko
bba85ebdfe [mlir] add types to the transform dialect
Introduce a type system for the transform dialect. A transform IR type
captures the expectations of the transform IR on the payload IR
operations that are being transformed, such as being of a certain kind
or implementing an interface that enables the transformation. This
provides stricter checking and better readability of the transform IR
than using the catch-all "handle" type.

This change implements the basic support for a type system amendable to
dialect extensions and adds a drop-in replacement for the unrestricted
"handle" type. The actual switch of transform dialect ops to that type
will happen in a separate commit.

See https://discourse.llvm.org/t/rfc-type-system-for-the-transform-dialect/65702

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D135164
2022-10-11 09:55:07 +00:00
Nicolas Vasilache
af664e4459 [mlir][Transform] Add a transform.split_handles operation and fix general silenceable bugs.
The transform.split_handles op is useful for ensuring a statically known number of operations are
tracked by the source `handle` and to extract them into individual handles
that can be further manipulated in isolation.

In the process of making the op robust wrt to silenceable errors and the suppress mode, issues were
uncovered and fixed.

The main issue was that silenceable errors were short-circuited too early and the payloads were not
set. This resulted in suppressed silenceable errors not propagating correctly.
Fixing the issue triggered a few test failures: silenceable error returns now must properly set the results state.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D135426
2022-10-07 09:01:34 -07:00
Alex Zinenko
3dfea727a4 [mlir] relax transform dialect multi-handle restriction
Relax the restriction in the transform dialect interpreter utilities
that expected a payload IR op to be assocaited with at most one
transform IR handle value. This was useful during the initial
bootstrapping to avoid use-after-free error equivalents when a payload
IR op could be erased through one of the handles associated with it and
then accessed through another. It was, however, possible to erase an
ancestor of the payload IR operation in question. The expensive-checks
mode of interpretation is able to detect both cases and has proven
sufficiently robust in debugging use-after-free errors.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D134964
2022-10-04 11:57:49 +00:00
Alex Zinenko
8975fb0b26 [mlir] fix DiagnosedSilenceableFailure::takeDiagnostics
This function was returning an rvalue reference to an object that was
also cleared via RAII when the function returned, making it always
return an empty object. Make it accept the mutable reference to the
object instead to avoid this dangerous behavior.

Reviewed By: guraypp

Differential Revision: https://reviews.llvm.org/D134948
2022-09-30 11:34:48 +00:00
Nicolas Vasilache
ecd9dc0499 [mlir][Transform] Add a new navigation op to retrieve the producer of an operand
Given an opOperand uniquely determined by the operation `%op` and the operand number `num`,
the `transform.get_producer_of_operand %op[num]` returns the handle to the unique operation
that produced the SSA value used as opOperand.

The transform fails if the operand is a block argument.

Differential Revision: https://reviews.llvm.org/D134171
2022-09-19 04:16:15 -07:00
Alex Zinenko
59a640a381 [mlir] improve the error message in expensive transform checks
Include the transform op being applied when reporting it using an invalidated
handle. This was missing previously and made it harder for the user to
understand where the handle is being used, especially if the transform script
included some sort of iteration.

Reviewed By: guraypp

Differential Revision: https://reviews.llvm.org/D133774
2022-09-13 16:58:52 +02:00
Alex Zinenko
a60ed95419 [mlir][transform] failure propagation mode in sequence
Introduce two different failure propagation mode in the Transform
dialect's Sequence operation. These modes specify whether silenceable
errors produced by nested ops are immediately propagated, thus stopping
the sequence, or suppressed. The latter is useful in end-to-end
transform application scenarios where the user cannot correct the
transformation, but it is robust enough to silenceable failures. It
can be combined with the "alternatives" operation. There is
intentionally no default value to avoid favoring one mode over the
other.

Downstreams can update their tests using:

  S='s/sequence \(%.*\) {/sequence \1 failures(propagate) {/'
  T='s/sequence {/sequence failures(propagate) {/'
  git grep -l transform.sequence | xargs sed -i -e "$S"
  git grep -l transform.sequence | xargs sed -i -e "$T"

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D131774
2022-08-12 15:31:22 +00:00
Matthias Springer
c1e6caac70 [mlir][transform] Support results on ForeachOp
Handles can be yielded from the ForeachOp.

Differential Revision: https://reviews.llvm.org/D130640
2022-07-28 10:39:54 +02:00
Matthias Springer
bffec215ab [mlir][transform] Add ForeachOp to transform dialect
This op "unbatches" an op handle and executes the loop body for each payload op.

Differential Revision: https://reviews.llvm.org/D130257
2022-07-26 18:07:44 +02:00
Matthias Springer
74902cc96f [mlir][linalg][NFC] Cleanup: Drop linalg.inplaceable attribute
bufferization.writable is used in most cases instead. All remaining test cases are updated. Some code that is no longer needed is deleted.

Differential Revision: https://reviews.llvm.org/D129739
2022-07-14 15:50:03 +02:00
Alex Zinenko
4e4a4c0576 [mlir] Allow Tile transform op to take dynamic sizes
Extend the definition of the Tile structured transform op to enable it
accepting handles to operations that produce tile sizes at runtime. This is
useful by itself and prepares for more advanced tiling strategies. Note that
the changes are relevant only to the transform dialect, the tiling
transformation itself already supports dynamic sizes.

Depends On D129216

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D129217
2022-07-12 12:21:54 +00:00
Alex Zinenko
00d1a1a25f [mlir] Add ReplicateOp to the Transform dialect
This handle manipulation operation allows one to define a new handle that is
associated with a the same payload IR operations N times, where N can be driven
by the size of payload IR operation list associated with another handle. This
can be seen as a sort of broadcast that can be used to ensure the lists
associated with two handles have equal numbers of payload IR ops as expected by
many pairwise transform operations.

Introduce an additional "expensive" check that guards against consuming a
handle that is assocaited with the same payload IR operation more than once as
this is likely to lead to double-free or other undesired effects.

Depends On D129110

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D129216
2022-07-12 09:07:59 +00:00
Nicolas Vasilache
69c8319e76 [mlir][Transform] Fix isDefiniteFailure helper
This newly added helper was returning definiteFailure even in the case of silenceableFailure.

Differential Revision: https://reviews.llvm.org/D129347
2022-07-08 00:39:42 -07:00
Nicolas Vasilache
5230710933 [mlir][Transform] Make applyToOne return a DiagnosedSilenceableFailure
This revision revisits the implementation of applyToOne and its handling
of recoverable errors as well as propagation of null handles.
The implementation is simplified to always require passing a vector<Operation*>
in which the results are returned, resulting in less template instantiation magic.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D129185
2022-07-07 07:32:04 -07:00
Alex Zinenko
8e03bfc368 [mlir] Transform dialect: introduce merge_handles op
This Transform dialect op allows one to merge the lists of Payload IR
operations pointed to by several handles into a single list associated with one
handle. This is an important Transform dialect usability improvement for cases
where transformations may temporarily diverge for different groups of Payload
IR ops before converging back to the same script. Without this op, several
copies of the trailing transformations would have to be present in the
transformation script.

Depends On D129090

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D129110
2022-07-07 13:19:46 +02:00
Nicolas Vasilache
8c6da76483 [mlir][Transform] Fix applyToOne corner case when no op is matched.
Such situations manifest themselves with an empty payload which ends up producing empty results.
In such cases, we still want to match the transform op contract and return as many empty SmallVector<Operation*>
as the op requires.

Differential Revision: https://reviews.llvm.org/D128456
2022-06-23 12:18:21 -07:00
Nicolas Vasilache
4c7225d19a [mlir][Transform] Fix implementation of the generic apply that is based on applyToOne.
The result of applying an N-result producing transformation to M payload ops
is an M-wide result, each containing N result operations.
This requires a transposition of the results obtained by calling `applyToOne`.

This revision fixes the issue and adds more advanced tests that exercise the behavior.

Differential Revision: https://reviews.llvm.org/D128414
2022-06-23 05:28:09 -07:00
Nicolas Vasilache
f439b31971 [mlir][Linalg] Split reduction transform op
This revision separates the `LinalgSplitReduction` pattern, whose application is based on attributes,
from its implementation.
A transform dialect op extension is added to control the application of the transformation at a finer granularity.

Differential Revision: https://reviews.llvm.org/D128165
2022-06-21 05:01:26 -07:00
Alex Zinenko
1d45282aa3 [mlir] address post-commit review for D127724
- make transform.alternatives op apply only to isolated-from-above payload IR
  scopes;
- fix potential leak;
- fix several typos.
2022-06-15 18:43:05 +02:00
Alex Zinenko
e3890b7fd6 [mlir] Introduce transform.alternatives op
Introduce a transform dialect op that allows one to attempt different
transformation sequences on the same piece of payload IR until one of them
succeeds. This op fundamentally expands the scope of possibilities in the
transform dialect that, until now, could only propagate transformation failure,
at least using in-tree operations. This requires a more detailed specification
of the execution model for the transform dialect that now indicates how failure
is handled and propagated.

Transformations described by transform operations now have tri-state results,
with some errors being fundamentally irrecoverable (e.g., generating malformed
IR) and some others being recoverable by containing ops. Existing transform ops
directly implementing the `apply` interface method are updated to produce this
directly. Transform ops with the `TransformEachTransformOpTrait` are currently
considered to produce only irrecoverable failures and will be updated
separately.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D127724
2022-06-14 17:51:30 +02:00
Alex Zinenko
6403e1b12a [mlir] add a dynamic user-after-parent-freed transform dialect check
In the transform dialect, a transform IR handle may be pointing to a payload IR
operation that is an ancestor of another payload IR operation pointed to by
another handle. If such a "parent" handle is consumed by a transformation, this
indicates that the associated operation is likely rewritten, which in turn
means that the "child" handle may now be associated with a dangling pointer or
a pointer to a different operation than originally. Add a handle invalidation
mechanism to guard against such situations by reporting errors at runtime.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D127480
2022-06-10 13:05:34 +02:00
Alex Zinenko
cc6c159203 [mlir] add VectorizeOp to structured transform ops
Vectorization is a key transformation to achieve high performance on most
architectures. In the transform dialect, vectorization is implemented as a
parameterizable transform op. It currently applies to a scope of payload IR
delimited by some isolated-from-above op, mainly because several enabling
transformations (such as affine simplification) are needed to perform
vectorization and these transformation would apply to ops other than the "main"
computational payload op. A separate "navigation" transform op that obtains the
isolated-from-above ancestor of an op is introduced in the core transform
dialect. Even though it is currently only useful for vectorization,
isolated-from-above ops are a common anchor for transformations (usually
implemented as passes) that is likely to be reused in the future.

Depends On D126374

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D126542
2022-05-30 17:37:50 +02:00
Alex Zinenko
73c3dff1b3 [mlir] Use-after-free checker for the Transform dialect
The Transform dialect uses the side effect modeling mechanism to record the
effects of the transform ops on the mapping between Transform IR values and
Payload IR ops. Introduce a checker pass that warns if a Transform IR value is
used after it has been freed (consumed). This pass is mostly intended as a
debugging aid in addition to the verification/assertion mechanisms in the
transform interpreter. It reports all potential use-after-free situations.
The implementation makes a series of simplifying assumptions to be simple and
conservative. A more advanced implementation would rely on the data flow-like
analysis associated with a side-effect resource rather than a value, which is
currently not supported by the analysis infrastructure.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D126381
2022-05-26 12:28:41 +02:00
Alex Zinenko
6c57b0debe [mlir] improve and test TransformState::Extension
Add the mechanism for TransformState extensions to update the mapping between
Transform IR values and Payload IR operations held by the state. The mechanism
is intentionally restrictive, similarly to how results of the transform op are
handled.

Introduce test ops that exercise a simple extension that maintains information
across the application of multiple transform ops.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D124778
2022-05-03 11:33:00 +02:00
Alex Zinenko
40a8bd635b [mlir] use side effects in the Transform dialect
Currently, the sequence of Transform dialect operations only supports a single
use of each operand (verified by the `transform.sequence` operation). This was
originally motivated by the need to guard against accessing a payload IR
operation associated with a transform IR value after this operation has likely
been rewritten by a transformation. However, not all Transform dialect
operations rewrite payload IR, in particular the "navigation" operation such as
`transform.pdl_match` do not.

Introduce memory effects to the Transform dialect operations to describe their
effect on the payload IR and the mapping between payload IR opreations and
transform IR values. Use these effects to replace the single-use rule, allowing
repeated reads and disallowing use-after-free, where operations with the "free"
effect are considered to "consume" the transform IR value and rewrite the
corresponding payload IR operations). As an additional improvement, this
enables code motion transformation on the transform IR itself.

Reviewed By: Mogball

Differential Revision: https://reviews.llvm.org/D124181
2022-04-22 23:29:11 +02:00
Alex Zinenko
30f22429d3 [mlir] Connect Transform dialect to PDL
This introduces a pair of ops to the Transform dialect that connect it to PDL
patterns. Transform dialect relies on PDL for matching the Payload IR ops that
are about to be transformed. For this purpose, it provides a container op for
patterns, a "pdl_match" op and transform interface implementations that call
into the pattern matching infrastructure.

To enable the caching of compiled patterns, this also provides the extension
mechanism for TransformState. Extensions allow one to store additional
information in the TransformState and thus communicate it between different
Transform dialect operations when they are applied. They can be added and
removed when applying transform ops. An extension containing a symbol table in
which the pattern names are resolved and a pattern compilation cache is
introduced as the first client.

Depends On D123664

Reviewed By: Mogball

Differential Revision: https://reviews.llvm.org/D124007
2022-04-21 16:23:10 +02:00
Alex Zinenko
0eb403ad1b [mlir][transform] Introduce transform.sequence op
Sequence is an important transform combination primitive that just indicates
transform ops being applied in a row. The simplest version requires fails
immediately if any transformation in the sequence fails. Introducing this
operation allows one to start placing transform IR within other IR.

Depends On D123135

Reviewed By: Mogball, rriddle

Differential Revision: https://reviews.llvm.org/D123664
2022-04-19 21:41:02 +02:00
Alex Zinenko
d064c4801c [mlir] Introduce Transform dialect
This dialect provides operations that can be used to control transformation of
the IR using a different portion of the IR. It refers to the IR being
transformed as payload IR, and to the IR guiding the transformation as
transform IR.

The main use case for this dialect is orchestrating fine-grain transformations
on individual operations or sets thereof. For example, it may involve finding
loop-like operations with specific properties (e.g., large size) in the payload
IR, applying loop tiling to those and only those operations, and then applying
loop unrolling to the inner loops produced by the previous transformations. As
such, it is not intended as a replacement for the pass infrastructure, nor for
the pattern rewriting infrastructure. In the most common case, the transform IR
will be processed and applied to payload IR by a pass. Transformations
expressed by the transform dialect may be implemented using the pattern
infrastructure or any other relevant MLIR component.

This dialect is designed to be extensible, that is, clients of this dialect are
allowed to inject additional operations into this dialect using the newly
introduced in this patch `TransformDialectExtension` mechanism. This allows the
dialect to avoid a dependency on the implementation of the transformation as
well as to avoid introducing dialect-specific transform dialects.

See https://discourse.llvm.org/t/rfc-interfaces-and-dialects-for-precise-ir-transformation-control/60927.

Reviewed By: nicolasvasilache, Mogball, rriddle

Differential Revision: https://reviews.llvm.org/D123135
2022-04-14 13:48:45 +02:00