Skip to content

Commit dd0e419

Browse files
authored
Merge pull request swiftlang#78482 from atrick/fix-markdep-load
Fix LifetimeDependenceScopeFixup to avoid rewriting mark_dependence.
2 parents 9bd48e0 + 195ca7c commit dd0e419

File tree

6 files changed

+67
-14
lines changed

6 files changed

+67
-14
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceScopeFixup.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,8 @@ let lifetimeDependenceScopeFixupPass = FunctionPass(
119119
continue
120120
}
121121
// Redirect the dependence base to ignore irrelevant borrow scopes.
122-
guard let newLifetimeDep = markDep.rewriteSkippingBorrow(scope: innerLifetimeDep.scope, context) else {
123-
continue
124-
}
122+
let newLifetimeDep = markDep.rewriteSkippingBorrow(scope: innerLifetimeDep.scope, context)
123+
125124
// Recursively sink enclosing end_access, end_borrow, or end_apply.
126125
let args = extendScopes(dependence: newLifetimeDep, localReachabilityCache, context)
127126

@@ -135,9 +134,9 @@ private extension MarkDependenceInst {
135134
///
136135
/// Note: this could be done as a general simplification, e.g. after inlining. But currently this is only relevant for
137136
/// diagnostics.
138-
func rewriteSkippingBorrow(scope: LifetimeDependence.Scope, _ context: FunctionPassContext) -> LifetimeDependence? {
137+
func rewriteSkippingBorrow(scope: LifetimeDependence.Scope, _ context: FunctionPassContext) -> LifetimeDependence {
139138
guard let newScope = scope.ignoreBorrowScope(context) else {
140-
return nil
139+
return LifetimeDependence(scope: scope, dependentValue: self)
141140
}
142141
let newBase = newScope.parentValue
143142
if newBase != self.baseOperand.value {

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ extension LifetimeDependence.Scope {
394394
self = .borrowed(BeginBorrowValue(bbi)!)
395395
case is MoveValueInst:
396396
self = .owned(introducer)
397+
case let bai as BeginAccessInst:
398+
self = .access(bai)
397399
default:
398400
self = .unknown(introducer)
399401
}
@@ -423,12 +425,12 @@ extension LifetimeDependence.Scope {
423425
/// Ignore "irrelevent" borrow scopes: load_borrow or begin_borrow without [var_decl]
424426
func ignoreBorrowScope(_ context: some Context) -> LifetimeDependence.Scope? {
425427
guard case let .borrowed(beginBorrowVal) = self else {
426-
return self
428+
return nil
427429
}
428430
switch beginBorrowVal {
429431
case let .beginBorrow(bb):
430432
if bb.isFromVarDecl {
431-
return self
433+
return nil
432434
}
433435
return LifetimeDependence.Scope(base: bb.borrowedValue, context).ignoreBorrowScope(context)
434436
case let .loadBorrow(lb):

test/SILGen/addressors.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct A {
4646
// CHECK: [[BASE:%.*]] = load [[T0]] : $*UnsafeMutablePointer<Int32>
4747
// CHECK: return [[BASE]] : $UnsafeMutablePointer<Int32>
4848

49+
// SILGEN-LABEL: sil hidden [ossa] @$s10addressors5test0yyF : $@convention(thin) () -> () {
4950
// CHECK-LABEL: sil hidden @$s10addressors5test0yyF : $@convention(thin) () -> () {
5051
func test0() {
5152
// CHECK: [[A:%.*]] = alloc_stack [var_decl] $A
@@ -55,12 +56,16 @@ func test0() {
5556
// CHECK: store [[AVAL]] to [[A]]
5657
var a = A()
5758

58-
// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] [[A]] : $*A
59+
// SILGEN: [[ACCESS:%.*]] = begin_access [read] [unknown] %{{.*}} : $*A
60+
// SILGEN: [[LD:%.*]] = load [trivial] [[ACCESS]] : $*A
61+
// SILGEN: [[T3:%.*]] = pointer_to_address %{{.*}} : $Builtin.RawPointer to [strict] $*Int32
62+
// SILGEN: [[MD:%.*]] = mark_dependence [unresolved] [[T3]] : $*Int32 on [[LD]] : $A
63+
5964
// CHECK: [[T0:%.*]] = function_ref @$s10addressors1AVys5Int32VAEcilu :
6065
// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[AVAL]])
6166
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
6267
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
63-
// CHECK: [[MD:%.*]] = mark_dependence [nonescaping] [[T3]] : $*Int32 on [[ACCESS]] : $*A
68+
// CHECK: [[MD:%.*]] = mark_dependence [nonescaping] [[T3]] : $*Int32 on [[AVAL]] : $A
6469
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[MD]] : $*Int32
6570
// CHECK: [[Z:%.*]] = load [[ACCESS]] : $*Int32
6671
let z = a[10]

test/SILOptimizer/lifetime_dependence/lifetime_dependence_scope_fixup.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,12 @@ public func test10() {
228228
}
229229
}
230230

231+
// CHECK-LABEL: sil hidden @$s31lifetime_dependence_scope_fixup37testPointeeDependenceOnMutablePointer1pySPys5Int64VG_tF : $@convention(thin) (UnsafePointer<Int64>) -> () {
232+
// CHECK: bb0(%0 : $UnsafePointer<Int64>):
233+
// CHECK: [[ALLOC:%.*]] = alloc_stack [var_decl] $UnsafePointer<Int64>, var, name "ptr", type $UnsafePointer<Int64>
234+
// CHECK: mark_dependence [nonescaping] %{{.*}} on %0
235+
// CHECK-LABEL: } // end sil function '$s31lifetime_dependence_scope_fixup37testPointeeDependenceOnMutablePointer1pySPys5Int64VG_tF'
236+
func testPointeeDependenceOnMutablePointer(p: UnsafePointer<Int64>) {
237+
var ptr = p
238+
_ = ptr.pointee
239+
}

test/SILOptimizer/lifetime_dependence/scopefixup.sil

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,42 @@ bb2:
8181
destroy_value %10
8282
unwind
8383
}
84+
85+
sil @pointeeAddressor : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
86+
87+
// Test dependence on a loaded trivial value. The dependence scope should not be on the access scope, which is narrower
88+
// than the scoped of the loaded value.
89+
//
90+
// CHECK-LABEL: sil hidden [ossa] @testTrivialAccess : $@convention(thin) (UnsafePointer<Int64>) -> () {
91+
// CHECK: bb0(%0 : $UnsafePointer<Int64>):
92+
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown]
93+
// CHECK: [[LD:%.*]] = load [trivial] [[ACCESS]]
94+
// CHECK: [[ADR:%.*]] = pointer_to_address %{{.*}} to [strict] $*Int64
95+
// CHECK: [[MD:%.*]] = mark_dependence [unresolved] [[ADR]] on [[LD]]
96+
// CHECK: [[ACCESS2:%.*]] = begin_access [read] [unsafe] [[MD]]
97+
// CHECK: end_access [[ACCESS2]]
98+
// CHECK: end_access [[ACCESS]]
99+
// CHECK-LABEL: } // end sil function 'testTrivialAccess'
100+
sil hidden [ossa] @testTrivialAccess : $@convention(thin) (UnsafePointer<Int64>) -> () {
101+
bb0(%0 : $UnsafePointer<Int64>):
102+
debug_value %0, let, name "p", argno 1
103+
%2 = alloc_box ${ var UnsafePointer<Int64> }, var, name "ptr"
104+
%3 = begin_borrow [var_decl] %2
105+
%4 = project_box %3, 0
106+
store %0 to [trivial] %4
107+
%6 = begin_access [read] [unknown] %4
108+
%7 = load [trivial] %6
109+
end_access %6
110+
%9 = function_ref @pointeeAddressor : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
111+
%10 = apply %9<Int64>(%7) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
112+
%11 = struct_extract %10, #UnsafePointer._rawValue
113+
%12 = pointer_to_address %11 to [strict] $*Int64
114+
%13 = mark_dependence [unresolved] %12 on %7
115+
%14 = begin_access [read] [unsafe] %13
116+
%15 = load [trivial] %14
117+
end_access %14
118+
end_borrow %3
119+
destroy_value %2
120+
%19 = tuple ()
121+
return %19
122+
}

test/SILOptimizer/unsafeAddress.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,11 @@ func testSMod(s: inout S) {
9797

9898
// Accessing s.data causes an escaping dependence because we don't extend the local access scope of 's'.
9999
//
100-
// TODO: could we notice the local access is already nested inside the same kind of access (modify) and consider this to
101-
// be 'mark_dependence [nonescaping]'?
102-
//
103100
// CHECK-LABEL: sil hidden @$s4main16testSInoutBorrow5mut_syAA1SVz_tF : $@convention(thin) (@inout S) -> () {
104101
// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0
102+
// CHECK: [[LD:%.*]] = load [[ACCESS]]
105103
// CHECK: [[ADR:%.*]] = pointer_to_address %{{.*}} to [strict] $*NC
106-
// CHECK: [[MD:%.*]] = mark_dependence [[ADR]] on [[ACCESS]]
104+
// CHECK: [[MD:%.*]] = mark_dependence [nonescaping] [[ADR]] on [[LD]]
107105
// CHECK: begin_access [read] [unsafe] [[MD]]
108106
// CHECK: apply
109107
// CHECK: end_access
@@ -114,8 +112,9 @@ func testSInoutBorrow(mut_s s: inout S) {
114112

115113
// CHECK-LABEL: sil hidden @$s4main19testSInoutMutBorrow5mut_syAA1SVz_tF : $@convention(thin) (@inout S) -> () {
116114
// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0
115+
// CHECK: [[LD:%.*]] = load [[ACCESS]]
117116
// CHECK: [[ADR:%.*]] = pointer_to_address %{{.*}} to [strict] $*NC
118-
// CHECK: [[MD:%.*]] = mark_dependence [nonescaping] [[ADR]] on [[ACCESS]]
117+
// CHECK: [[MD:%.*]] = mark_dependence [nonescaping] [[ADR]] on [[LD]]
119118
// CHECK: begin_access [read] [unsafe] [[MD]]
120119
// CHECK: apply
121120
// CHECK: end_access

0 commit comments

Comments
 (0)