Skip to content

[OSSACanonicalizeOwned] Fix liveness passed to completion. #78624

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

Merged
merged 7 commits into from
Jan 16, 2025

Conversation

nate-chandler
Copy link
Contributor

To determine where a lifetime ends within dead-end blocks, OSSACanonicalizeOwned uses OSSACompleteLifetime's visitAvailabilityBoundary. This API takes a liveness which it uses to walk forward to the availability boundary. Specifically, the liveness passed from OSSACanonicalizeOwned to OSSACompleteLifetime is a variation of OSSACanonicalizeOwned's own liveness (it has destroys added).

There is a mismatch in the characteristics of livenesses created by OSSACanonicalizeOwned and OSSACompleteLifetime: The former deals with not only direct uses of a value but also uses of its copies; that introduces the possibility for consuming uses in the middle of liveness. The latter on the other hand deals only with uses of a single value (nestedly, but at each level of nesting only a single value). Passing a liveness from the former to the latter without handling this mismatch is incorrect: OSSACompleteLifetime understands consuming uses to always end a lifetime, even when they are in the middle of a copy-extended liveness. The result is that OSSACompleteLifetime produces non-sensical results when provided with such a liveness.

To address this, fixup the liveness passed from OSSACanonicalizeOwned to OSSACompleteLifetime by demoting consuming uses that appear within (that's to say not on the boundary) of liveness to non-consuming uses.

Also, check in a few other changes that facilitated tracking this down:

  • printing AST types when printing the SIL module when passing -sil-print-module-on-error
  • a minor refactoring to SILCombine to extract the processing it does on a single instruction into a separate function
  • a FunctionTest to call that new SILCombine function

rdar://142846936

The pass is structured to drain an instruction worklist and perform a
sequence of operations on each popped instruction.  Extract that
sequence of operations into a new processInstruction function. Enables
testing the sequence on a single instruction.
According to the documentation,

```
It's ok if postDomBlocks has duplicates or extraneous blocks, as long
as they jointly post-dominate all live blocks that aren't on dead-end
paths.
```

Previously, though, duplicates resulted in trapping: each element of
`postDomBlocks` is pushed into a `BasicBlockWorklist`; when the second
occurrence of an element in `postDomBlocks` was encountered,
`BasicBlockWorklist::push` would trigger an assertion failure.

Here, `pushIfNotVisited` is called instead.
@nate-chandler nate-chandler force-pushed the rdar142520491_2 branch 2 times, most recently from 30024b3 to 4f8cf61 Compare January 14, 2025 02:15
@nate-chandler
Copy link
Contributor Author

Source compat failures match failures in baseline.

@nate-chandler nate-chandler marked this pull request as ready for review January 14, 2025 15:25
@nate-chandler nate-chandler removed the request for review from jckarter January 14, 2025 15:25
To determine where a lifetime ends within dead-end blocks,
OSSACanonicalizeOwned uses OSSACompleteLifetime's
visitAvailabilityBoundary.  This API takes a liveness which it uses to
walk forward to the availability boundary.  Specifically, the liveness
passed from OSSACanonicalizeOwned to OSSACompleteLifetime is a variation
of OSSACanonicalizeOwned's own liveness (it has destroys added).

There is a mismatch in the characteristics of livenesses created by
OSSACanonicalizeOwned and OSSACompleteLifetime:  The former deals with
not only direct uses of a value but also uses of its copies; that
introduces the possibility for consuming uses in the middle of liveness.
The latter on the other hand deals only with uses of a single value
(nestedly, but at each level of nesting only a single value).  Passing a
liveness from the former to the latter without handling this mismatch
is incorrect: OSSACompleteLifetime understands consuming uses to always
end a lifetime, even when they are in the middle of a copy-extended
liveness.  The result is that OSSACompleteLifetime produces non-sensical
results when provided with such a liveness.

To address this, fixup the liveness passed from OSSACanonicalizeOwned to
OSSACompleteLifetime by demoting consuming uses that appear within
(that's to say _not_ on the boundary) of liveness to non-consuming uses.

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

@swift-ci please test

@nate-chandler
Copy link
Contributor Author

@swift-ci please apple silicon benchmark

@nate-chandler
Copy link
Contributor Author

@swift-ci please test source compatibility

@nate-chandler
Copy link
Contributor Author

@swift-ci please test macos platform

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nate-chandler nate-chandler merged commit b59280c into swiftlang:main Jan 16, 2025
6 of 8 checks passed
@nate-chandler nate-chandler deleted the rdar142520491_2 branch January 16, 2025 03:38
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.

2 participants