Skip to content

Commit 69de2ee

Browse files
authored
Merge pull request #78640 from atrick/fix-inguaranteed-depend
LifetimeDependence.Scope: recognize @in_guaranteed dependencies.
2 parents 217311f + c8bec28 commit 69de2ee

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,11 @@ extension LifetimeDependence.Scope {
329329
self = Self(guaranteed: refElt.operand.value, context)
330330
case let .argument(arg):
331331
if arg.convention.isIndirectIn {
332-
self = .initialized(initialAddress: arg, initializingStore: nil)
332+
if arg.convention.isGuaranteed {
333+
self = .caller(arg)
334+
} else {
335+
self = .initialized(initialAddress: arg, initializingStore: nil)
336+
}
333337
} else if arg.convention.isIndirectOut || arg.convention.isInout {
334338
// TODO: verify that @out values are never reassigned.
335339
self = .caller(arg)

test/SILOptimizer/lifetime_dependence/diagnostic_passes.sil

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-sil-opt -test-runner %s \
22
// RUN: -diagnostics -sil-verify-all \
33
// RUN: -enable-experimental-feature LifetimeDependence \
4+
// RUN: -enable-experimental-feature Span \
45
// RUN: 2>&1 | %FileCheck %s
56

67
// Test SIL expected from SILGen output. Run all diagnostic passes which includes lifetime dependence handling:
@@ -12,6 +13,7 @@
1213

1314
// REQUIRES: swift_in_compiler
1415
// REQUIRES: swift_feature_LifetimeDependence
16+
// REQUIRES: swift_feature_Span
1517

1618
sil_stage raw
1719

@@ -23,9 +25,15 @@ struct Owner {}
2325
struct NE: ~Escapable {}
2426
struct OtherNE: ~Escapable {}
2527

28+
public struct Container {
29+
var pointer: UnsafeRawPointer
30+
var object: AnyObject
31+
}
32+
2633
sil @getNE : $@convention(c) (@in_guaranteed Owner) -> @lifetime(borrow 0) @autoreleased NE
2734
sil @copyNE : $@convention(c) (NE, @lifetime(copy 0) @inout NE) -> ()
2835
sil @makeOwner : $@convention(c) () -> Owner
36+
sil @_overrideLifetimeBorrowing : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : ~Copyable, τ_0_0 : ~Escapable, τ_0_1 : ~Copyable, τ_0_1 : ~Escapable> (@in τ_0_0, @in_guaranteed τ_0_1) -> @lifetime(borrow 1) @out τ_0_0
2937

3038
// Modify a local via 'inout' assignment.
3139
// Do not insert a mark_dep.
@@ -129,3 +137,64 @@ bb0:
129137
%93 = tuple ()
130138
return %93 : $()
131139
}
140+
141+
// Init.init()
142+
sil @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
143+
// RawSpan.init()
144+
sil @$ss7RawSpanV12_unsafeStart9byteCountABSV_SitcfC : $@convention(method) (UnsafeRawPointer, Int, @thin RawSpan.Type) -> @lifetime(borrow 0) @owned RawSpan
145+
146+
// Test dependence on an in_guaranteed address and a store_borrow.
147+
//
148+
// A mark_dependence will be created for %23 apply, but OnonSimplify will later remove it.
149+
//
150+
// CHECK-LABEL: sil [available 9999] [ossa] @testInGuaranteedRawSpan : $@convention(method) (@in_guaranteed Container) -> @lifetime(borrow 0) @owned RawSpan {
151+
// CHECK: bb0(%0 : $*Container):
152+
// CHECK: [[GETSPAN:%.*]] = apply %{{.*}}({{.*}}) : $@convention(method) (UnsafeRawPointer, Int, @thin RawSpan.Type) -> @lifetime(borrow 0) @owned RawSpan
153+
// CHECK: mark_dependence [nonescaping] [[GETSPAN]] on %0
154+
// CHECK: [[OUT:%.*]] = alloc_stack $RawSpan
155+
// CHECK: [[IN:%.*]] = alloc_stack $RawSpan
156+
// CHECK: store %{{.*}} to [init] [[IN]]
157+
// CHECK: [[LB:%.*]] = load_borrow %0
158+
// CHECK: [[BORROWSELF:%.*]] = alloc_stack $Container
159+
// CHECK: [[SB:%.*]] = store_borrow [[LB]] to [[BORROWSELF]]
160+
// CHECK: apply %{{.*}}<RawSpan, Container>([[OUT]], [[IN]], [[SB]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : ~Copyable, τ_0_0 : ~Escapable, τ_0_1 : ~Copyable, τ_0_1 : ~Escapable> (@in τ_0_0, @in_guaranteed τ_0_1) -> @lifetime(borrow 1) @out τ_0_0
161+
// CHECK: [[RET:%.*]] = load [take] [[OUT]]
162+
// CHECK: return [[RET]]
163+
// CHECK-LABEL: } // end sil function 'testInGuaranteedRawSpan'
164+
sil [available 9999] [ossa] @testInGuaranteedRawSpan : $@convention(method) (@in_guaranteed Container) -> @lifetime(borrow 0) @owned RawSpan {
165+
bb0(%0 : $*Container):
166+
debug_value %0, let, name "self", argno 1, expr op_deref
167+
%2 = metatype $@thin RawSpan.Type
168+
%3 = load_borrow %0
169+
%4 = struct_extract %3, #Container.pointer
170+
%5 = integer_literal $Builtin.IntLiteral, 0
171+
%6 = metatype $@thin Int.Type
172+
%7 = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
173+
%8 = apply %7(%5, %6) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
174+
175+
%9 = function_ref @$ss7RawSpanV12_unsafeStart9byteCountABSV_SitcfC : $@convention(method) (UnsafeRawPointer, Int, @thin RawSpan.Type) -> @lifetime(borrow 0) @owned RawSpan
176+
%10 = apply %9(%4, %8, %2) : $@convention(method) (UnsafeRawPointer, Int, @thin RawSpan.Type) -> @lifetime(borrow 0) @owned RawSpan
177+
end_borrow %3
178+
%12 = move_value [var_decl] %10
179+
debug_value %12, let, name "span"
180+
%14 = alloc_stack $RawSpan
181+
%15 = begin_borrow %12
182+
%16 = copy_value %15
183+
%17 = alloc_stack $RawSpan
184+
store %16 to [init] %17
185+
%19 = load_borrow %0
186+
%20 = alloc_stack $Container
187+
%21 = store_borrow %19 to %20
188+
189+
%22 = function_ref @_overrideLifetimeBorrowing : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : ~Copyable, τ_0_0 : ~Escapable, τ_0_1 : ~Copyable, τ_0_1 : ~Escapable> (@in τ_0_0, @in_guaranteed τ_0_1) -> @lifetime(borrow 1) @out τ_0_0
190+
%23 = apply %22<RawSpan, Container>(%14, %17, %21) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : ~Copyable, τ_0_0 : ~Escapable, τ_0_1 : ~Copyable, τ_0_1 : ~Escapable> (@in τ_0_0, @in_guaranteed τ_0_1) -> @lifetime(borrow 1) @out τ_0_0
191+
end_borrow %21
192+
dealloc_stack %20
193+
end_borrow %19
194+
dealloc_stack %17
195+
end_borrow %15
196+
%29 = load [take] %14
197+
dealloc_stack %14
198+
destroy_value %12
199+
return %29
200+
}

test/SILOptimizer/lifetime_dependence/lifetime_dependence_util.sil

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,9 @@ entry(%0 : @owned $C, %1 : @owned $D, %2 : @guaranteed $D, %3 : $*D, %4 : $*D):
159159
%inguaranteed_arg_mark = mark_dependence [nonescaping] %guaranteed_arg_mark : $C on %3 : $*D
160160
specify_test "lifetime_dependence_scope %inguaranteed_arg_mark"
161161
// CHECK-LABEL: dependence_scope: lifetime_dependence_scope with: %inguaranteed_arg_mark
162-
// CHECK-NEXT: Initialized: %3 = argument of bb0 : $*D
162+
// CHECK-NEXT: Caller: %3 = argument of bb0 : $*D
163163
// CHECK-NEXT: Dependent: %{{.*}} = mark_dependence [nonescaping] %{{.*}} : $C on %3 : $*D
164-
// CHECK-NEXT: begin: bb0
165-
// CHECK-NEXT: ends:
164+
// CHECK-NEXT: Caller range
166165
// CHECK: dependence_scope: lifetime_dependence_scope with: %inguaranteed_arg_mark
167166

168167
%inout_arg_mark = mark_dependence [nonescaping] %inguaranteed_arg_mark : $C on %4 : $*D

0 commit comments

Comments
 (0)