Skip to content

Commit 4ddc754

Browse files
committed
[AddressLowering] Storage root inherits lexical.
When a `begin_borrow [lexical]` is lowered, the lifetime that it describes can't be shortened (or eliminated) when lowering. In some cases, though, there will not be an alloc_stack corresponding directly to the value being borrowed. In these cases, mark the whole aggregate lexical.
1 parent a995c56 commit 4ddc754

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,6 +2776,13 @@ void UseRewriter::visitBeginBorrowInst(BeginBorrowInst *borrow) {
27762776
allocStack->setIsLexical();
27772777
return;
27782778
}
2779+
auto storage = AccessStorageWithBase::compute(address);
2780+
if (auto base = storage.base) {
2781+
if (auto *allocStack = dyn_cast<AllocStackInst>(base)) {
2782+
allocStack->setIsLexical();
2783+
return;
2784+
}
2785+
}
27792786
// Function arguments are inherently lexical.
27802787
if (isa<SILFunctionArgument>(address))
27812788
return;

test/SILOptimizer/opaque_values_Onone.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,35 @@
88
func generic_identity<T>(t: T) -> T {
99
return t
1010
}
11+
12+
13+
struct Outer<T : Equatable> {
14+
enum Inner {
15+
case outside
16+
case inside(T)
17+
}
18+
}
19+
20+
extension Outer.Inner {
21+
// CHECK-LABEL: sil hidden @outer_inner_compare
22+
// CHECK: [[LHS_ADDR:%[^,]+]] = alloc_stack [lexical] $Outer<T>.Inner
23+
// CHECK: [[RHS_ADDR:%[^,]+]] = alloc_stack [lexical] $Outer<T>.Inner
24+
// CHECK: switch_enum_addr [[LHS_ADDR]] : $*Outer<T>.Inner, case #Outer.Inner.inside!enumelt: [[L_INSIDE:bb[0-9]+]], case #Outer.Inner.outside!enumelt: {{bb[0-9]+}}
25+
// CHECK: [[L_INSIDE]]:
26+
// CHECK: unchecked_take_enum_data_addr [[LHS_ADDR]] : $*Outer<T>.Inner, #Outer.Inner.inside!enumelt
27+
// CHECK: switch_enum_addr [[RHS_ADDR]] : $*Outer<T>.Inner, case #Outer.Inner.inside!enumelt: [[L_AND_R_INSIDE:bb[0-9]+]], default {{bb[0-9]+}}
28+
// CHECK: [[L_AND_R_INSIDE]]:
29+
// CHECK: unchecked_take_enum_data_addr [[RHS_ADDR]] : $*Outer<T>.Inner, #Outer.Inner.inside!enumelt
30+
// CHECK-LABEL: } // end sil function 'outer_inner_compare'
31+
@_silgen_name("outer_inner_compare")
32+
static func compare(_ lhs: Outer.Inner, _ rhs: Outer.Inner) -> Bool {
33+
switch (lhs, rhs) {
34+
case (.inside(let l), .inside(let r)):
35+
return l == r
36+
case (.outside, .outside):
37+
return true
38+
default:
39+
return false
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)