When an owned value has no lifetime ending uses it means that it is in a dead-end region.
We must not remove and inserting compensating destroys for it because that would potentially destroy the value too early.
Initialization of an object might be cut off and removed after a dead-end loop or an `unreachable`.
In this case a class destructor would see uninitialized fields.
Fixes a mis-compile
https://github.com/swiftlang/swift/issues/85851
rdar://165876726
DeadCodeElimination can remove instructions including their destroys and then insert compensating destroys at a new place.
This is effectively destroy-hoisting which doesn't respect deinit-barriers.
Disable removing and re-creating `destroy_value` instructions. This is done by other optimizations.
Specifically, improved debug info retention in:
* tryReplaceRedundantInstructionPair,
* splitAggregateLoad,
* TempLValueElimination,
* Mem2Reg,
* ConstantFolding.
The changes to Mem2Reg allow debug info to be retained in the case tested by
self-nostorage.swift in -O builds, so we have just enabled -O in that file
instead of writing a new test for it.
We attempted to add a case to salvageDebugInfo for unchecked_enum_data, but it
caused crashes in Linux CI that we were not able to reproduce.
Empty access scopes can be a result of e.g. redundant-load-elimination.
It's still important to keep those access scopes to detect access violations.
Even if the load is physically not done anymore, in case of a conflicting access a propagated load is still wrong and must be detected.
rdar://164571252
This is necessary because we need to model its stack-allocation
behavior, although I'm not yet doing that in this patch because
StackNesting first needs to be taught to not try to move the
deallocation.
I'm not convinced that `async let` *should* be doing a stack allocation,
but it undoubtedly *is* doing a stack allocation, and until we have an
alternative to that, we will need to model it properly.
There is another near-identical function in DebugOptUtils.h that can be used
everywhere this function is used, and offers more flexibility in its callback
interface.
This pass removes `copy_addr` instructions.
However, it has some problems which causes compiler crashes.
It's not worth fixing these bugs because
1. Most copy_addrs can be eliminated by TempRValueElimination and TempLValueElimination.
2. Once we have opaque value we don't need copy_addr elimination, anyway.
rdar://162212460
This is a follow-up of https://github.com/swiftlang/swift/pull/84905, which handles non-copyable enums with a deinit correctly.
Also, for copyable enums it's more efficient to use `end_lifetime` than `destroy_value`, because we already know that the enum contains a trivial case.
Therefore no destroy operation is needed.
When replacing a `switch_enum` of an owned enum value with a branch to a non-payload case destination,
we need to insert a destroy of the enum value.
Fixes a SIL ownership verification failure.
https://github.com/swiftlang/swift/issues/84552
rdar://161482601
This pass has been disabled since a very long time (because it's terrible for code size).
It does not work for OSSA. Therefore it cannot be enabled anymore (as is) once we have OSSA throughout the pipeline.
So it's time to completely remove it.
The intent for `@inline(always)` is to act as an optimization control.
The user can rely on inlining to happen or the compiler will emit an error
message.
Because function values can be dynamic (closures, protocol/class lookup)
this guarantee can only be upheld for direct function references.
In cases where the optimizer can resolve dynamic function values the
attribute shall be respected.
rdar://148608854
This does not enable it by default. Use either of the flags:
```
-enable-copy-propagation
-enable-copy-propagation=always
```
to enable it in -Onone. The previous frontend flag
`-enable-copy-propagation=true` has been renamed to
`-enable-copy-propagation=optimizing`, which is currently default.
rdar://107610971
Since the time that lifetimes in `alloc_stack [lexical]` began to be
represented after promotion by `move_value [lexical]`s, the
`endOwnedLexicalLifetimeBeforeInst` is just an assertion. In the
future, lifetimes of values never destroyed that leak into dead end
blocks should be completed by OSSACompleteLifetime. For now, just
delete this code.
The lifetimes of the values stored into these locations may need to be
completed: if a trivial case of a non-trivial enum is written to the
location, its lifetime must be completed.
rdar://158139991
It is valid to leak a value on paths into dead-end regions.
Specifically, it is valid to leak an `alloc_box`. Thus, "final
releases" in dead-end regions may not destroy the box and consequently
may not release its contents. Therefore it's invalid to lower such final
releases to `dealloc_stack`s, let alone `destroy_addr`s. The in-general
invalidity of that transformation results in miscompiling whenever a box
is leaked and its projected address is used after such final releases.
Fix this by not treating final releases as boundary markers of the
`alloc_box` and not lowering them to `destroy_addr`s and
`dealloc_stack`s.
rdar://158149082
Enum types may have incomplete lifetimes in address form for trivial case values. When promoted to value form, they will end up with incomplete ossa lifetimes.
Because we know that the incomplete enum values are trivial enum cases we complete their lifetimes with `end_lifetime` instead of `destroy_value`.
This is especially important for Embedded Swift where we are not allowed to insert destroys which were not there before.
Fixes a compiler crash in Embedded Swift caused by de-virtualizing such an inserted destroy and ending up with a non-specialized generic function.
rdar://158807801