Skip to content

Code Size: Pass large loadable types by address instead of by value - Updated Version #9142

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 3 commits into from
May 1, 2017

Conversation

shajrawi
Copy link

radar rdar://problem/28680453

This is an updated version of #8909

It addresses the code review comments and splits the PR into multiple commits

Reduce the size of the text area (code size of the compiled output) by changing the way we generate LLVM IR for loadable types:

We do a SIL level transformation, during IRGen, that, from a bird's eye view, does the following:
For every every function that takes as an input a big type, re-write it to take a pointer to a big type instead.
: $@convention(method) (BigStruct) turns into $@convention(method) (@in_constant BigStruct)

There are a few new SIL pieces to support this:

  • A @in_constant calling convention
  • New retain_value_addr and release_value_addr SIL instructions that take as an input an address, load the value inside it and call retain_value and release_value respectively
  • New outlined functions that do retains and releases of large values

Please note:

  • For outlined retain/release, I currently create a function per large type in IRGen, re-using the retain/releases from the value-witness table is less efficient than a direct call to a smaller function
  • We currently add new alloc_stack instructions and, in some cases, load of the function arguments to make this work. The current implementation, while it has some peephole optimizations for the most painful cases, is still very conservative: we can update this in the future, further reducing the code size
  • In case we had call to a function that takes a $BigType, and now takes $*BigType, there are cases wherein we create new alloc_stack and store instructions in order to call said function. Just like the point made above - the current implementation is very conservative / can be further optimized. this will be done in phases

The radar mentioned in this PR contains a test program called BigTypeProg: This program contains a big struct with some loadable types + a class / need for retain and release. Passes it around to different functions that access the struct.

Under -Onone we have 3X binary size reduction, under -O a 2X binary size reduction. The text area is reduced by around 84% and 65% respectively.

Joe Shajrawi added 2 commits April 30, 2017 10:13
… input an address, load the value inside it and call retain_value and release_value respectively
@shajrawi shajrawi force-pushed the loadable_by_addr_split branch 13 times, most recently from f1d07de to c09636a Compare May 1, 2017 18:44
@shajrawi shajrawi force-pushed the loadable_by_addr_split branch from c09636a to 4dc0801 Compare May 1, 2017 19:04
@shajrawi
Copy link
Author

shajrawi commented May 1, 2017

@swift-ci Please smoke test

@bob-wilson
Copy link
Contributor

The Linux failure here does not have anything to do with these changes.

@bob-wilson bob-wilson merged commit 84d1630 into swiftlang:master May 1, 2017
@shajrawi shajrawi deleted the loadable_by_addr_split branch May 5, 2017 05:45
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