@@ -209,11 +209,13 @@ class TransformOptions {
209209// / TransformOpInterface. The operations implementing this interface and the
210210// / surrounding structure are referred to as transform IR. The operations to
211211// / which transformations apply are referred to as payload IR. The state thus
212- // / contains the mapping between values defined in the transform IR ops and
213- // / payload IR ops. It assumes that each value in the transform IR can be used
214- // / at most once (since transformations are likely to change the payload IR ops
215- // / the value corresponds to). Checks that transform IR values correspond to
216- // / disjoint sets of payload IR ops throughout the transformation.
212+ // / contains the many-to-many mapping between values defined in the transform IR
213+ // / ops and payload IR ops. The "expensive-checks" option can be passed to
214+ // / the constructor at transformation execution time that transform IR values
215+ // / used as operands by a transform IR operation are not associated with
216+ // / dangling pointers to payload IR operations that are known to have been
217+ // / erased by previous transformation through the same or a different transform
218+ // / IR value.
217219// /
218220// / A reference to this class is passed as an argument to "apply" methods of the
219221// / transform op interface. Thus the "apply" method can call
@@ -235,9 +237,10 @@ class TransformState {
235237 // / operations in the payload IR.
236238 using TransformOpMapping = DenseMap<Value, SmallVector<Operation *>>;
237239
238- // / Mapping between a payload IR operation and the transform IR value it is
239- // / currently associated with.
240- using TransformOpReverseMapping = DenseMap<Operation *, Value>;
240+ // / Mapping between a payload IR operation and the transform IR values it is
241+ // / associated with.
242+ using TransformOpReverseMapping =
243+ DenseMap<Operation *, SmallVector<Value, 2 >>;
241244
242245 // / Bidirectional mappings between transform IR values and payload IR
243246 // / operations.
@@ -249,7 +252,7 @@ class TransformState {
249252public:
250253 // / Creates a state for transform ops living in the given region. The parent
251254 // / operation of the region. The second argument points to the root operation
252- // / in the payload IR beind transformed, which may or may not contain the
255+ // / in the payload IR being transformed, which may or may not contain the
253256 // / region with transform ops. Additional options can be provided through the
254257 // / trailing configuration object.
255258 TransformState (Region ®ion, Operation *root,
@@ -263,9 +266,10 @@ class TransformState {
263266 // / This is helpful for transformations that apply to a particular handle.
264267 ArrayRef<Operation *> getPayloadOps (Value value) const ;
265268
266- // / Returns the Transform IR handle for the given Payload IR op if it exists
267- // / in the state, null otherwise.
268- Value getHandleForPayloadOp (Operation *op) const ;
269+ // / Populates `handles` with all handles pointing to the given Payload IR op.
270+ // / Returns success if such handles exist, failure otherwise.
271+ LogicalResult getHandlesForPayloadOp (Operation *op,
272+ SmallVectorImpl<Value> &handles) const ;
269273
270274 // / Applies the transformation specified by the given transform op and updates
271275 // / the state accordingly.
@@ -275,13 +279,13 @@ class TransformState {
275279 // / list of operations in the payload IR. The arguments must be defined in
276280 // / blocks of the currently processed transform IR region, typically after a
277281 // / region scope is defined.
278- LogicalResult mapBlockArguments (BlockArgument argument,
279- ArrayRef<Operation *> operations) {
282+ void mapBlockArguments (BlockArgument argument,
283+ ArrayRef<Operation *> operations) {
280284#if LLVM_ENABLE_ABI_BREAKING_CHECKS
281285 assert (argument.getParentRegion () == regionStack.back () &&
282286 " mapping block arguments from a region other than the active one" );
283287#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
284- return setPayloadOps (argument, operations);
288+ setPayloadOps (argument, operations);
285289 }
286290
287291 // Forward declarations to support limited visibility.
@@ -379,7 +383,8 @@ class TransformState {
379383 const TransformState &getTransformState () const { return state; }
380384
381385 // / Replaces the given payload op with another op. If the replacement op is
382- // / null, removes the association of the payload op with its handle.
386+ // / null, removes the association of the payload op with its handle. Returns
387+ // / failure if the op is not associated with any handle.
383388 LogicalResult replacePayloadOp (Operation *op, Operation *replacement);
384389
385390 private:
@@ -451,20 +456,29 @@ class TransformState {
451456 return it->second ;
452457 }
453458
454- // / Sets the payload IR ops associated with the given transform IR value.
455- // / Fails if this would result in multiple transform IR values with uses
456- // / corresponding to the same payload IR ops. For example, a hypothetical
457- // / "find function by name" transform op would (indirectly) call this
458- // / function for its result. Having two such calls in a row with for different
459- // / values, e.g. coming from different ops:
459+ // / Removes the mapping between the given payload IR operation and the given
460+ // / transform IR value.
461+ void dropReverseMapping (Mappings &mappings, Operation *op, Value value);
462+
463+ // / Sets the payload IR ops associated with the given transform IR value
464+ // / (handle). A payload op may be associated multiple handles as long as
465+ // / at most one of them gets consumed by further transformations.
466+ // / For example, a hypothetical "find function by name" may be called twice in
467+ // / a row to produce two handles pointing to the same function:
460468 // /
461469 // / %0 = transform.find_func_by_name { name = "myfunc" }
462470 // / %1 = transform.find_func_by_name { name = "myfunc" }
463471 // /
464- // / would lead to both values pointing to the same operation. The second call
465- // / to setPayloadOps will fail, unless the association with the %0 value is
466- // / removed first by calling update/removePayloadOps.
467- LogicalResult setPayloadOps (Value value, ArrayRef<Operation *> targets);
472+ // / which is valid by itself. However, calling a hypothetical "rewrite and
473+ // / rename function" transform on both handles:
474+ // /
475+ // / transform.rewrite_and_rename %0 { new_name = "func" }
476+ // / transform.rewrite_and_rename %1 { new_name = "func" }
477+ // /
478+ // / is invalid given the transformation "consumes" the handle as expressed
479+ // / by side effects. Practically, a transformation consuming a handle means
480+ // / that the associated payload operation may no longer exist.
481+ void setPayloadOps (Value value, ArrayRef<Operation *> targets);
468482
469483 // / Forgets the payload IR ops associated with the given transform IR value.
470484 void removePayloadOps (Value value);
@@ -473,24 +487,18 @@ class TransformState {
473487 // / The callback function is called once per associated operation and is
474488 // / expected to return the modified operation or nullptr. In the latter case,
475489 // / the corresponding operation is no longer associated with the transform IR
476- // / value. May fail if the operation produced by the update callback is
477- // / already associated with a different Transform IR handle value.
478- LogicalResult
479- updatePayloadOps (Value value,
480- function_ref<Operation *(Operation *)> callback);
481-
482- // / Attempts to record the mapping between the given Payload IR operation and
483- // / the given Transform IR handle. Fails and reports an error if the operation
484- // / is already tracked by another handle.
485- static LogicalResult tryEmplaceReverseMapping (Mappings &map, Operation *op,
486- Value handle);
490+ // / value.
491+ void updatePayloadOps (Value value,
492+ function_ref<Operation *(Operation *)> callback);
487493
488494 // / If the operand is a handle consumed by the operation, i.e. has the "free"
489495 // / memory effect associated with it, identifies other handles that are
490496 // / pointing to payload IR operations nested in the operations pointed to by
491- // / the consumed handle. Marks all such handles as invalidated so trigger
497+ // / the consumed handle. Marks all such handles as invalidated to trigger
492498 // / errors if they are used.
493499 void recordHandleInvalidation (OpOperand &handle);
500+ void recordHandleInvalidationOne (OpOperand &handle, Operation *payloadOp,
501+ Value otherHandle);
494502
495503 // / Checks that the operation does not use invalidated handles as operands.
496504 // / Reports errors and returns failure if it does. Otherwise, invalidates the
@@ -566,9 +574,9 @@ namespace detail {
566574// / Maps the only block argument of the op with PossibleTopLevelTransformOpTrait
567575// / to either the list of operations associated with its operand or the root of
568576// / the payload IR, depending on what is available in the context.
569- LogicalResult
570- mapPossibleTopLevelTransformOpBlockArguments (TransformState &state ,
571- Operation *op, Region ®ion);
577+ void mapPossibleTopLevelTransformOpBlockArguments (TransformState &state,
578+ Operation *op ,
579+ Region ®ion);
572580
573581// / Verification hook for PossibleTopLevelTransformOpTrait.
574582LogicalResult verifyPossibleTopLevelTransformOpTrait (Operation *op);
@@ -605,18 +613,17 @@ class PossibleTopLevelTransformOpTrait
605613 // / Sets up the mapping between the entry block of the given region of this op
606614 // / and the relevant list of Payload IR operations in the given state. The
607615 // / state is expected to be already scoped at the region of this operation.
608- // / Returns failure if the mapping failed, e.g., the value is already mapped.
609- LogicalResult mapBlockArguments (TransformState &state, Region ®ion) {
616+ void mapBlockArguments (TransformState &state, Region ®ion) {
610617 assert (region.getParentOp () == this ->getOperation () &&
611618 " op comes from the wrong region" );
612- return detail::mapPossibleTopLevelTransformOpBlockArguments (
619+ detail::mapPossibleTopLevelTransformOpBlockArguments (
613620 state, this ->getOperation (), region);
614621 }
615- LogicalResult mapBlockArguments (TransformState &state) {
622+ void mapBlockArguments (TransformState &state) {
616623 assert (
617624 this ->getOperation ()->getNumRegions () == 1 &&
618625 " must indicate the region to map if the operation has more than one" );
619- return mapBlockArguments (state, this ->getOperation ()->getRegion (0 ));
626+ mapBlockArguments (state, this ->getOperation ()->getRegion (0 ));
620627 }
621628};
622629
0 commit comments