-
Notifications
You must be signed in to change notification settings - Fork 10.5k
AllocBoxToStack: Remove bodies of closure functions left unused after specialization. #67031
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
AllocBoxToStack: Remove bodies of closure functions left unused after specialization. #67031
Conversation
… specialization. We can't remove the functions at this point in case they might have other function passes enqueued to run on them, but we can at least remove the function contents that are now unnecessary. We need to do this in cases when move-only types are involved, since the semantics of the move checker rely on unescaped captures being promoted before the pass runs, and we leave behind invalid SIL in the unpromoted code. rdar://110675352
@swift-ci Please test |
|
||
// TODO: Erase from module if there are no more uses. | ||
// If the function has no remaining references, it should eventually | ||
// be deleted. We can't do that from a function pass, since the function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eeckstein I'm surprised that we can't mark functions deleted (which should automatically remove the function body). We should even have a SILFunction::deleteIfUnused
API. Do you remember why we never did that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's not that easy to see if a function is unused. There is no use list for functions. We have Refcount
, but that also includes references from utilities, like the cache in the Deserializer. Also, in case of cycles the refcount would be useless.
So the strategy is to keep unused functions around until the DeadFunctionElimination pass deletes them eventually.
…originals removed by MoveOnlyChecker. This is an improvement of swiftlang#67031 which avoids deleting the closure function body during AllocBoxToStack, which still breaks pass invariants by modifying functions other than the currently-analyzed function. As a function pass, AllocBoxToStack also doesn't really know with certainty whether the original closure function is unused after stack promotion or not. We still want to eliminate the original when it may contain invalid SIL for move-only values that rely on the escape analysis for correct semantics, so rather than mark the original function to be *ignored* during move-only checking, mark it to be *deleted* by move-only checking if the function is in fact unused at that point. If the marked function is still used, we let it pass through move-only checking normally, which may cause redundant diagnostics but is the right thing to do since code is still potentially using the closure with escaping semantics. We should rearrange things to make this situation impossible in the future. rdar://110675352
Thanks for the feedback @atrick and @eeckstein. I'll revert this and try another approach: #67205 |
…originals removed by MoveOnlyChecker. This is an improvement of swiftlang#67031 which avoids deleting the closure function body during AllocBoxToStack, which still breaks pass invariants by modifying functions other than the currently-analyzed function. As a function pass, AllocBoxToStack also doesn't really know with certainty whether the original closure function is unused after stack promotion or not. We still want to eliminate the original when it may contain invalid SIL for move-only values that rely on the escape analysis for correct semantics, so rather than mark the original function to be *ignored* during move-only checking, mark it to be *deleted* by move-only checking if the function is in fact unused at that point. If the marked function is still used, we let it pass through move-only checking normally, which may cause redundant diagnostics but is the right thing to do since code is still potentially using the closure with escaping semantics. We should rearrange things to make this situation impossible in the future. rdar://110675352
We can't remove the functions at this point in case they might have other function passes enqueued to run on them, but we can at least remove the function contents that are now unnecessary. We need to do this in cases when move-only types are involved, since the semantics of the move checker rely on unescaped captures being promoted before the pass runs, and we leave behind invalid SIL in the unpromoted code. rdar://110675352