Skip to content

Commit 49136f2

Browse files
committed
Fix LifetimeDependenceScopeFixup to avoid rewriting mark_dependence.
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())))
1 parent f7fb099 commit 49136f2

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,12 +423,12 @@ extension LifetimeDependence.Scope {
423423
/// Ignore "irrelevent" borrow scopes: load_borrow or begin_borrow without [var_decl]
424424
func ignoreBorrowScope(_ context: some Context) -> LifetimeDependence.Scope? {
425425
guard case let .borrowed(beginBorrowVal) = self else {
426-
return self
426+
return nil
427427
}
428428
switch beginBorrowVal {
429429
case let .beginBorrow(bb):
430430
if bb.isFromVarDecl {
431-
return self
431+
return nil
432432
}
433433
return LifetimeDependence.Scope(base: bb.borrowedValue, context).ignoreBorrowScope(context)
434434
case let .loadBorrow(lb):

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 %{{.*}} 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: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,40 @@ 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: end_access [[ACCESS]]
95+
// CHECK: [[ADR:%.*]] = pointer_to_address %{{.*}} to [strict] $*Int64
96+
// CHECK: mark_dependence [unresolved] [[ADR]] on [[LD]]
97+
// CHECK-LABEL: } // end sil function 'testTrivialAccess'
98+
sil hidden [ossa] @testTrivialAccess : $@convention(thin) (UnsafePointer<Int64>) -> () {
99+
bb0(%0 : $UnsafePointer<Int64>):
100+
debug_value %0, let, name "p", argno 1
101+
%2 = alloc_box ${ var UnsafePointer<Int64> }, var, name "ptr"
102+
%3 = begin_borrow [var_decl] %2
103+
%4 = project_box %3, 0
104+
store %0 to [trivial] %4
105+
%6 = begin_access [read] [unknown] %4
106+
%7 = load [trivial] %6
107+
end_access %6
108+
%9 = function_ref @pointeeAddressor : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
109+
%10 = apply %9<Int64>(%7) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
110+
%11 = struct_extract %10, #UnsafePointer._rawValue
111+
%12 = pointer_to_address %11 to [strict] $*Int64
112+
%13 = mark_dependence [unresolved] %12 on %7
113+
%14 = begin_access [read] [unsafe] %13
114+
%15 = load [trivial] %14
115+
end_access %14
116+
end_borrow %3
117+
destroy_value %2
118+
%19 = tuple ()
119+
return %19
120+
}

0 commit comments

Comments
 (0)