Skip to content

Commit 18d8d9b

Browse files
authored
Merge pull request #67163 from meg-gupta/fixpai5.9
[5.9] Fix insertion of dealloc_stack for partial_apply [on_stack] while going to non-OSSA
2 parents 4895334 + e508ad8 commit 18d8d9b

File tree

2 files changed

+51
-10
lines changed

2 files changed

+51
-10
lines changed

lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -539,19 +539,11 @@ bool OwnershipModelEliminatorVisitor::visitDestroyValueInst(
539539
DestroyValueInst *dvi) {
540540
// Nonescaping closures are represented ultimately as trivial pointers to
541541
// their context, but we use ownership to do borrow checking of their captures
542-
// in OSSA. Now that we're eliminating ownership, fold away destroys, unless
543-
// we're destroying the original partial_apply, in which case this is where
544-
// we dealloc_stack the context.
542+
// in OSSA. Now that we're eliminating ownership, fold away destroys.
545543
auto operand = dvi->getOperand();
546544
auto operandTy = operand->getType();
547545
if (auto operandFnTy = operandTy.getAs<SILFunctionType>()){
548546
if (operandFnTy->isTrivialNoEscape()) {
549-
if (auto origPA = dvi->getNonescapingClosureAllocation()) {
550-
withBuilder<void>(dvi, [&](SILBuilder &b, SILLocation loc) {
551-
b.createDeallocStack(loc, origPA);
552-
});
553-
}
554-
555547
eraseInstruction(dvi);
556548
return true;
557549
}
@@ -685,9 +677,41 @@ static bool stripOwnership(SILFunction &func) {
685677
if (func.isExternalDeclaration())
686678
return false;
687679

680+
llvm::DenseMap<PartialApplyInst *, SmallVector<SILInstruction *>>
681+
lifetimeEnds;
682+
683+
// Nonescaping closures are represented ultimately as trivial pointers to
684+
// their context, but we use ownership to do borrow checking of their captures
685+
// in OSSA. Now that we're eliminating ownership, we need to dealloc_stack the
686+
// context at its lifetime ends.
687+
// partial_apply's lifetime ends has to be gathered before we begin to leave
688+
// OSSA, but no dealloc_stack can be emitted until after we leave OSSA.
689+
for (auto &block : func) {
690+
for (auto &ii : block) {
691+
auto *pai = dyn_cast<PartialApplyInst>(&ii);
692+
if (!pai || !pai->isOnStack()) {
693+
continue;
694+
}
695+
pai->visitOnStackLifetimeEnds([&](Operand *op) {
696+
lifetimeEnds[pai].push_back(op->getUser());
697+
return true;
698+
});
699+
}
700+
}
701+
688702
// Set F to have unqualified ownership.
689703
func.setOwnershipEliminated();
690704

705+
// Now that we are in non-ossa, create dealloc_stack at partial_apply's
706+
// lifetime ends
707+
for (auto &it : lifetimeEnds) {
708+
auto *pai = it.first;
709+
for (auto *lifetimeEnd : it.second) {
710+
SILBuilderWithScope(lifetimeEnd->getNextInstruction())
711+
.createDeallocStack(lifetimeEnd->getLoc(), pai);
712+
}
713+
}
714+
691715
bool madeChange = false;
692716
SmallVector<SILInstruction *, 32> createdInsts;
693717
OwnershipModelEliminatorVisitor visitor(func);

test/SILOptimizer/ownership_model_eliminator.sil

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,4 +393,21 @@ bb0(%0 : $*C):
393393
dealloc_stack %1 : $*C
394394
%9999 = tuple()
395395
return %9999 : $()
396-
}
396+
}
397+
398+
sil @closure1: $@convention(thin) (@guaranteed C, @inout_aliasable C) -> ()
399+
sil @closure2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
400+
401+
// Ensure no assertion about missing dealloc_stack for partial_apply [on_stack] after OME
402+
sil [ossa] @test_partial_apply_on_stack: $@convention(thin) (@guaranteed C, @inout C) -> () {
403+
bb0(%0 : @guaranteed $C, %1 : $*C):
404+
%f1 = function_ref @closure1: $@convention(thin) (@guaranteed C, @inout_aliasable C) -> ()
405+
%pa1 = partial_apply [callee_guaranteed] [on_stack] %f1(%0, %1) : $@convention(thin) (@guaranteed C, @inout_aliasable C) -> ()
406+
%md = mark_dependence %pa1 : $@noescape @callee_guaranteed () -> () on %1 : $*C
407+
%f2 = function_ref @closure2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
408+
%pa2 = partial_apply [callee_guaranteed] %f2(%md) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
409+
destroy_value %pa2 : $@callee_guaranteed () -> ()
410+
%t = tuple ()
411+
return %t : $()
412+
}
413+

0 commit comments

Comments
 (0)