Skip to content

Add support for a mandatory-copy-propagation pass. #36245

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 10 commits into from
Mar 3, 2021

Conversation

atrick
Copy link
Contributor

@atrick atrick commented Mar 3, 2021

It is currently disabled so this commit is NFC.

MandatoryCopyPropagation canonicalizes all all OSSA lifetimes with
either CopyValue or DestroyValue operations. While regular
CopyPropagation only canonicalizes lifetimes with copies. This ensures
that more lifetime program bugs are found in debug builds. Eventually,
regular CopyPropagation will also canonicalize all lifetimes, but for
now, we don't want to expose optimized code to more behavior change
than necessary.

Add frontend flags for developers to easily control copy propagation:

-enable-copy-propagation: enables whatever form of copy propagation the current pipeline runs (mandatory-copy-propagation at -Onone, regular copy-propation at -O).

-disable-copy-propagation: similarly disables any form of copy
propagation in the current pipelien.

To control a specific variant of the passes, use
-Xllvm -disable-pass=mandatory-copy-propagation
or -Xllvm -disable-pass=copy-propagation instead.

The meaning of these flags will stay the same as we adjust the
defaults. Soon mandatory-copy-propagation will be enabled by
default. There are two reasons to do this, both related to predictable
behavior across Debug and Release builds.

  1. Shortening object lifetimes can cause observable changes in program
    behavior in the presense of weak/unowned reference and
    deinitializer side effects.

  2. Programmers need to know reliably whether a given code pattern will
    copy the storage for copy-on-write types (Array, Set). Eliminating
    the "unexpected" copies the same way at -Onone and -O both makes
    debugging tractable and provides assurance that the code isn't
    relying on the luck of the optimizer in a particular compiler
    release.

atrick added 9 commits March 2, 2021 22:19
It is currently disabled so this commit is NFC.

MandatoryCopyPropagation canonicalizes all all OSSA lifetimes with
either CopyValue or DestroyValue operations. While regular
CopyPropagation only canonicalizes lifetimes with copies. This ensures
that more lifetime program bugs are found in debug builds. Eventually,
regular CopyPropagation will also canonicalize all lifetimes, but for
now, we don't want to expose optimized code to more behavior change
than necessary.

Add frontend flags for developers to easily control copy propagation:

-enable-copy-propagation: enables whatever form of copy propagation
 the current pipeline runs (mandatory-copy-propagation at -Onone,
 regular copy-propation at -O).

-disable-copy-propagation: similarly disables any form of copy
 propagation in the current pipelien.

To control a specific variant of the passes, use
   -Xllvm -disable-pass=mandatory-copy-propagation
or -Xllvm -disable-pass=copy-propagation instead.

The meaning of these flags will stay the same as we adjust the
defaults. Soon mandatory-copy-propagation will be enabled by
default. There are two reasons to do this, both related to predictable
behavior across Debug and Release builds.

1. Shortening object lifetimes can cause observable changes in program
   behavior in the presense of weak/unowned reference and
   deinitializer side effects.

2. Programmers need to know reliably whether a given code pattern will
   copy the storage for copy-on-write types (Array, Set). Eliminating
   the "unexpected" copies the same way at -Onone and -O both makes
   debugging tractable and provides assurance that the code isn't
   relying on the luck of the optimizer in a particular compiler
   release.
This bleeds into the implementation where "guaranteed" is used
everywhere to talk about optimization of guaranteed values. We need to
use mandatory to indicate we're talking about the pass pipeline.
-enable-copy-propagation: enables whatever form of copy propagation
 the current pipeline runs (mandatory-copy-propagation at -Onone,
 regular copy-propation at -O).

-disable-copy-propagation: similarly disables any form of copy
 propagation in the current pipelien.
Otherwise the verifier will fail on trivial cases like this:

sil hidden [ossa] @testassign : $@convention(thin) <T> (@inout T, @in T) -> () {
bb0(%0 : $*T, %1 : @owned $T):
  store %1 to [assign] %0 : $*T
  %3 = tuple ()
  return %3 : $()
}

SIL memory lifetime failure in @testassign: memory is initialized at
function return but shouldn't memory location:
  %1 = argument of bb0 : $T
Move opaque-value tests into copy_propagation_opaque.sil.
@atrick atrick requested a review from gottesmm March 3, 2021 06:21
@atrick
Copy link
Contributor Author

atrick commented Mar 3, 2021

@swift-ci test

@atrick
Copy link
Contributor Author

atrick commented Mar 3, 2021

@swift-ci smoke test

@atrick atrick merged commit c7f2130 into swiftlang:main Mar 3, 2021
@atrick atrick deleted the mandatory-copyprop branch October 18, 2022 23:56
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.

1 participant