Skip to content

[SIL] Added borrow scopes to alloc_boxes. #40793

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

Conversation

nate-chandler
Copy link
Contributor

Because AllocBoxToStack is not able to transform every alloc_box into an alloc_stack, it's necessary to add begin_borrow [lexical] to every alloc_box in order to provide lexical scopes for those alloc_boxes which will not be transformed into alloc_stacks.

Now that alloc_boxes whose lifetimes are lexical are emitted with begin_borrow [lexical]/end_borrow, AllocBoxToStack needs to be able to see through those new borrow scopes in order to continue stack promoting the same boxes that it was able to before those lexical scopes were emitted.

@nate-chandler nate-chandler marked this pull request as draft January 11, 2022 02:13
@nate-chandler nate-chandler requested a review from atrick January 11, 2022 03:41
@nate-chandler nate-chandler force-pushed the silgen/emit-borrow-scopes-for-alloc_boxes branch 3 times, most recently from d411337 to 3293c8e Compare January 13, 2022 16:05
@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
Because AllocBoxToStack is not able to transform every alloc_box into an
alloc_stack, it's necessary to add begin_borrow [lexical] to every
alloc_box in order to provide lexical scopes for those alloc_boxes which
will not be transformed into alloc_stacks.
Now that alloc_boxes whose lifetimes are lexical are emitted with
begin_borrow [lexical]/end_borrow, AllocBoxToStack needs to be able to
see through those new borrow scopes in order to continue stack promoting
the same boxes that it was able to before those lexical scopes were
emitted.
@nate-chandler nate-chandler force-pushed the silgen/emit-borrow-scopes-for-alloc_boxes branch from 3293c8e to f19e413 Compare January 13, 2022 21:34
@nate-chandler nate-chandler marked this pull request as ready for review January 13, 2022 21:34
@nate-chandler
Copy link
Contributor Author

@swift-ci please benchmark

@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
@swift-ci
Copy link
Contributor

Performance (x86_64): -O

Regression OLD NEW DELTA RATIO
FlattenListLoop 1664 2547 +53.1% 0.65x (?)
FlattenListFlatMap 4770 5843 +22.5% 0.82x (?)
NSStringConversion.Rebridge.Medium 170 184 +8.2% 0.92x (?)
NSStringConversion.Rebridge.Long 171 184 +7.6% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
ArrayAppendGenericStructs 2470 2020 -18.2% 1.22x (?)
String.data.Small 56 50 -10.7% 1.12x (?)
Breadcrumbs.MutatedUTF16ToIdx.Mixed 287 263 -8.4% 1.09x (?)
NSStringConversion.Rebridge.LongUTF8 55 51 -7.3% 1.08x (?)
Diffing.Myers.Similar 541 502 -7.2% 1.08x (?)
NSStringConversion.Rebridge.UTF8 458 425 -7.2% 1.08x (?)

Code size: -O

Performance (x86_64): -Osize

Regression OLD NEW DELTA RATIO
NSError 190 213 +12.1% 0.89x (?)

Code size: -Osize

Performance (x86_64): -Onone

Regression OLD NEW DELTA RATIO
DictionaryBridgeToObjC_BulkAccess 169 187 +10.7% 0.90x (?)
 
Improvement OLD NEW DELTA RATIO
NSError 837 751 -10.3% 1.11x (?)

Code size: -swiftlibs

How to read the data The 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
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac Pro
  Model Identifier: MacPro6,1
  Processor Name: 12-Core Intel Xeon E5
  Processor Speed: 2.7 GHz
  Number of Processors: 1
  Total Number of Cores: 12
  L2 Cache (per Core): 256 KB
  L3 Cache: 30 MB
  Memory: 64 GB

@swiftlang swiftlang deleted a comment from swift-ci Jan 13, 2022
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.

Thanks! That's a ton of tests to fix!

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - f19e413

@nate-chandler
Copy link
Contributor Author

@swift-ci please test macos platform

@nate-chandler nate-chandler merged commit 5fcac08 into swiftlang:main Jan 14, 2022
@nate-chandler nate-chandler deleted the silgen/emit-borrow-scopes-for-alloc_boxes branch January 14, 2022 15:32
nate-chandler added a commit to nate-chandler/swift that referenced this pull request Mar 11, 2022
After swiftlang#40793, alloc_boxes all have
their lifetimes protected by a lexical borrow scope.  In that PR, DI had
been updated to see through begin_borrow instructions from a project_box
to a mark_uninitialized.  It did not, however, correct the end_borrow
instructions when destroy_values of mark_uninitializeds were replaced
with destroy_addrs of project_boxes.  That is done here.

In a bit more detail, in the following context

    %box = alloc_box
    %mark_uninit = mark_uninitialized %box
    %lifetime = begin_borrow [lexical] %mark_uninit
    %proj_box = project_box %lifetime

When it is not statically known whether a field is initialized, we are
replacing the instruction

      // before
      destroy_value %mark_uninit
      // after

with the following diamond

      // before
      %initialized = load
      cond_br %initialized, yes, no

    yes:
      destroy_addr %proj_box
      br bottom

    no:
      br bottom

    bottom:
      dealloc_box %box
      br keep_going

    keep_going:
      // after

Doing so is problematic, though, because by SILGen construction the
destroy_value is always preceded by an end_borrow:

      end_borrow %lifetime
      destroy_value %mark_uninit

Previously, that end_borrow remained above the

      %initialized = load

instruction in the above.  That was invalid because the the newly
introduced

      destroy_addr %proj_box

was a use of the borrow scope (%proj_box is a projection of the
begin_borrow) and consequently must be within the borrow scope.

Note also that it would not be sufficient to simply emit the diamond
before the end_borrow.  The end_borrow must come before the destruction
of the value whose lifetime it is protecting (%box), and the diamond
contains the instruction to destroy that value (dealloc_box) in its
bottom block.

To resolve this issue, just move the end_borrow instruction from where
it was to before the dealloc box.  (This is actually done by moving it to
the top of the diamond's "continue" block prior to the emission of that
dealloc_box instruction.)

rdar://89984216
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.

3 participants