Skip to content

Commit cf81c20

Browse files
committed
Factor out helper to find the original PartialApplyInst deallocated by a DestroyValueInst in OSSA, if any
1 parent 8e0e51a commit cf81c20

File tree

4 files changed

+51
-35
lines changed

4 files changed

+51
-35
lines changed

include/swift/SIL/SILCloner.h

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,23 +1962,10 @@ void SILCloner<ImplClass>::visitDestroyValueInst(DestroyValueInst *Inst) {
19621962
if (fnTy->isTrivialNoEscape()) {
19631963
// Destroying the partial_apply [stack] becomes the stack deallocation
19641964
// of the context.
1965-
// Look through mark_dependence and other wrapper instructions.
1966-
SILValue deallocOperand = Inst->getOperand();
1967-
while (true) {
1968-
if (auto mdi = dyn_cast<MarkDependenceInst>(deallocOperand)) {
1969-
deallocOperand = mdi->getValue();
1970-
} else if (isa<ConvertEscapeToNoEscapeInst>(deallocOperand)) {
1971-
break;
1972-
} else if (auto conv = dyn_cast<ConversionInst>(deallocOperand)) {
1973-
deallocOperand = conv->getConverted();
1974-
} else {
1975-
break;
1976-
}
1977-
}
1978-
if (isa<PartialApplyInst>(deallocOperand)) {
1965+
if (auto origPA = Inst->getNonescapingClosureAllocation()) {
19791966
recordClonedInstruction(Inst,
19801967
getBuilder().createDeallocStack(getOpLocation(Inst->getLoc()),
1981-
getOpValue(deallocOperand)));
1968+
getOpValue(origPA)));
19821969
}
19831970

19841971
return;

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8193,6 +8193,10 @@ class DestroyValueInst
81938193
void setPoisonRefs(bool poisonRefs = true) {
81948194
sharedUInt8().DestroyValueInst.poisonRefs = poisonRefs;
81958195
}
8196+
8197+
/// If the value being destroyed is a stack allocation of a nonescaping
8198+
/// closure, then return the PartialApplyInst that allocated the closure.
8199+
PartialApplyInst *getNonescapingClosureAllocation() const;
81968200
};
81978201

81988202
class MoveValueInst

lib/SIL/IR/SILInstruction.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,47 @@ PartialApplyInst::visitOnStackLifetimeEnds(
17051705
return !noUsers;
17061706
}
17071707

1708+
PartialApplyInst *
1709+
DestroyValueInst::getNonescapingClosureAllocation() const {
1710+
SILValue operand = getOperand();
1711+
auto operandFnTy = operand->getType().getAs<SILFunctionType>();
1712+
// The query doesn't make sense if we aren't operating on a noescape closure
1713+
// to begin with.
1714+
if (!operandFnTy || !operandFnTy->isTrivialNoEscape()) {
1715+
return nullptr;
1716+
}
1717+
1718+
// Look through marker and conversion instructions that would forward
1719+
// ownership of the original partial application.
1720+
while (true) {
1721+
if (auto mdi = dyn_cast<MarkDependenceInst>(operand)) {
1722+
operand = mdi->getValue();
1723+
continue;
1724+
} else if (isa<ConvertEscapeToNoEscapeInst>(operand)) {
1725+
// Stop at a conversion from escaping closure, since there's no stack
1726+
// allocation in that case.
1727+
return nullptr;
1728+
} else if (auto conv = dyn_cast<ConversionInst>(operand)) {
1729+
operand = conv->getConverted();
1730+
continue;
1731+
} else if (auto pa = dyn_cast<PartialApplyInst>(operand)) {
1732+
// If we found the `[on_stack]` partial apply, we're done.
1733+
if (pa->isOnStack()) {
1734+
return pa;
1735+
}
1736+
// Any other kind of partial apply fails to pass muster.
1737+
return nullptr;
1738+
} else {
1739+
// The original partial_apply instruction should only be forwarded
1740+
// through one of the above instructions. Anything else should lead us
1741+
// to a copy or borrow of the closure from somewhere else.
1742+
// TODO: Assert that this is one of those cases, such as a SILArgument,
1743+
// copy_value, etc.
1744+
return nullptr;
1745+
}
1746+
}
1747+
}
1748+
17081749
#ifndef NDEBUG
17091750

17101751
//---

lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -486,30 +486,14 @@ bool OwnershipModelEliminatorVisitor::visitDestroyValueInst(
486486
// we dealloc_stack the context.
487487
auto operand = dvi->getOperand();
488488
auto operandTy = operand->getType();
489-
if (auto operandFnTy = operandTy.getAs<SILFunctionType>()) {
489+
if (auto operandFnTy = operandTy.getAs<SILFunctionType>()){
490490
if (operandFnTy->isTrivialNoEscape()) {
491-
// Look through mark_dependence and other wrapper instructions.
492-
SILValue deallocOperand = operand;
493-
while (true) {
494-
if (auto mdi = dyn_cast<MarkDependenceInst>(deallocOperand)) {
495-
deallocOperand = mdi->getValue();
496-
} else if (isa<ConvertEscapeToNoEscapeInst>(deallocOperand)) {
497-
// If there's a surviving convert_escape_to_noescape that wasn't
498-
// turned into a stack closure, then stop here and just delete the
499-
// destroy_value, since the original escaping closure's lifetime
500-
// will persist.
501-
break;
502-
} else if (auto conv = dyn_cast<ConversionInst>(deallocOperand)) {
503-
deallocOperand = conv->getConverted();
504-
} else {
505-
break;
506-
}
507-
}
508-
if (isa<PartialApplyInst>(deallocOperand)) {
491+
if (auto origPA = dvi->getNonescapingClosureAllocation()) {
509492
withBuilder<void>(dvi, [&](SILBuilder &b, SILLocation loc) {
510-
b.createDeallocStack(loc, deallocOperand);
493+
b.createDeallocStack(loc, origPA);
511494
});
512495
}
496+
513497
eraseInstruction(dvi);
514498
return true;
515499
}

0 commit comments

Comments
 (0)