This is an archive of the discontinued LLVM Phabricator instance.

[mlir][transform] Use TrackingListener-aware iterator for getPayloadOps
ClosedPublic

Authored by springerm on May 4 2023, 6:39 AM.

Details

Summary

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. nullptrs are not enumerated by getPayloadOps. At the end of each transformation, nullptrs are removed from the mapping data structure.

Depends On: D149937

Diff Detail

Event Timeline

springerm created this revision.May 4 2023, 6:39 AM
Herald added a project: Restricted Project. · View Herald Transcript
springerm requested review of this revision.May 4 2023, 6:39 AM
Herald added a project: Restricted Project. · View Herald Transcript
springerm retitled this revision from [mlir][transform][WIP] Use TrackingListener-aware iterator for getPayloadOps to [mlir][transform] Use TrackingListener-aware iterator for getPayloadOps.May 5 2023, 1:54 AM
springerm edited the summary of this revision. (Show Details)
ftynse requested changes to this revision.May 5 2023, 4:25 AM
ftynse added inline comments.
mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
590

Nit: please document.

647–665

Nit: let's have Range && here to avoid unnecessary copying.

656

Nit: std::forward<Range>(ops)

667

Isn't this covered by the template case? (Maybe it wasn't because of missing &&?)

1115

Same as above.

1183

Nit: std::empty(targets)

mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
212–213

Same as above: Range &&.

mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
377–379

Not preserving the order may be problematic. I've seen cases where two handles are co-iterated. We can preserve the order here, I believe. Specifically, when compacting the associations of a handle, we can iterate over the vector backwards and swap nullptr with the last non-null element, which is the replacement value due to the order of addition. We can then just resize the vector down to the size with non-null elements, which is also more efficient than erasing nulls one by one and copying the tail every time,

399

This is problematic. Appending to the vector invalidates iterators because it may trigger reallocation, so if we are iterating over the exact same container elsewhere, it may segfault. We need to either double the size of the vector before the iterator is produced so we can just write to the second half, or store these replacements separately.

This revision now requires changes to proceed.May 5 2023, 4:25 AM
springerm marked 8 inline comments as done.May 9 2023, 12:56 AM
springerm added inline comments.
mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
399

replacement ops are no longer added to the end of the list. they are immediately put at the right place in this function (same functionality as before this revision). the only special handling is for op erasures: nullptrs are put in the direct mapping (and removed later).

springerm updated this revision to Diff 520617.May 9 2023, 12:56 AM
springerm marked an inline comment as done.
springerm edited the summary of this revision. (Show Details)

address comments

springerm planned changes to this revision.May 9 2023, 1:00 AM
springerm updated this revision to Diff 520621.May 9 2023, 1:25 AM

improve test case

ftynse accepted this revision.May 12 2023, 7:37 AM
This revision is now accepted and ready to land.May 12 2023, 7:37 AM

Great, thanks for pushing on this!

This revision was landed with ongoing or failed builds.May 15 2023, 1:38 AM
This revision was automatically updated to reflect the committed changes.