Skip to content

Commit b389de3

Browse files
committed
[BarrierAccessScopes] Handle found gen locality.
As the utility runs, new gens may become local: as access scopes are determined to contain deinit barriers, their `end_access` instructions become kills; if such an `end_access` occurs in the same block above an initially-non-local gen, that gen is now local. Previously, it was asserted that initially-non-local gens would not encounter when visiting the block backwards from that gen. Iteration would also _stop_ at the discovered kill, if any. As described above, the assertion was incorrect. Stopping at the discovered kill was also incorrect. It's necessary to continue walking the block after finding such a new kill because the book-keeping the utility does for which access scopes contain barriers. Concretely, there are two cases: (1) It may contain another `end_access` and above it a deinit barrier which must result in that second scope becoming a deinit barrier. (2) Some of its predecessors may be in the region, all the access scopes which are open at the begin of this block must be unioned into the set of scopes open at each predecessors' end, and more such access scopes may be discovered above the just-visited `end_access`. Here, both the assertion failure and the early bailout are fixed by walking from the indicated initially-non-local gen backwards over the entire block, regardless of whether a kill was encountered. If a kill is encountered, it is asserted that the kill is an `end_access` to account for the case described above. rdar://139840307
1 parent bf167a6 commit b389de3

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

include/swift/SILOptimizer/Analysis/VisitBarrierAccessScopes.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,21 @@ class VisitBarrierAccessScopes {
199199
[&](SILBasicBlock *successor) { return visited.contains(successor); }));
200200

201201
visited.insert(block);
202-
bool foundLocalKill = visitBlockFromGenThroughKill(from);
203-
assert(!foundLocalKill && "found local kill for non-local gen?!");
204-
(void)foundLocalKill;
202+
for (auto *instruction = from; instruction;
203+
instruction = instruction->getPreviousInstruction()) {
204+
if (visitInstruction(instruction)) {
205+
// New kills are incrementally added as access scopes are determined to
206+
// be barriers. For this reason, gens may newly be discovered to be
207+
// local. This can only happen when the kill which makes the gen local
208+
// ends an access scope (i.e. is an end_access).
209+
assert(isa<EndAccessInst>(instruction) &&
210+
"found preexisting local kill for initially-non-local gen?!");
211+
// Even so, the remainder of the block must still be visited.
212+
}
213+
}
214+
if (block->hasPhi()) {
215+
visitPhi(block);
216+
}
205217
visitBlockBegin(block);
206218
}
207219

test/SILOptimizer/shrink_borrow_scope.unit.sil

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ import Swift
55

66
class C {}
77

8+
struct X {}
9+
810
sil [ossa] @get_owned_c : $@convention(thin) () -> (@owned C)
911
sil [ossa] @callee_guaranteed: $@convention(thin) (@guaranteed C) -> ()
12+
sil [ossa] @barrier : $@convention(thin) () -> ()
13+
1014

1115
// CHECK-LABEL: begin running test 1 of {{[^,]+}} on nohoist_over_rewritten_copy
1216
// CHECK-NOT: DELETED:
@@ -29,3 +33,37 @@ entry:
2933
return %retval : $(C, C)
3034
}
3135

36+
// CHECK-LABEL: begin running test {{.*}} on nohoist_over_access_scope_barrier_1
37+
// CHECK: Result: did not shrink
38+
// CHECK-LABEL: end running test {{.*}} on nohoist_over_access_scope_barrier_1
39+
sil [ossa] @nohoist_over_access_scope_barrier_1 : $@convention(thin) (@guaranteed C, @inout X) -> () {
40+
entry(%c : @guaranteed $C, %addr : $*X):
41+
%borrow = begin_borrow %c : $C
42+
specify_test "shrink_borrow_scope %borrow"
43+
%access = begin_access [modify] [dynamic] %addr : $*X
44+
cond_br undef, kill_introducer, newly_local_gen
45+
46+
kill_introducer:
47+
cond_br undef, left, right
48+
49+
left:
50+
%barrier = function_ref @barrier : $@convention(thin) () -> ()
51+
apply %barrier() : $@convention(thin) () -> ()
52+
end_access %access : $*X
53+
end_borrow %borrow : $C
54+
br exit
55+
56+
right:
57+
end_access %access : $*X
58+
end_borrow %borrow : $C
59+
br exit
60+
61+
newly_local_gen:
62+
end_access %access : $*X
63+
end_borrow %borrow : $C
64+
br exit
65+
66+
exit:
67+
%retval = tuple ()
68+
return %retval : $()
69+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend -c -O %s
2+
3+
protocol P {}
4+
enum E {
5+
case c(any P)
6+
var d: [String:String] { [:] }
7+
}
8+
9+
final class C {
10+
var o: [String:String]?
11+
}
12+
13+
func f(_ e: E?) {
14+
if let e {
15+
C().o?.merge(e.d) { c, _ in c }
16+
}
17+
}

0 commit comments

Comments
 (0)