Skip to content

Commit 0326c98

Browse files
committed
LifetimeDependenceScopeFixup: handle unsafe addressors
Handle unsafe addressors just like projections of stored properties rather than as separate variable accesses.
1 parent b0f2ca0 commit 0326c98

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,12 +638,34 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
638638

639639
mutating func walkUp(address: Value) -> WalkResult {
640640
if let beginAccess = address.definingInstruction as? BeginAccessInst {
641+
// Treat calls to unsafe[Mutable]Address like a projection of 'self' rather than a separate variable access.
642+
if let addressorSelf = beginAccess.unsafeAddressorSelf {
643+
return walkUp(valueOrAddress: addressorSelf)
644+
}
641645
return introducer(beginAccess, nil)
642646
}
643647
return walkUpDefault(address: address)
644648
}
645649
}
646650

651+
private extension BeginAccessInst {
652+
// Recognize an access scope for a unsafe addressor:
653+
// %adr = pointer_to_address
654+
// %md = mark_dependence %adr
655+
// begin_access [unsafe] %md
656+
var unsafeAddressorSelf: Value? {
657+
guard isUnsafe else {
658+
return nil
659+
}
660+
let accessBaseAndScopes = address.accessBaseWithScopes
661+
guard case .pointer = accessBaseAndScopes.base,
662+
case let .dependence(markDep) = accessBaseAndScopes.scopes.first else {
663+
return nil
664+
}
665+
return markDep.base
666+
}
667+
}
668+
647669
/// Walk up the lifetime dependence chain.
648670
///
649671
/// This finds the introducers of a dependence chain. which represent the value's "inherited" dependencies. This stops

test/SILOptimizer/lifetime_dependence/semantics.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,34 @@ extension Array {
7474
}
7575
}
7676

77+
struct Inner {
78+
var p: UnsafePointer<Int>
79+
80+
@lifetime(borrow self)
81+
borrowing func span() -> Span<Int> {
82+
Span(base: p, count: 1)
83+
}
84+
}
85+
86+
struct Outer {
87+
let inner: Inner
88+
let fakePointer: UnsafePointer<Inner>
89+
90+
var innerAddress: Inner {
91+
unsafeAddress {
92+
fakePointer
93+
}
94+
}
95+
/* TODO: rdar://137608270 Add Builtin.addressof() support for @addressable arguments
96+
@addressableSelf
97+
var innerAddress: Inner {
98+
unsafeAddress {
99+
Builtin.addressof(inner)
100+
}
101+
}
102+
*/
103+
}
104+
77105
func parse(_ span: Span<Int>) {}
78106

79107
// =============================================================================
@@ -172,3 +200,17 @@ func testTrivialScope<T>(a: Array<T>) -> Span<T> {
172200
// expected-note @-3{{it depends on the lifetime of variable 'p'}}
173201
// expected-note @-3{{this use causes the lifetime-dependent value to escape}}
174202
}
203+
204+
// =============================================================================
205+
// Scoped dependence on property access
206+
// =============================================================================
207+
208+
@lifetime(borrow outer)
209+
func testBorrowComponent(outer: Outer) -> Span<Int> {
210+
outer.inner.span()
211+
}
212+
213+
@lifetime(borrow outer)
214+
func testBorrowAddressComponent(outer: Outer) -> Span<Int> {
215+
outer.innerAddress.span()
216+
}

0 commit comments

Comments
 (0)