Skip to content

Commit 78d0660

Browse files
committed
[CanonBorrowScope] Allow inner val without outer.
When rewriting outer uses of the borrow, `recursivelyRewriterOuterUses` is called recursively. First, it is called with the borrow itself. Subsequently, it is called with forwarding users of the borrow. Such a user may not be rewriteable as outer uses. If it isn't `innerToOuterMap` won't have an entry for it. Previously, failing to find an entry would raise an assertion. Here, the function is made to return a "null" SILValue. Its caller RewriteOuterBorrowUses::visitForwardingUse was already written to handle such a result.
1 parent 8c8b24f commit 78d0660

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

lib/SILOptimizer/Utils/CanonicalizeBorrowScope.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,9 @@ class RewriteOuterBorrowUses {
638638
assert(succeed && "should be filtered by FindBorrowScopeUses");
639639

640640
auto iter = innerToOuterMap.find(innerValue);
641-
assert(iter != innerToOuterMap.end());
641+
if (iter == innerToOuterMap.end()) {
642+
return SILValue();
643+
}
642644
SILValue outerValue = iter->second;
643645
cleanupOuterValue(outerValue);
644646
return outerValue;

test/SILOptimizer/canonicalize_borrow_scope_unit.sil

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ import Builtin
44

55
typealias AnyObject = Builtin.AnyObject
66

7+
class C {}
8+
class D : C {}
9+
10+
sil @getD : $() -> (@owned D)
11+
sil @takeC : $(@owned C) -> ()
12+
713
struct Unmanaged<Instance> where Instance : AnyObject {
814
unowned(unsafe) var _value: @sil_unmanaged Instance
915
}
@@ -57,3 +63,37 @@ bb0(%instance : @guaranteed $Instance):
5763
%retval = struct $Unmanaged<Instance> (%unmanaged : $@sil_unmanaged Instance)
5864
return %retval : $Unmanaged<Instance>
5965
}
66+
67+
// CHECK-LABEL: begin running test {{.*}} on dont_rewrite_inner_forwarding_user: canonicalize-borrow-scope
68+
// CHECK-LABEL: sil [ossa] @dont_rewrite_inner_forwarding_user : {{.*}} {
69+
// CHECK: [[GET_C:%[^,]+]] = function_ref @getD
70+
// CHECK: [[TAKE_C:%[^,]+]] = function_ref @takeC
71+
// CHECK: [[C:%[^,]+]] = apply [[GET_C]]()
72+
// CHECK: [[OUTER_COPY:%[^,]+]] = copy_value [[C]]
73+
// CHECK: [[OUTER_UPCAST:%[^,]+]] = upcast [[OUTER_COPY]]
74+
// CHECK: [[B:%[^,]+]] = begin_borrow [[C]]
75+
// CHECK: [[DEAD_INNER_COPY:%[^,]+]] = copy_value [[B]]
76+
// CHECK: destroy_value [[DEAD_INNER_COPY]]
77+
// CHECK: [[U:%[^,]+]] = upcast [[B]]
78+
// CHECK: [[C1:%[^,]+]] = copy_value [[U]]
79+
// CHECK: apply [[TAKE_C]]([[C1]])
80+
// CHECK: end_borrow [[B]]
81+
// CHECK: destroy_value [[C]]
82+
// CHECK: return [[OUTER_UPCAST]]
83+
// CHECK-LABEL: } // end sil function 'dont_rewrite_inner_forwarding_user'
84+
// CHECK-LABEL: end running test {{.*}} on dont_rewrite_inner_forwarding_user: canonicalize-borrow-scope
85+
sil [ossa] @dont_rewrite_inner_forwarding_user : $@convention(thin) () -> (@owned C) {
86+
%getD = function_ref @getD : $@convention(thin) () -> (@owned D)
87+
%takeC = function_ref @takeC : $@convention(thin) (@owned C) -> ()
88+
%d = apply %getD() : $@convention(thin) () -> (@owned D)
89+
test_specification "canonicalize-borrow-scope @instruction"
90+
%b = begin_borrow %d : $D
91+
%c2 = copy_value %b : $D
92+
%u2 = upcast %c2 : $D to $C
93+
%c1 = copy_value %b : $D
94+
%u1 = upcast %c1 : $D to $C
95+
apply %takeC(%u1) : $@convention(thin) (@owned C) -> ()
96+
end_borrow %b : $D
97+
destroy_value %d : $D
98+
return %u2 : $C
99+
}

0 commit comments

Comments
 (0)