Skip to content

Commit 68037fa

Browse files
committed
LifetimeDependenceScopeFixup: handle nested access
After extending access scopes, rewrite the mark_depenendence to be on the outermost scope.
1 parent f0b0400 commit 68037fa

File tree

6 files changed

+94
-16
lines changed

6 files changed

+94
-16
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceScopeFixup.swift

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,26 @@ let lifetimeDependenceScopeFixupPass = FunctionPass(
3737
guard let markDep = instruction as? MarkDependenceInst else {
3838
continue
3939
}
40-
if let lifetimeDep = LifetimeDependence(markDep, context) {
41-
fixup(dependence: lifetimeDep, context)
40+
guard let lifetimeDep = LifetimeDependence(markDep, context) else {
41+
continue
42+
}
43+
guard let beginAccess = extendAccessScopes(dependence: lifetimeDep,
44+
context) else {
45+
continue
4246
}
47+
extendDependenceBase(dependenceInstruction: markDep,
48+
beginAccess: beginAccess, context)
4349
}
4450
}
4551

46-
private func fixup(dependence: LifetimeDependence,
47-
_ context: FunctionPassContext) {
52+
// Extend all access scopes that enclose `dependence` and return the
53+
// outermost access.
54+
private func extendAccessScopes(dependence: LifetimeDependence,
55+
_ context: FunctionPassContext) -> BeginAccessInst? {
4856
log("Scope fixup for lifetime dependent instructions: \(dependence)")
4957

5058
guard case .access(let bai) = dependence.scope else {
51-
return
59+
return nil
5260
}
5361
var range = InstructionRange(begin: bai, context)
5462
var walker = LifetimeDependenceScopeFixupWalker(bai.parentFunction, context) {
@@ -89,6 +97,29 @@ private func fixup(dependence: LifetimeDependence,
8997
}
9098
beginAccess = enclosingBeginAccess
9199
}
100+
return beginAccess
101+
}
102+
103+
/// Rewrite the mark_dependence to depend on the outermost access
104+
/// scope now that the nested scopes have all been extended.
105+
private func extendDependenceBase(dependenceInstruction: MarkDependenceInst,
106+
beginAccess: BeginAccessInst,
107+
_ context: FunctionPassContext) {
108+
guard case let .base(accessBase) = beginAccess.address.enclosingAccessScope
109+
else {
110+
fatalError("this must be the outer-most access scope")
111+
}
112+
// If the outermost access is in the caller, then depende on the
113+
// address argument.
114+
let baseAddress: Value
115+
switch accessBase {
116+
case let .argument(arg):
117+
assert(arg.type.isAddress)
118+
baseAddress = arg
119+
default:
120+
baseAddress = beginAccess
121+
}
122+
dependenceInstruction.baseOperand.set(to: baseAddress, context)
92123
}
93124

94125
private struct LifetimeDependenceScopeFixupWalker : LifetimeDependenceDefUseWalker {

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ extension LifetimeDependence {
233233

234234
/// Construct LifetimeDependence from mark_dependence [unresolved]
235235
///
236+
/// For any LifetimeDependence constructed from a mark_dependence,
237+
/// its `dependentValue` will be the result of the mark_dependence.
238+
///
236239
/// TODO: Add SIL verification that all mark_depedence [unresolved]
237240
/// have a valid LifetimeDependence.
238241
init?(_ markDep: MarkDependenceInst, _ context: some Context) {

test/SILOptimizer/lifetime_dependence_borrow.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,8 @@ func bv_get_borrow(container: borrowing NC) -> _borrow(container) BV {
4242
func bv_get_copy(container: borrowing NC) -> _copy(container) BV {
4343
return container.getBV()
4444
}
45+
46+
// Recognize nested accesses as part of the same dependence scope.
47+
func bv_get_mutate(container: inout NC) -> _mutate(container) BV {
48+
container.getBV()
49+
}

test/SILOptimizer/lifetime_dependence_inherit.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ struct NE {
3939
}
4040

4141
// Test lifetime inheritance through chained consumes.
42-
//
43-
// This requires an inherit_lifetime marker on the argument.
4442
func bv_derive(bv: consuming BV) -> _consume(bv) BV {
4543
bv.derive()
4644
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: %target-swift-frontend %s -emit-sil \
2+
// RUN: -sil-verify-all \
3+
// RUN: -module-name test \
4+
// RUN: -disable-experimental-parser-round-trip \
5+
// RUN: -enable-experimental-feature NonescapableTypes \
6+
// RUN: -Xllvm -enable-lifetime-dependence-diagnostics \
7+
// RUN: 2>&1 | %FileCheck %s
8+
9+
// REQUIRES: swift_in_compiler
10+
11+
// Test LifetimeDependenceScopeFixup.
12+
13+
@_nonescapable
14+
struct BV {
15+
let p: UnsafeRawPointer
16+
let c: Int
17+
18+
public var isEmpty: Bool { c == 0 }
19+
20+
@_unsafeNonescapableResult
21+
init(_ p: UnsafeRawPointer, _ c: Int) {
22+
self.p = p
23+
self.c = c
24+
}
25+
}
26+
27+
struct NC : ~Copyable {
28+
let p: UnsafeRawPointer
29+
let c: Int
30+
31+
// Requires a borrow.
32+
borrowing func getBV() -> _borrow(self) BV {
33+
BV(p, c)
34+
}
35+
}
36+
37+
// Rewrite the mark_dependence to depende on the incoming argument rather than the nested access.
38+
//
39+
// CHECK-LABEL: sil hidden @$s4test13bv_get_mutate9containerAA2BVVAA2NCVz_tF : $@convention(thin) (@inout NC) -> _scope(1) @owned BV {
40+
// CHECK: bb0(%0 : $*NC):
41+
// CHECK: [[A:%.*]] = begin_access [read] [static] %0 : $*NC
42+
// CHECK: [[L:%.*]] = load [[A]] : $*NC
43+
// CHECK: [[R:%.*]] = apply %{{.*}}([[L]]) : $@convention(method) (@guaranteed NC) -> _scope(0) @owned BV
44+
// CHECK: [[M:%.*]] = mark_dependence [nonescaping] [[R]] : $BV on %0 : $*NC
45+
// CHECK-LABEL: } // end sil function '$s4test13bv_get_mutate9containerAA2BVVAA2NCVz_tF'
46+
func bv_get_mutate(container: inout NC) -> _mutate(container) BV {
47+
container.getBV()
48+
}

test/SILOptimizer/lifetime_dependence_todo.swift

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,11 @@
1111
// REQUIRES: disabled
1212

1313

14-
// =============================================================================
15-
// Diagnostics that should not fail.
16-
17-
// Recognize nested accesses as part of the same dependence scope.
18-
func bv_get_mutate(container: inout NC) -> _mutate(container) BV {
19-
container.getBV()
20-
}
21-
2214
// =============================================================================
2315
// Diagnostics that should fail.
2416

25-
// Test that an unsafe dependence requires Builtin.lifetime_dependence.
17+
// @_unsafeResultDependsOn: Test that an unsafe dependence requires
18+
// Builtin.lifetime_dependence.
2619
//
2720
func bv_derive_local(bv: consuming BV) -> _consume(bv) BV {
2821
let bv2 = BV(bv.p, bv.i)

0 commit comments

Comments
 (0)