Skip to content

Commit 7c1da20

Browse files
committed
[ShrinkBorrowScope] Checked before adding preds.
Previously, after determining that a block was dead, all its predecessors were added to the worklist. That is a problem, with the current algorithm, if any of the predecessors have a terminator over which the borrow scope cannot be shrunk. Here, before adding a dead block's predecessors to the worklist of blocks through which to shrink, ensure that all those predecessors have terminators over which the scope can be shrunk. Finally, when beginning to process a block, if it doesn't have a starting instruction, first hoist over thet terminator.
1 parent c88b043 commit 7c1da20

File tree

2 files changed

+71
-10
lines changed

2 files changed

+71
-10
lines changed

lib/SILOptimizer/Utils/ShrinkBorrowScope.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,6 @@ void ShrinkBorrowScope::findBarriers() {
298298
if (!startingInstruction && !hasOnlyDeadSuccessors(block)) {
299299
continue;
300300
}
301-
if (!startingInstruction &&
302-
!tryHoistOverInstruction(block->getTerminator())) {
303-
// This block was walked to--it was not one containing one of the initial
304-
// end_borrow instructions. Check whether it forwards the ownership of
305-
// the borrowed value (either directly or indirectly). If it does, we
306-
// must not hoist the end_borrow above it.
307-
continue;
308-
}
309301
for (auto *successor : block->getSuccessorBlocks()) {
310302
barredBlocks.erase(successor);
311303
}
@@ -317,6 +309,14 @@ void ShrinkBorrowScope::findBarriers() {
317309
// contained an original scope-ending instruction, start scanning from it.
318310
SILInstruction *instruction =
319311
startingInstruction ? startingInstruction : block->getTerminator();
312+
if (!startingInstruction) {
313+
// That there's no starting instruction means that this this block did not
314+
// contain an original introducer. It was added to the worklist later.
315+
// At that time, it was checked that this block (along with all that
316+
// successor's other predecessors) had a terminator over which the borrow
317+
// scope could be shrunk. Shrink it now.
318+
assert(tryHoistOverInstruction(block->getTerminator()));
319+
}
320320
SILInstruction *barrier = nullptr;
321321
while ((instruction = getPreviousInstruction(instruction))) {
322322
if (instruction == introducer) {
@@ -334,8 +334,16 @@ void ShrinkBorrowScope::findBarriers() {
334334
} else {
335335
deadBlocks.insert(block);
336336
barredBlocks.insert(block);
337-
for (auto *predecessor : block->getPredecessorBlocks()) {
338-
worklist.push_back(predecessor);
337+
// If any of block's predecessor has a terminator over which the scope
338+
// can't be shrunk, the scope is barred from shrinking out of this block.
339+
if (llvm::all_of(block->getPredecessorBlocks(), [&](auto *block) {
340+
return canHoistOverInstruction(block->getTerminator());
341+
})) {
342+
// Otherwise, add all predecessors to the worklist and attempt to shrink
343+
// the borrow scope through them.
344+
for (auto *predecessor : block->getPredecessorBlocks()) {
345+
worklist.push_back(predecessor);
346+
}
339347
}
340348
}
341349
}

test/SILOptimizer/shrink_borrow_scope.sil

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,38 @@ exit:
313313
return %instance_c : $C
314314
}
315315

316+
// CHECK-LABEL: sil [ossa] @dont_hoist_over_some_barred_blocks : {{.*}} {
317+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
318+
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]] : $C
319+
// CHECK: cond_br undef, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]]
320+
// CHECK: [[LEFT]]:
321+
// CHECK: br [[EXIT:bb[0-9]+]](undef : $C)
322+
// CHECK: [[RIGHT]]:
323+
// CHECK: [[COPY:%[^,]+]] = copy_value [[LIFETIME]] : $C
324+
// CHECK: br [[EXIT]]([[COPY]] : $C)
325+
// CHECK: [[EXIT]]
326+
// CHECK: end_borrow [[LIFETIME]] : $C
327+
// CHECK-LABEL: } // end sil function 'dont_hoist_over_some_barred_blocks'
328+
sil [ossa] @dont_hoist_over_some_barred_blocks : $(@owned C) -> () {
329+
entry(%instance : @owned $C):
330+
%borrow = begin_borrow %instance : $C
331+
cond_br undef, left, right
332+
333+
left:
334+
br exit(undef : $C)
335+
336+
right:
337+
%copy = copy_value %borrow : $C
338+
br exit(%copy : $C)
339+
340+
exit(%thing : @owned $C):
341+
end_borrow %borrow : $C
342+
destroy_value %thing : $C
343+
destroy_value %instance : $C
344+
%retval = tuple ()
345+
return %retval : $()
346+
}
347+
316348
// =============================================================================
317349
// branching tests }}
318350
// =============================================================================
@@ -663,6 +695,27 @@ entry(%instance : @owned $C):
663695
return %result : $()
664696
}
665697

698+
// CHECK-LABEL: sil [ossa] @hoist_over_try_apply_at_borrow : {{.*}} {
699+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
700+
// CHECK-NEXT: try_apply undef([[INSTANCE]]) : $@convention(thin) (@guaranteed C) -> @error Error, normal bb1, error bb2
701+
// CHECK-LABEL: } // end sil function 'hoist_over_try_apply_at_borrow'
702+
sil [ossa] @hoist_over_try_apply_at_borrow : $@convention(thin) (@owned C) -> @error Error {
703+
bb0(%instance : @owned $C):
704+
%lifetime = begin_borrow %instance : $C
705+
try_apply undef(%lifetime) : $@convention(thin) (@guaranteed C) -> @error Error, normal good, error bad
706+
707+
good(%8 : $()):
708+
end_borrow %lifetime : $C
709+
destroy_value %instance : $C
710+
%13 = tuple ()
711+
return %13 : $()
712+
713+
bad(%15 : @owned $Error):
714+
end_borrow %lifetime : $C
715+
destroy_value %instance : $C
716+
throw %15 : $Error
717+
}
718+
666719
// =============================================================================
667720
// instruction tests }}
668721
// =============================================================================

0 commit comments

Comments
 (0)