This is an archive of the discontinued LLVM Phabricator instance.

[mlir][transform][NFC] Store all Mappings in region stack
ClosedPublic

Authored by springerm on Jun 26 2023, 6:49 AM.

Details

Summary

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.

Depends On: D153764

Diff Detail

Event Timeline

springerm created this revision.Jun 26 2023, 6:49 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 26 2023, 6:49 AM
springerm requested review of this revision.Jun 26 2023, 6:49 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 26 2023, 6:50 AM
ftynse accepted this revision.Jun 26 2023, 7:55 AM
This revision is now accepted and ready to land.Jun 26 2023, 7:55 AM
This revision was landed with ongoing or failed builds.Jun 26 2023, 8:36 AM
This revision was automatically updated to reflect the committed changes.

@springerm this patch seems to have introduced a use-after-free error. Specifically, in the ForeachOp::apply() method, ops inserted in setPayloadOps() seem to be erased before the next call to getPayloadOps(). My hunch is that the pointers are invalidated as a result of applying the transformation, since copying all pointers first seems to make the problem go away. Does the following patch seem like a reasonable fix? Are there other places where we should copy the pointers first before using them?

--- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
+++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
@@ -828,7 +828,9 @@ transform::ForeachOp::apply(transform::TransformRewriter &rewriter,
                             transform::TransformState &state) {
   SmallVector<SmallVector<Operation *>> resultOps(getNumResults(), {});

-  for (Operation *op : state.getPayloadOps(getTarget())) {
+  // Copy pointers to guard against invalidation by the transform.
+  SmallVector<Operation *> payloadOps{state.getPayloadOps(getTarget())};
+  for (Operation *op : payloadOps) {
     auto scope = state.make_region_scope(getBody());
     if (failed(state.mapBlockArguments(getIterationVariable(), {op})))
       return DiagnosedSilenceableFailure::definiteFailure();

Correction: this patch didn't _introduce_ the problem, it just made it apparent.