Skip to content

Commit 5db3758

Browse files
Merge pull request swiftlang#58557 from nate-chandler/rdar92460184
[MemAccessUtils] A resilient struct is a product leaf.
2 parents 2782725 + 3e2efa5 commit 5db3758

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,11 @@ void swift::visitProductLeafAccessPathNodes(
14001400
worklist.push_back({silType.getTupleElementType(index), elementNode});
14011401
}
14021402
} else if (auto *decl = silType.getStructOrBoundGenericStruct()) {
1403+
if (decl->isResilient(tec.getContext()->getParentModule(),
1404+
tec.getResilienceExpansion())) {
1405+
visitor(AccessPath::PathNode(node), silType);
1406+
continue;
1407+
}
14031408
unsigned index = 0;
14041409
for (auto *field : decl->getStoredProperties()) {
14051410
auto *fieldNode = node->getChild(index);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -enable-library-evolution \
3+
// RUN: -emit-module-path=%t/resilient_struct.swiftmodule \
4+
// RUN: -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
5+
6+
// RUN: %target-sil-opt -I %t -opt-mode=speed -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK
7+
8+
import resilient_struct
9+
10+
struct Twople<Bound> {
11+
@_hasStorage public let lowerBound: Bound { get }
12+
@_hasStorage public let upperBound: Bound { get }
13+
}
14+
15+
sil [ossa] @get_range_out : $@convention(thin) () -> @out Twople<Size>
16+
17+
// Given a non-resilient struct containing two resilient struct fields ONLY ONE
18+
// of which is copy_addr'd out of just before the destroy_addr of the struct,
19+
// DO NOT fold the destroy_addr of the struct into the one copy_addrs--doing so
20+
// would leave the second field initialized.
21+
//
22+
// CHECK: sil [ossa] @dont_fold_into_one_of_two_copy_addr_resilient_struct : {{.*}} {
23+
// CHECK-NOT: copy_addr [take]
24+
// CHECK: copy_addr
25+
// CHECK-NEXT: destroy_addr
26+
// CHECK-LABEL: } // end sil function 'dont_fold_into_one_of_two_copy_addr_resilient_struct'
27+
sil [ossa] @dont_fold_into_one_of_two_copy_addr_resilient_struct : $@convention(thin) () -> () {
28+
bb0:
29+
%range_addr = alloc_stack $Twople<Size>
30+
%get_range_out = function_ref @get_range_out : $@convention(thin) () -> @out Twople<Size>
31+
apply %get_range_out(%range_addr) : $@convention(thin) () -> @out Twople<Size>
32+
%range_upperBound_addr = struct_element_addr %range_addr : $*Twople<Size>, #Twople.upperBound
33+
%date_addr = alloc_stack $Size
34+
copy_addr %range_upperBound_addr to [initialization] %date_addr : $*Size
35+
destroy_addr %range_addr : $*Twople<Size>
36+
destroy_addr %date_addr : $*Size
37+
dealloc_stack %date_addr : $*Size
38+
dealloc_stack %range_addr : $*Twople<Size>
39+
%retval = tuple ()
40+
return %retval : $()
41+
} // end sil function 'dont_fold_into_one_of_two_copy_addr_resilient_struct'
42+
43+
// Given a non-resilient struct containing two resilient fields both of which
44+
// are copy_addr'd out of just before the destroy_addr of the struct, fold the
45+
// destroy_addr of the struct into the two copy_addrs, forming copy_addr
46+
// [take]s.
47+
//
48+
// CHECK: sil [ossa] @fold_into_two_of_two_copy_addr_resilient_struct : {{.*}} {
49+
// CHECK: copy_addr [take]
50+
// CHECK: copy_addr [take]
51+
// CHECK-LABEL: } // end sil function 'fold_into_two_of_two_copy_addr_resilient_struct'
52+
sil [ossa] @fold_into_two_of_two_copy_addr_resilient_struct : $@convention(thin) () -> () {
53+
bb0:
54+
%range_addr = alloc_stack $Twople<Size>
55+
%get_range_out = function_ref @get_range_out : $@convention(thin) () -> @out Twople<Size>
56+
apply %get_range_out(%range_addr) : $@convention(thin) () -> @out Twople<Size>
57+
%range_upperBound_addr = struct_element_addr %range_addr : $*Twople<Size>, #Twople.upperBound
58+
%range_lowerBound_addr = struct_element_addr %range_addr : $*Twople<Size>, #Twople.lowerBound
59+
%date_addr_1 = alloc_stack $Size
60+
%date_addr_2 = alloc_stack $Size
61+
copy_addr %range_upperBound_addr to [initialization] %date_addr_1 : $*Size
62+
copy_addr %range_lowerBound_addr to [initialization] %date_addr_2 : $*Size
63+
destroy_addr %range_addr : $*Twople<Size>
64+
destroy_addr %date_addr_1 : $*Size
65+
destroy_addr %date_addr_2 : $*Size
66+
dealloc_stack %date_addr_2 : $*Size
67+
dealloc_stack %date_addr_1 : $*Size
68+
dealloc_stack %range_addr : $*Twople<Size>
69+
%retval = tuple ()
70+
return %retval : $()
71+
} // end sil function 'dont_fold_into_one_of_two_copy_addr_resilient_struct'
72+

0 commit comments

Comments
 (0)