Skip to content
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 typed boxes to simplify capture representation in SILGen #13

Closed
wants to merge 8 commits into from
Closed

Use typed boxes to simplify capture representation in SILGen #13

wants to merge 8 commits into from

Conversation

jckarter
Copy link
Contributor

Now that SIL has @box T types, we no longer need to capture mutable variables as pairs of box and address. Here's a series of patches that simplifies the way SILGen emits captures so that they're only passed as boxes, along with follow-up changes to capture promotion, SILCombine, and DI to preserve their existing behavior. Until now, we also claimed that capture addresses were passed @inout, which is semantically incorrect—mutable captures are allowed to be mutated simultaneously from the closure and the original context in well-typed, well-synchronized ways. I introduced a new parameter convention @inout_aliasable to represent these semantics for @noescape mutable captures. I'd like some review of the various pieces before mashing into master:

@rjmccall, do the semantics of @inout_aliasable make sense to you? I'm not thrilled with the name, since we were already throwing aliasable around with the different meaning of "allow type-punned aliases through this pointer", which I don't want to allow.

@lattner, I changed SILGen to emit mark_function_escape instructions on variable addresses before they're captured; that way, DI still works on captured variables without having to do concurrent analysis of the box and address value uses. I also adjusted the diagnostics to use the more specific "captured by a closure" diagnostic when this happens, instead of the generic "used before initialized" diagnostic. Is there a better approach you'd prefer?

@rudkx, do the changes to capture promotion look reasonable? Are there any other passes you're aware of that would need updating to avoid optimizer regressions?

@adrian-prantl, there's a regression in debug info that I wasn't sure how to address, since the argument addresses are no longer passed directly. I could have SILGen emit debug_addr instructions to annotate the projections that get emitted on the callee side. Is that the right thing to do, or do we need extra information to flag these as arguments or captures instead of regular variables?

Now that boxes are typed and projectable, the address no longer has to be passed separately.

For now, this breaks capture promotion, DI, and debug info, which analyze uses of the address param. Will be addressed in upcoming commits:

    Swift :: DebugInfo/byref-capture.swift
    Swift :: DebugInfo/closure-args.swift
    Swift :: DebugInfo/closure-args2.swift
    Swift :: DebugInfo/inout.swift
    Swift :: DebugInfo/linetable.swift
    Swift :: SILPasses/capture_promotion.swift
    Swift :: SILPasses/definite_init_diagnostics.swift
Match the new SILGen pattern, where only the box parameter is partially applied to the closure, and the address of the value is projected on the callee side.
There's no longer a direct use of the variable's address when we invoke the closure, but we have a handy mark_function_escape instruction to mark the use without requiring merging analysis of the box and its contents. This also gives us a slightly more accurate error message when a variable is prematurely captured, noting the variable was captured by a closure instead of just generically used.
Modeling nonescaping captures as @inout parameters is wrong, because captures are allowed to share state, unlike 'inout' parameters, which are allowed to assume to some degree that there are no aliases during the parameter's scope. To model this, introduce a new @inout_aliasable parameter convention to indicate an indirect parameter that can be written to, not only by the current function, but by well-typed, well-synchronized aliasing accesses too. (This is unrelated to our discussions of adding a "type-unsafe-aliasable" annotation to pointer_to_address to allow for safe pointer punning.)
This unblocks existing load/store optimizations when a closure is inlined and the original boxed value is exposed.
@rjmccall
Copy link
Contributor

The semantics seems good to me. I think "aliased", "aliasing", or "aliasable" is right term for this, and we should chose a stronger and more specific name for things that are allowed to violate TBAA.

@rudkx
Copy link
Contributor

rudkx commented Nov 30, 2015

@jckarter I don't know of other optimizations that need to be updated for this, but it would be good to do a benchmark run as a sanity check before it gets merged to master.

@gribozavr
Copy link
Contributor

The combined patch XFAILs some tests. Is that intended?

@jckarter
Copy link
Contributor Author

jckarter commented Dec 1, 2015

@gribozavr Yes, as I noted in the patch description, it regresses debug information for boxed captures. I wasn't sure what the proper way to fix this was, so I'm awaiting @adrian-prantl's feedback.

@lattner
Copy link
Contributor

lattner commented Dec 1, 2015

On Nov 30, 2015, at 10:32 AM, Joe Groff notifications@github.com wrote:

Now that SIL has @box T types, we no longer need to capture mutable variables as pairs of box and address. Here's a series of patches that simplifies the way SILGen emits captures so that they're only passed as boxes, along with follow-up changes to capture promotion, SILCombine, and DI to preserve their existing behavior. Until now, we also claimed that capture addresses were passed @inout, which is semantically incorrect—mutable captures are allowed to be mutated simultaneously from the closure and the original context in well-typed, well-synchronized ways. I introduced a new parameter convention @inout_aliasable to represent these semantics for @NoEscape mutable captures. I'd like some review of the various pieces before mashing into master:

@lattner https://github.com/lattner, I changed SILGen to emit mark_function_escape instructions on variable addresses before they're captured; that way, DI still works on captured variables without having to do concurrent analysis of the box and address value uses. I also adjusted the diagnostics to use the more specific "captured by a closure" diagnostic when this happens, instead of the generic "used before initialized" diagnostic. Is there a better approach you'd prefer?

The DI and related SILGen changes look great to me. Thanks for doing this, it is an really nice cleanup too. One bad thing is that it invalidates some slides from our SIL talk :-)

-Chris

@jckarter
Copy link
Contributor Author

jckarter commented Dec 1, 2015

I guess we have to give the talk again at Barcelona next year then. Thanks for the review!

@jckarter
Copy link
Contributor Author

jckarter commented Dec 4, 2015

Thanks for the feedback everyone! With @adrian-prantl's recent fixes the proper debug info appears to fall out. Going public seems to have messed with the connection in the pull request; I'll finish this up out of band.

@jckarter jckarter closed this Dec 4, 2015
slavapestov pushed a commit to slavapestov/swift that referenced this pull request Nov 27, 2018
…nd-use-libbsd

Port transform and use libbsd
slavapestov pushed a commit to slavapestov/swift that referenced this pull request Nov 27, 2018
…nd-use-libbsd

Port transform and use libbsd

Signed-off-by: Daniel A. Steffen <dsteffen@apple.com>
kateinoigakukun referenced this pull request in kateinoigakukun/swift Nov 15, 2019
This allows running build commands in a reproducible way either locally or with any other CI.

* Move CI build commands to separate scripts
* Run CI on pushes to `swiftwasm` branch
* Split build and setup steps into separate scrtipts
* Fix execution directories in the build scripts
lorentey pushed a commit that referenced this pull request Dec 11, 2019
kateinoigakukun referenced this pull request in kateinoigakukun/swift Dec 14, 2019
This allows running build commands in a reproducible way either locally or with any other CI.

* Move CI build commands to separate scripts
* Run CI on pushes to `swiftwasm` branch
* Split build and setup steps into separate scrtipts
* Fix execution directories in the build scripts
kateinoigakukun referenced this pull request in kateinoigakukun/swift Jan 11, 2020
This allows running build commands in a reproducible way either locally or with any other CI.

* Move CI build commands to separate scripts
* Run CI on pushes to `swiftwasm` branch
* Split build and setup steps into separate scrtipts
* Fix execution directories in the build scripts
MaxDesiatov referenced this pull request in MaxDesiatov/swift May 1, 2020
This allows running build commands in a reproducible way either locally or with any other CI.

* Move CI build commands to separate scripts
* Run CI on pushes to `swiftwasm` branch
* Split build and setup steps into separate scrtipts
* Fix execution directories in the build scripts
DougGregor pushed a commit to DougGregor/swift that referenced this pull request Apr 28, 2024
Windows: add developer tools packaging rules
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.

5 participants