mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
AllocStackToBox: fix a bug which results in a too early released captured variable
In case of a borrowed `alloc_box`, the optimization didn't look through the `begin_borrow` when calculating the final release of the box. This resulted in inserting the destroy of the inserted `alloc_stack` too early. rdar://97087762
This commit is contained in:
@@ -53,9 +53,9 @@ static llvm::cl::opt<bool> AllocBoxToStackAnalyzeApply(
|
|||||||
// SIL Utilities for alloc_box Promotion
|
// SIL Utilities for alloc_box Promotion
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
static SILValue stripOffCopyValue(SILValue V) {
|
static SILValue stripOffCopyAndBorrow(SILValue V) {
|
||||||
while (auto *CVI = dyn_cast<CopyValueInst>(V)) {
|
while (isa<CopyValueInst>(V) || isa<BeginBorrowInst>(V)) {
|
||||||
V = CVI->getOperand();
|
V = cast<SingleValueInstruction>(V)->getOperand(0);
|
||||||
}
|
}
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ static bool addLastRelease(SILValue V, SILBasicBlock *BB,
|
|||||||
for (auto I = BB->rbegin(); I != BB->rend(); ++I) {
|
for (auto I = BB->rbegin(); I != BB->rend(); ++I) {
|
||||||
if (isa<StrongReleaseInst>(*I) || isa<DeallocBoxInst>(*I) ||
|
if (isa<StrongReleaseInst>(*I) || isa<DeallocBoxInst>(*I) ||
|
||||||
isa<DestroyValueInst>(*I)) {
|
isa<DestroyValueInst>(*I)) {
|
||||||
if (stripOffCopyValue(I->getOperand(0)) != V)
|
if (stripOffCopyAndBorrow(I->getOperand(0)) != V)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Releases.push_back(&*I);
|
Releases.push_back(&*I);
|
||||||
|
|||||||
@@ -469,6 +469,43 @@ bb0(%0 : $Int):
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sil [ossa] @closureWithBoxArg : $@convention(thin) (@guaranteed { var SomeClass }) -> () {
|
||||||
|
bb0(%0 : @guaranteed ${ var SomeClass }):
|
||||||
|
%r = tuple ()
|
||||||
|
return %r : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
sil [ossa] @useClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
|
||||||
|
bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
|
||||||
|
%r = tuple ()
|
||||||
|
return %r : $()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil [ossa] @finalReleaseWithBorrow
|
||||||
|
// CHECK: [[S:%[0-9]+]] = alloc_stack {{.*}}$SomeClass
|
||||||
|
// CHECK-NOT: destroy_addr
|
||||||
|
// CHECK: [[F:%[0-9]+]] = function_ref @useClosure
|
||||||
|
// CHECK: apply [[F]]
|
||||||
|
// CHECK: destroy_addr [[S]]
|
||||||
|
// CHECK: } // end sil function 'finalReleaseWithBorrow'
|
||||||
|
sil [ossa] @finalReleaseWithBorrow : $@convention(thin) (@owned SomeClass) -> () {
|
||||||
|
bb0(%0 : @owned $SomeClass):
|
||||||
|
%1 = alloc_box $ { var SomeClass }
|
||||||
|
%2 = begin_borrow %1 : ${ var SomeClass }
|
||||||
|
%1a = project_box %2 : ${ var SomeClass }, 0
|
||||||
|
store %0 to [init] %1a : $*SomeClass
|
||||||
|
%3 = function_ref @closureWithBoxArg : $@convention(thin) (@guaranteed { var SomeClass }) -> ()
|
||||||
|
%4 = copy_value %2 : ${ var SomeClass }
|
||||||
|
%5 = partial_apply [callee_guaranteed] %3(%4) : $@convention(thin) (@guaranteed { var SomeClass }) -> ()
|
||||||
|
end_borrow %2 : ${ var SomeClass }
|
||||||
|
destroy_value %1 : ${ var SomeClass }
|
||||||
|
%6 = function_ref @useClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
||||||
|
apply %6(%5) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
||||||
|
destroy_value %5 : $@callee_guaranteed () -> ()
|
||||||
|
%10 = tuple ()
|
||||||
|
return %10 : $()
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) <U where U : P> (@owned @callee_owned () -> @out U) -> ()
|
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) <U where U : P> (@owned @callee_owned () -> @out U) -> ()
|
||||||
sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) <U where U : P> (@owned @callee_owned () -> @out U) -> () {
|
sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) <U where U : P> (@owned @callee_owned () -> @out U) -> () {
|
||||||
// CHECK: bb0
|
// CHECK: bb0
|
||||||
|
|||||||
Reference in New Issue
Block a user