Skip to content

6.2: [DCE] Don't delete instructions which consume escaping values. #80781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: release/6.2
Choose a base branch
from

Conversation

nate-chandler
Copy link
Contributor

@nate-chandler nate-chandler commented Apr 12, 2025

Explanation: Fix a lifetime-shortening miscompile in DCE.

Dead code elimination deletes instructions. Some of those instructions consume their operands. When such an instruction is deleted, a compensating lifetime-ending instruction (e.g. destroy_value) must be inserted. In simple cases, the pass has its own logic to determine where to insert the compensating lifetime-ending instruction. For more complex cases, it depends on the lifetime completion utility, inserting compensating lifetime ends at the liveness boundary. The utility requires (and can't be made not to) complete liveness of the value that it's called on: it is not permitted to complete the lifetime at the liveness boundary of a value which does not have complete liveness. Why? The boundary isn't known. In particular, it is not permitted if the value has a pointer escape.

Previously, however, DCE used the utility even in such cases. This could result in inserting a compensating lifetime-ending instruction just after the value escapes to a pointer. Code which then used that pointer would be using a dangling pointer.

Here, the pass is fixed to check whether an instruction consumes a value which escapes to a pointer. If it does, it marks the instruction live, preventing it from being deleted.
Scope: Affects optimized code.
Issue: rdar://149007151
Original PR: #80766
Risk: Low, the fix is to prevent the pass from making a change occasionally.
Testing: Added test.
Reviewer: Andrew Trick ( @atrick )

When DCE deletes instructions as dead, if the instruction ends one of
its operands lifetimes, it must insert a compensating lifetime end.
When the def block of the value and the parent block of the instruction
are different, it uses lifetime completion.  Lifetime completion relies
on complete liveness, which doesn't and can't exist for values with
pointer escapes.  The result is ending lifetimes too early.

Avoid this scenario by marking such instructions live.

In the fullness of time, it may be possible to track the deleted
instruction's "location" even in the face of deletions of adjacent
instructions and parent blocks and to insert the lifetime end at that
location.

rdar://149007151
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler nate-chandler marked this pull request as ready for review April 12, 2025 15:31
@nate-chandler nate-chandler requested a review from a team as a code owner April 12, 2025 15:31
@nate-chandler nate-chandler enabled auto-merge April 12, 2025 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant