Skip to content

Commit f3b2430

Browse files
authored
Merge pull request #28235 from gottesmm/pr-b17541a0a4d7b1ca7d40f3c80835d603a5698adc
2 parents d53c015 + dfb9a80 commit f3b2430

File tree

2 files changed

+70
-12
lines changed

2 files changed

+70
-12
lines changed

lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -406,24 +406,38 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
406406
// dead end blocks that use the value in a non-consuming way.
407407
//
408408
// TODO: There may be some way of sinking this into the loop below.
409-
if (destroys.empty() &&
410-
llvm::any_of(borrowScopeIntroducers,
411-
[](BorrowScopeIntroducingValue borrowScope) {
412-
return borrowScope.isLocalScope();
413-
})) {
409+
bool haveAnyLocalScopes = llvm::any_of(
410+
borrowScopeIntroducers, [](BorrowScopeIntroducingValue borrowScope) {
411+
return borrowScope.isLocalScope();
412+
});
413+
414+
if (destroys.empty() && haveAnyLocalScopes) {
414415
return false;
415416
}
416417

417418
// If we reached this point, then we know that all of our users can accept a
418-
// guaranteed value and our owned value is destroyed only by
419-
// destroy_value. Check if all of our destroys are joint post-dominated by the
420-
// our end borrow scope set. If they do not, then the copy_value is lifetime
421-
// extending the guaranteed value, we can not eliminate it.
419+
// guaranteed value and our owned value is destroyed only by a set of
420+
// destroy_values. Check if:
421+
//
422+
// 1. All of our destroys are joint post-dominated by our end borrow scope
423+
// set. If they do not, then the copy_value is lifetime extending the
424+
// guaranteed value, we can not eliminate it.
425+
//
426+
// 2. If all of our destroy_values are dead end. In such a case, the linear
427+
// lifetime checker will not perform any checks since it assumes that dead
428+
// end destroys can be ignored. Since we are going to end the program
429+
// anyways, we want to be conservative here and optimize only if we do not
430+
// need to insert an end_borrow since all of our borrow introducers are
431+
// non-local scopes.
422432
{
423433
SmallVector<BranchPropagatedUser, 8> destroysForLinearLifetimeCheck;
434+
bool foundNonDeadEnd = false;
424435
for (auto *dvi : destroys) {
436+
foundNonDeadEnd |= !getDeadEndBlocks().isDeadEnd(dvi->getParent());
425437
destroysForLinearLifetimeCheck.push_back(&dvi->getAllOperands()[0]);
426438
}
439+
if (!foundNonDeadEnd && haveAnyLocalScopes)
440+
return false;
427441
SmallVector<BranchPropagatedUser, 8> scratchSpace;
428442
SmallPtrSet<SILBasicBlock *, 4> visitedBlocks;
429443
if (llvm::any_of(borrowScopeIntroducers,

test/SILOptimizer/semantic-arc-opts.sil

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -824,8 +824,8 @@ bb0:
824824
unreachable
825825
}
826826

827-
// Make sure we do perform the optimization if our borrowed value is an
828-
// argument.
827+
// Make sure that since we have a guaranteed argument and do not need to reason
828+
// about end_borrows, we handle this.
829829
//
830830
// CHECK-LABEL: sil [ossa] @guaranteed_arg_used_by_postdominating_no_return_function : $@convention(thin) (@guaranteed NativeObjectPair) -> MyNever {
831831
// CHECK-NOT: copy_value
@@ -839,6 +839,23 @@ bb0(%0 : @guaranteed $NativeObjectPair):
839839
unreachable
840840
}
841841

842+
843+
// Make sure that since our borrow introducer is a begin_borrow, we do not
844+
// eliminate the copy.
845+
//
846+
// CHECK-LABEL: sil [ossa] @borrowed_val_used_by_postdominating_no_return_function : $@convention(thin) (@owned NativeObjectPair) -> MyNever {
847+
// CHECK: copy_value
848+
// CHECK: } // end sil function 'borrowed_val_used_by_postdominating_no_return_function'
849+
sil [ossa] @borrowed_val_used_by_postdominating_no_return_function : $@convention(thin) (@owned NativeObjectPair) -> MyNever {
850+
bb0(%0 : @owned $NativeObjectPair):
851+
%1 = begin_borrow %0 : $NativeObjectPair
852+
%2 = struct_extract %1 : $NativeObjectPair, #NativeObjectPair.obj1
853+
%3 = copy_value %2 : $Builtin.NativeObject
854+
%func = function_ref @unreachable_guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> MyNever
855+
apply %func(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> MyNever
856+
unreachable
857+
}
858+
842859
// Just make sure that we do not crash on this. We should be able to eliminate
843860
// everything here.
844861
//
@@ -855,4 +872,31 @@ bb0(%0 : @guaranteed $NativeObjectPair):
855872
destroy_value %2 : $Builtin.NativeObject
856873
%9999 = tuple()
857874
return %9999 : $()
858-
}
875+
}
876+
877+
// Just make sure we do not crash here.
878+
//
879+
// CHECK-LABEL: sil [ossa] @do_not_insert_end_borrow_given_deadend : $@convention(thin) (@guaranteed ClassLet) -> () {
880+
// CHECK: copy_value
881+
// CHECK: } // end sil function 'do_not_insert_end_borrow_given_deadend'
882+
sil [ossa] @do_not_insert_end_borrow_given_deadend : $@convention(thin) (@guaranteed ClassLet) -> () {
883+
bb0(%x : @guaranteed $ClassLet):
884+
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
885+
%p = ref_element_addr %x : $ClassLet, #ClassLet.aLet
886+
%v = load_borrow %p : $*Klass
887+
%c = copy_value %v : $Klass
888+
end_borrow %v : $Klass
889+
apply %f(%c) : $@convention(thin) (@guaranteed Klass) -> ()
890+
cond_br undef, bb1, bb2
891+
892+
bb1:
893+
destroy_value %c : $Klass
894+
br bb3
895+
896+
bb2:
897+
destroy_value %c : $Klass
898+
br bb3
899+
900+
bb3:
901+
unreachable
902+
}

0 commit comments

Comments
 (0)