Skip to content

Commit 1b51aa8

Browse files
committed
LifetimeDependenceScopeFixup: extend store_borrow scopes
This is require to handle '@'_addressable arguments on the caller side.
1 parent 7b83c09 commit 1b51aa8

File tree

2 files changed

+117
-15
lines changed

2 files changed

+117
-15
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceScopeFixup.swift

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ private struct ScopeExtension {
249249

250250
private extension LifetimeDependence.Scope {
251251
/// The instruction that introduces an extendable scope. This returns a non-nil scope introducer for
252-
/// Extendable.nestedScopes.
252+
/// ScopeExtension.nestedScopes.
253253
var extendableBegin: Instruction? {
254254
switch self {
255255
case let .access(beginAccess):
@@ -258,6 +258,17 @@ private extension LifetimeDependence.Scope {
258258
return beginBorrow.value.definingInstruction!
259259
case let .yield(yieldedValue):
260260
return yieldedValue.definingInstruction!
261+
case let .initialized(initializer):
262+
switch initializer {
263+
case let .store(initializingStore: store, initialAddress: _):
264+
if let sb = store as? StoreBorrowInst {
265+
return sb
266+
}
267+
return nil
268+
case .argument, .yield:
269+
// TODO: extend indirectly yielded scopes.
270+
return nil
271+
}
261272
default:
262273
return nil
263274
}
@@ -277,17 +288,8 @@ private extension LifetimeDependence.Scope {
277288
let accessExtension = gatherAccessExtension(beginAccess: beginAccess, innerScopes: &innerScopes)
278289
return SingleInlineArray(element: accessExtension)
279290
case let .borrowed(beginBorrow):
280-
let borrowedValue = beginBorrow.baseOperand!.value
281-
let enclosingScope = LifetimeDependence.Scope(base: borrowedValue, context)
282-
innerScopes.push(self)
283-
var innerBorrowScopes = innerScopes
284-
innerBorrowScopes.push(enclosingScope)
285-
if let extensions = enclosingScope.gatherExtensions(innerScopes: innerBorrowScopes, context) {
286-
return extensions
287-
}
288-
// This is the outermost scope to be extended because gatherExtensions did not find an enclosing scope.
289-
return SingleInlineArray(element: getOuterExtension(owner: enclosingScope.parentValue, nestedScopes: innerScopes,
290-
context))
291+
return gatherBorrowExtension(borrowedValue: beginBorrow.baseOperand!.value, innerScopes: &innerScopes, context)
292+
291293
case let .yield(yieldedValue):
292294
innerScopes.push(self)
293295
var extensions = SingleInlineArray<ScopeExtension>()
@@ -300,6 +302,17 @@ private extension LifetimeDependence.Scope {
300302
extensions.append(contentsOf: gatherOperandExtension(on: operand, innerScopes: innerScopes, context))
301303
}
302304
return extensions
305+
case let .initialized(initializer):
306+
switch initializer {
307+
case let .store(initializingStore: store, initialAddress: _):
308+
if let sb = store as? StoreBorrowInst {
309+
return gatherBorrowExtension(borrowedValue: sb.source, innerScopes: &innerScopes, context)
310+
}
311+
return nil
312+
case .argument, .yield:
313+
// TODO: extend indirectly yielded scopes.
314+
return nil
315+
}
303316
default:
304317
return nil
305318
}
@@ -360,6 +373,23 @@ private extension LifetimeDependence.Scope {
360373
}
361374
return ScopeExtension(owner: outerBeginAccess, nestedScopes: innerScopes, dependsOnArg: nil)
362375
}
376+
377+
func gatherBorrowExtension(borrowedValue: Value,
378+
innerScopes: inout SingleInlineArray<LifetimeDependence.Scope>,
379+
_ context: FunctionPassContext)
380+
-> SingleInlineArray<ScopeExtension> {
381+
382+
let enclosingScope = LifetimeDependence.Scope(base: borrowedValue, context)
383+
innerScopes.push(self)
384+
var innerBorrowScopes = innerScopes
385+
innerBorrowScopes.push(enclosingScope)
386+
if let extensions = enclosingScope.gatherExtensions(innerScopes: innerBorrowScopes, context) {
387+
return extensions
388+
}
389+
// This is the outermost scope to be extended because gatherExtensions did not find an enclosing scope.
390+
return SingleInlineArray(element: getOuterExtension(owner: enclosingScope.parentValue, nestedScopes: innerScopes,
391+
context))
392+
}
363393
}
364394

365395
/// Compute the range of the a scope owner. Nested scopes must stay within this range.
@@ -584,6 +614,17 @@ private extension LifetimeDependence.Scope {
584614
case let .yield(yieldedValue):
585615
let beginApply = yieldedValue.definingInstruction as! BeginApplyInst
586616
return beginApply.createEnd(builder, context)
617+
case let .initialized(initializer):
618+
switch initializer {
619+
case let .store(initializingStore: store, initialAddress: _):
620+
if let sb = store as? StoreBorrowInst {
621+
return builder.createEndBorrow(of: sb)
622+
}
623+
return nil
624+
case .argument, .yield:
625+
// TODO: extend indirectly yielded scopes.
626+
return nil
627+
}
587628
default:
588629
return nil
589630
}

test/SILOptimizer/lifetime_dependence/scope_fixup.sil

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
// RUN: %target-sil-opt %s \
2-
// RUN: --lifetime-dependence-scope-fixup \
1+
// RUN: %target-sil-opt \
2+
// RUN: -lifetime-dependence-scope-fixup \
33
// RUN: -sil-verify-all \
44
// RUN: -enable-experimental-feature LifetimeDependence \
5-
// RUN: 2>&1 | %FileCheck %s
5+
// RUN: -enable-experimental-feature AddressableParameters \
6+
// RUN: -enable-experimental-feature AddressableTypes \
7+
// RUN: %s | %FileCheck %s
68

79
// REQUIRES: swift_in_compiler
810
// REQUIRES: swift_feature_LifetimeDependence
11+
// REQUIRES: swift_feature_AddressableParameters
12+
// REQUIRES: swift_feature_AddressableTypes
913

1014
// Test the SIL representation for lifetime dependence scope fixup.
1115

@@ -15,6 +19,10 @@ import Builtin
1519
import Swift
1620

1721
struct NE : ~Escapable {
22+
var p: UnsafeRawPointer
23+
24+
@lifetime(immortal)
25+
init()
1826
}
1927

2028
struct Wrapper : ~Escapable {
@@ -31,6 +39,22 @@ struct NCContainer : ~Copyable {
3139
var wrapper: Wrapper { get } // _read
3240
}
3341

42+
struct TrivialHolder {
43+
var pointer: UnsafeRawPointer
44+
}
45+
46+
struct Holder {
47+
var object: AnyObject
48+
}
49+
50+
@_addressableForDependencies
51+
struct AddressableForDeps {}
52+
53+
sil @getPtr : $@convention(thin) () -> @out UnsafeRawPointer
54+
sil @getSpan : $@convention(thin) (@in_guaranteed AnyObject) -> @lifetime(borrow 0) @out NE
55+
56+
sil @useNE : $@convention(thin) (@guaranteed NE) -> ()
57+
3458
sil [ossa] @Wrapper_init : $@convention(method) (@owned NE, @thin Wrapper.Type) -> @lifetime(copy 0) @owned Wrapper
3559

3660
sil [ossa] @NCContainer_ne_read : $@yield_once @convention(method) (@guaranteed NCContainer) -> @lifetime(borrow 0) @yields @guaranteed NE
@@ -120,3 +144,40 @@ bb0(%0 : $UnsafePointer<Int64>):
120144
%19 = tuple ()
121145
return %19
122146
}
147+
148+
// =============================================================================
149+
// @_addressable
150+
// =============================================================================
151+
152+
sil [ossa] @addressableArg : $@convention(thin) (@in_guaranteed Holder) -> @lifetime(borrow address 0) @owned NE
153+
154+
// CHECK-LABEL: sil hidden [ossa] @testAddressableArg : $@convention(thin) (@guaranteed Holder) -> () {
155+
// CHECK: bb0(%0 : @guaranteed $Holder):
156+
// CHECK: [[ALLOC:%.*]] = alloc_stack $Holder
157+
// CHECK: [[SB:%.*]] = store_borrow %0 to [[ALLOC]]
158+
// CHECK: [[APPLY:%.*]] = apply %{{.*}}([[SB]]) : $@convention(thin) (@in_guaranteed Holder) -> @lifetime(borrow address 0) @owned NE
159+
// CHECK: [[MD:%.*]] = mark_dependence [unresolved] [[APPLY]] on [[SB]]
160+
// CHECK: [[MV:%.*]] = move_value [var_decl] [[MD]]
161+
// CHECK: apply %{{.*}}([[MV]]) : $@convention(thin) (@guaranteed NE) -> ()
162+
// CHECK: destroy_value [[MV]]
163+
// CHECK: end_borrow [[SB]]
164+
// CHECK: dealloc_stack [[ALLOC]]
165+
// CHECK-LABEL: } // end sil function 'testAddressableArg'
166+
sil hidden [ossa] @testAddressableArg : $@convention(thin) (@guaranteed Holder) -> () {
167+
bb0(%0 : @guaranteed $Holder):
168+
debug_value %0, let, name "arg", argno 1
169+
%2 = alloc_stack $Holder
170+
%3 = store_borrow %0 to %2
171+
%4 = function_ref @addressableArg : $@convention(thin) (@in_guaranteed Holder) -> @lifetime(borrow address 0) @owned NE
172+
%5 = apply %4(%3) : $@convention(thin) (@in_guaranteed Holder) -> @lifetime(borrow address 0) @owned NE
173+
%6 = mark_dependence [unresolved] %5 on %3
174+
end_borrow %3
175+
%8 = move_value [var_decl] %6
176+
debug_value %8, let, name "ne"
177+
%useNE = function_ref @useNE : $@convention(thin) (@guaranteed NE) -> ()
178+
%18 = apply %useNE(%8) : $@convention(thin) (@guaranteed NE) -> ()
179+
destroy_value %8
180+
dealloc_stack %2
181+
%99 = tuple ()
182+
return %99 : $()
183+
}

0 commit comments

Comments
 (0)