mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Fix DCE of begin_borrow with @guaranteed operand
For the lower most begin_borrows with @guaranteed operands, there was no @guaranteed phi computation, restructure the code and fix this case.
This commit is contained in:
@@ -283,37 +283,33 @@ void DCE::markLive() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SILInstructionKind::BeginBorrowInst: {
|
case SILInstructionKind::BeginBorrowInst: {
|
||||||
// Currently we only support borrows of owned values.
|
|
||||||
// Nested borrow handling can be complex in the presence of reborrows.
|
|
||||||
// So it is not handled currently.
|
|
||||||
auto *borrowInst = cast<BeginBorrowInst>(&I);
|
auto *borrowInst = cast<BeginBorrowInst>(&I);
|
||||||
|
// Populate guaranteedPhiDependencies for this borrowInst
|
||||||
|
findGuaranteedPhiDependencies(BorrowedValue(borrowInst));
|
||||||
|
auto disableBorrowDCE = [&](SILValue borrow) {
|
||||||
|
visitTransitiveEndBorrows(borrow, [&](EndBorrowInst *endBorrow) {
|
||||||
|
markInstructionLive(endBorrow);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// If we have a begin_borrow of a @guaranteed operand, disable DCE'ing
|
||||||
|
// of parent borrow scopes. Dead reborrows needs complex handling, whuch
|
||||||
|
// is why it is disabled for now.
|
||||||
if (borrowInst->getOperand()->getOwnershipKind() ==
|
if (borrowInst->getOperand()->getOwnershipKind() ==
|
||||||
OwnershipKind::Guaranteed) {
|
OwnershipKind::Guaranteed) {
|
||||||
// Visit the end_borrows of all the borrow scopes that this
|
|
||||||
// begin_borrow could be borrowing.
|
|
||||||
SmallVector<SILValue, 4> roots;
|
SmallVector<SILValue, 4> roots;
|
||||||
findGuaranteedReferenceRoots(borrowInst->getOperand(),
|
findGuaranteedReferenceRoots(borrowInst->getOperand(),
|
||||||
/*lookThroughNestedBorrows=*/false,
|
/*lookThroughNestedBorrows=*/false,
|
||||||
roots);
|
roots);
|
||||||
|
// Visit the end_borrows of all the borrow scopes that this
|
||||||
|
// begin_borrow could be borrowing, and mark them live.
|
||||||
for (auto root : roots) {
|
for (auto root : roots) {
|
||||||
visitTransitiveEndBorrows(root,
|
disableBorrowDCE(root);
|
||||||
[&](EndBorrowInst *endBorrow) {
|
|
||||||
markInstructionLive(endBorrow);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
// Populate guaranteedPhiDependencies for this borrow
|
// If we have a lexical borrow scope or a pointer escape, disable DCE.
|
||||||
findGuaranteedPhiDependencies(BorrowedValue(borrowInst));
|
|
||||||
// Don't optimize a borrow scope if it is lexical or has a pointer
|
|
||||||
// escape.
|
|
||||||
if (borrowInst->isLexical() ||
|
if (borrowInst->isLexical() ||
|
||||||
hasPointerEscape(BorrowedValue(borrowInst))) {
|
hasPointerEscape(BorrowedValue(borrowInst))) {
|
||||||
// Visit all end_borrows and mark them live
|
disableBorrowDCE(borrowInst);
|
||||||
visitTransitiveEndBorrows(borrowInst, [&](EndBorrowInst *endBorrow) {
|
|
||||||
markInstructionLive(endBorrow);
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -529,6 +529,48 @@ bb1(%newborrowi : @guaranteed $Klass, %newborrowo : @guaranteed $Klass):
|
|||||||
return %res : $()
|
return %res : $()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sil [ossa] @dce_nestedborrowlifetime4 : $@convention(thin) (@guaranteed Wrapper1, @guaranteed Wrapper1) -> () {
|
||||||
|
bb0(%0 : @guaranteed $Wrapper1, %1 : @guaranteed $Wrapper1):
|
||||||
|
cond_br undef, bb1, bb2
|
||||||
|
|
||||||
|
bb1:
|
||||||
|
%outer1 = begin_borrow %0 : $Wrapper1
|
||||||
|
%ex1 = struct_extract %outer1 : $Wrapper1, #Wrapper1.val1
|
||||||
|
%ex11 = struct_extract %ex1 : $Wrapper2, #Wrapper2.val2
|
||||||
|
br bb3(%ex11 : $Klass, %outer1 : $Wrapper1)
|
||||||
|
|
||||||
|
bb2:
|
||||||
|
%outer2 = begin_borrow %1 : $Wrapper1
|
||||||
|
%ex2 = struct_extract %outer2 : $Wrapper1, #Wrapper1.val1
|
||||||
|
%ex21 = struct_extract %ex2 : $Wrapper2, #Wrapper2.val2
|
||||||
|
br bb3(%ex21 : $Klass, %outer2 : $Wrapper1)
|
||||||
|
|
||||||
|
bb3(%phi1 : @guaranteed $Klass, %phi2 : @guaranteed $Wrapper1):
|
||||||
|
%f = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
|
||||||
|
apply %f(%phi1) : $@convention(thin) (@guaranteed Klass) -> ()
|
||||||
|
end_borrow %phi2 : $Wrapper1
|
||||||
|
%9999 = tuple()
|
||||||
|
return %9999 : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
sil [ossa] @dce_nestedborrowlifetime5 : $@convention(thin) (@guaranteed Wrapper1) -> () {
|
||||||
|
bb0(%0 : @guaranteed $Wrapper1):
|
||||||
|
%outer1 = begin_borrow %0 : $Wrapper1
|
||||||
|
%inner1 = begin_borrow %outer1 : $Wrapper1
|
||||||
|
%ex1 = struct_extract %inner1 : $Wrapper1, #Wrapper1.val1
|
||||||
|
%ex11 = struct_extract %ex1 : $Wrapper2, #Wrapper2.val2
|
||||||
|
br bb2(%ex11 : $Klass, %inner1 : $Wrapper1)
|
||||||
|
|
||||||
|
bb2(%phi1 : @guaranteed $Klass, %phi2 : @guaranteed $Wrapper1):
|
||||||
|
%f = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
|
||||||
|
apply %f(%phi1) : $@convention(thin) (@guaranteed Klass) -> ()
|
||||||
|
end_borrow %phi2 : $Wrapper1
|
||||||
|
end_borrow %outer1 : $Wrapper1
|
||||||
|
%9999 = tuple()
|
||||||
|
return %9999 : $()
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: sil [ossa] @infinite_loop :
|
// CHECK-LABEL: sil [ossa] @infinite_loop :
|
||||||
// CHECK-NOT: copy_value
|
// CHECK-NOT: copy_value
|
||||||
// CHECK-LABEL: } // end sil function 'infinite_loop'
|
// CHECK-LABEL: } // end sil function 'infinite_loop'
|
||||||
|
|||||||
Reference in New Issue
Block a user