* rename `ScopedInstruction.endOperands` -> `scopeEndingOperands`
* let them behave the same way. For `load_borrow` there was a difference because `endOperands` didn't consider branches to re-borrow phis.
Briefly (April 2025), RawSpan._extracting, Span._extracting, and UTF8Span.span
returned a borrowed value that depended on a copied argument. Continue to
support those interfaces. The implementations were correct but needed an
explicit _overrideLifetime.
Diagnose a scoped dependence on an argument that inherits its lifetime as an
error:
@lifetime(borrow arg)
func reborrowSpan<T>(_ arg: Span<T>) -> Span<T> { arg }
@lifetime(copy span)
public func testBorrowInheritedArg<T>(_ span: Span<T>) -> Span<T> {
reborrowSpan(span) // expected-error {{lifetime-dependent value escapes its scope}}
}
Fixes: rdar://146319009 ([nonescapable] enforce borrow constraint narrowing of inherited lifetime)
For example:
```
%0 = load %1
copy_addr %1 to %2
```
->
```
%0 = load %1
store %0 to %2
```
This is important for MandatoryRedundantLoadElimination to be able to create statically initialized globals in the mandatory pipeline.
For example:
```
public struct MyStruct {
public static let r: Range<Int> = 1 ..< 3
}
```
gets a statically initialized global, even at Onone, with this improvement.
rdar://149356742
Allow a dependency on a local [read] access scope to be transfered to the
caller's [modify] access.
Fixes rdar://149560133 (Invalid lifetime dependence error when
trying to return Span from an inout argument)
Add support for returnValue phis (e.g. to return an Optional .some or .none).
Fixes rdar://149397018 (Wrapping non escapable in an Optional
(or any copy lifetime wrapper) is an escape)
* move it from the SIL to the AST module (where it belongs)
* change the signature of `diagnose` from `diagnose(location, .some_error)` to `diagnose(.some_error, at: location)`
* add an overload to allow passing a `SIL.Location` directly to `diagnose`
* add a `Diagnostic : Error` utility struct which allows throwing a `Diagnostic`
Add support for extending owned temporary values in addition to access scopes
and borrow scopes. Required for _read accessors in which the coroutine depends
on an owned value.
SwiftCompilerSources for Windows is now fully enabled, so there is no
longer any reason to gate these passes under an OS check.
commit d482ab73bc
Author: Hiroshi Yamauchi <hjyamauchi@gmail.com>
Date: Fri Dec 13 09:24:44 2024 -0800
Update the pinned toolchain for Windows and enable SwiftCompilerSources for Win/ARM64
Fixes a false alarm in case of recursive calls with different type parameters.
For example:
```
protocol P {
associatedtype E: P
}
func noRecursionMismatchingTypeArgs1<T: P>(_ t: T.Type) {
if T.self == Int.self {
return
}
noRecursionMismatchingTypeArgs1(T.E.self)
}
```
With this approach, you cannot tell whether a parameter is addressable only
from the function type. Instead you need the SILValue that will be passed to the
call site.
* let `SIL.Type` conform to `TypeProperties` to share the implementation of common type properties between the AST types and `SIL.Type`
* call references to an `AST.Type` `rawType` (instead of just `type`)
* remove unneeded stuff
* add comments
Otherwise, DestroyHoisting attemps to compute interior liveness
and inserts destoys at the ends. CanonicalizeOSSALifetimes is
designed to do this and not DestroyHoisting.
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