allLifetimeEndingInstructions collects insertion points for end_borrows,
and can end up having duplicate entries in the case of enums with non payloaded cases.
Unique the entries so we don't end up with multiple end_borrows
Fixes rdar://146212574
Set the visitInnerUses flag. This is only a quick, partial fix.
InteriorUseWalker does not generate complete liveness for two reasons
1. pointer escapes. The client must always check for escapes before assuming
complete liveness.
2. dead end blocks. Until we have complete OSSA lifetimes, the algorithm for
handling nested borrows is incorrect. The visitInnerUses flag works around this
problem, but it isn't well tested and I'm not sure it's properly records escapes yet.
Needed to diagnose MutableSpan and OutputSpan.
For now, simply remove the bailout and TODO. The next change will introduce more
logic to force a diagnostic error in rare cases that can't be handled completely.
Fixes rdar://143584461 (Extended exclusive borrow issues with
MutableSpan and OutputSpan)
Functional changes:
Improved modeling of dependence on local variable scopes.
For nested modify->read accesses, only extend the read accesses.
Avoid making a read access dependent on an inout argument.
The following needs to be an error to prevent span storage from being modified:
@lifetime(owner)
foo(owner: inout Owner) -> Span {
owner.span
}
Improve usability of borrowing trivial values (UnsafePointer). Allow:
let span = Span(buffer.baseAddress)
Ignore access scopes for trivial values.
Structural changes:
Delete the LifetimeDependenceUseDefWalker.
Encapsulate all logic for variable introducers within the LifetimeDependenceInsertion pass. Once mark_dependence instructions are inserted, no subsequent pass needs to think about the "root" of a dependence.
Fixes: rdar://142451725 (Escape analysis fails with mutations)
If the memory location depends on something, insert a dependency for the loaded value:
```
%2 = mark_dependence %1 on %0
%3 = load %2
```
->
```
%2 = mark_dependence %1 on %0 // not needed anymore, can be removed eventually
%3 = load %2
%4 = mark_dependence %3 on %0
// replace %3 with %4
```
Memory effects of begin_access are only defined to prevent the optimizer moving loads and stores across a begin_access.
But those memory effects are not relevant for RedundantLoadElimination
The problem with `is_escaping_closure` was that it didn't consume its operand and therefore reference count checks were unreliable.
For example, copy-propagation could break it.
As this instruction was always used together with an immediately following `destroy_value` of the closure, it makes sense to combine both into a `destroy_not_escaped_closure`.
It
1. checks the reference count and returns true if it is 1
2. consumes and destroys the operand
This encourages AccessPathWalker clients to handle enclosing mark_deps. In
some cases, it is necessary. The accessBaseWithScopes API now provides both
nested begin_access and mark_dependence.
A `unchecked_enum_data` which extracts a trivial payload out of a non-trivial enum ends the lifetime of its owned operand.
Fixes an ownership verification error
rdar://142644731
This pass rewrites mark_depenendence to ignore "useless" borrow scopes. It was
also accidentally rewriting a dependence on a loaded value, which may redirect the
dependence to the access scope used to load that value. That access scope may be
narrower than the lifetime of the loaded value which could result in invalid
SIL. Do not rewrite this mark_dependence:
%access = begin_access [read] [unknown] %base
%load = load [trivial] %access
end_access %access
%adr = pointer_to_address
%md = mark_dependence [unresolved] %adr on %load
Fixes rdar://142424000 (Swift compiler crashes with Assertion failed
(isa<UnreachableInst>(block->getTerminator())))
* `users`: maps from a sequence of operands to a sequence of instructions
* `users(ofType:)` : as `users`, but filters users of a certain instruction type
* `Value.users`: = `Value.uses.users`
Briefly, some versions of Span in the standard library violated trivial
lifetimes; versions of the compiler built at that time simply ignored
dependencies on trivial values. For now, disable trivial dependencies to allow
newer compilers to build against those older standard libraries. This check is
only relevant for ~6 mo (until July 2025).
Handle all combinations of nested dependence scopes: access scopes, coroutines,
and borrow scopes.
This is required to enforce ~Escapable _read accessors and unsafeAddress addressors.
Fixes rdar://140424699 (Invalid SIL is generated by some passes for certain
@lifetime annotations)
With OSSA it can happen more easily that the final release is not immediately located before the related dealloc_stack_ref.
Therefore do a more precise check (using escape analysis) if any instruction between a release and a dealloc_stack_ref might (implicitly) release the allocated object.
This is part of fixing regressions when enabling OSSA modules:
rdar://140229560
It hoists `destroy_value` instructions without shrinking an object's lifetime.
This is done if it can be proved that another copy of a value (either in an SSA value or in memory) keeps the referenced object(s) alive until the original position of the `destroy_value`.
```
%1 = copy_value %0
...
last_use_of %0
// other instructions
destroy_value %0 // %1 is still alive here
```
->
```
%1 = copy_value %0
...
last_use_of %0
destroy_value %0
// other instructions
```
The benefit of this optimization is that it can enable copy-propagation by moving destroys above deinit barries and access scopes.
It removes a `copy_value` where the source is a guaranteed value, if possible:
```
%1 = copy_value %0 // %0 = a guaranteed value
// uses of %1
destroy_value %1 // borrow scope of %0 is still valid here
```
->
```
// uses of %0
```
This optimization is very similar to the LoadCopyToBorrow optimization.
Therefore I merged both optimizations into a single file and renamed it to "CopyToBorrowOptimization".
Scope-ending instructions, like `end_borrow` are only irrelevant for RLE if the preceding load is not changed.
If it is changed from `load [copy]` -> `load [take]` the memory effects of those scope-ending instructions prevent that the `load [take]` will illegally mutate memory which is protected from mutation by the scope.
Fixes a memory verifier crash
rdar://139824805