-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
Use stack allocation for Swift closures #21933
Use stack allocation for Swift closures #21933
Conversation
It does not take ownership of its non-trivial arguments, is a trivial function type and therefore must not be destroyed. The compiler must make sure to extend the lifetime of non-trivial arguments beyond the last use of the closure. %objc = copy_value %0 : $AnObject %closure = partial_apply [stack] [callee_guaranteed] %16(%obj) : $@convention(thin) (@guaranteed AnObject) -> () %closure2 = mark_dependence %closure : $@NoEscape @callee_guaranteed () -> () on %obj : $AnObject %user = function_ref @useClosure : $@convention(thin) (@NoEscape @callee_guaranteed () -> ()) -> () apply %user(%closure2) : $@convention(thin) (@NoEscape @callee_guaranteed () -> ()) -> () dealloc_stack %closure : $() ->() destroy_value %obj : $AnObject // noescape closure does not take ownership SR-904 rdar://35590578
@swift-ci Please test |
@swift-ci Please test source compatibility |
@swift-ci Please smoke benchmark |
Build failed |
Build comment file:Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
Code size: -swiftlibs
How to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
Build failed |
nice! |
+1! |
😍 Thank you! Are there any guidelines or guarantees as to when this will and will not kick in that we can rely on? I'd like to add a section to stdlib programmer's manual. |
@milseman While it is a best effort as this matches patterns I expect any closure directly passed to a swift closure parameter to be allocated on the stack.
Objective-C block arguments remain allocated on the heap for now. |
What would be an example of a pattern match failure? Is there any way we can write tests to enforce this better? We pretty much have to make all closure-taking functions inlinable currently, and this could help with that. But, the only source-level test I see here calls an |
… reuses heap object as context
We need to recreate instructions in order as some instructions result type dependends on its operand
@swift-ci Please test |
Build failed |
Build failed |
… eliminate all dealloc_stack instructions in the block
@swift-ci Please test |
@swift-ci Please test source compatibility |
Build failed |
Build failed |
@swift-ci Please test |
Build failed |
Build failed |
@swift-ci Please test |
Build failed |
Build failed |
@milseman I am going to add a more comprehensive set of tests that verify that the closure is stack allocated in a followup PR: aschwaighofer/swift@partial_apply_stack...aschwaighofer:partial_apply_stack_tests |
@aschwaighofer Can you add documentation around triviality/ownership to SIL.rst. I was trying to reason about this today and I had no clue. |
nm I found it. |
Adds an
on_stack
version ofpartial_apply
It does not take ownership of its non-trivial arguments, is a trivial
function type and therefore must not be destroyed. The compiler must
make sure to extend the lifetime of non-trivial arguments beyond the
last use of the closure.
Closure lifetime fixup will use
partial_apply [on_stack]
as appropriate.SR-904
rdar://35590578