Skip to content

Commit 4612728

Browse files
committed
[NFC] Add BeginApplyInst::getEndApplyUses() API.
A begin_apply token may be used by operands that do not end the coroutine: mark_dependence. We need an API that gives us only the coroutine-ending uses. This blocks ~Escapable accessors. end_borrow is considered coroutine-ending even though it does not actually terminate the coroutine. We cannot simply ask isLifetimeEnding, because end_apply and abort_apply do not end any lifetime.
1 parent c5de02f commit 4612728

File tree

10 files changed

+56
-27
lines changed

10 files changed

+56
-27
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3217,6 +3217,13 @@ class EndApplyInst;
32173217
class AbortApplyInst;
32183218
class EndBorrowInst;
32193219

3220+
struct EndApplyFilter {
3221+
std::optional<Operand*> operator()(Operand *use) const;
3222+
};
3223+
3224+
using EndApplyRange = OptionalTransformRange<ValueBase::use_range,
3225+
EndApplyFilter>;
3226+
32203227
/// BeginApplyInst - Represents the beginning of the full application of
32213228
/// a yield_once coroutine (up until the coroutine yields a value back).
32223229
class BeginApplyInst final
@@ -3267,6 +3274,8 @@ class BeginApplyInst final
32673274
&getAllResultsBuffer().drop_back(isCalleeAllocated() ? 1 : 0).back());
32683275
}
32693276

3277+
EndApplyRange getEndApplyUses() const;
3278+
32703279
MultipleValueInstructionResult *getCalleeAllocationResult() const {
32713280
if (!isCalleeAllocated()) {
32723281
return nullptr;
@@ -3336,6 +3345,25 @@ class EndApplyInst
33363345
}
33373346
};
33383347

3348+
inline std::optional<Operand*>
3349+
EndApplyFilter::operator()(Operand *use) const {
3350+
// An end_borrow ends the coroutine scope at a dead-end block without
3351+
// terminating the coroutine.
3352+
switch (use->getUser()->getKind()) {
3353+
case SILInstructionKind::EndApplyInst:
3354+
case SILInstructionKind::AbortApplyInst:
3355+
case SILInstructionKind::EndBorrowInst:
3356+
return use;
3357+
default:
3358+
return std::nullopt;
3359+
}
3360+
}
3361+
3362+
inline EndApplyRange BeginApplyInst::getEndApplyUses() const {
3363+
return makeOptionalTransformRange(
3364+
getTokenResult()->getUses(), EndApplyFilter());
3365+
}
3366+
33393367
//===----------------------------------------------------------------------===//
33403368
// Literal instructions.
33413369
//===----------------------------------------------------------------------===//
@@ -8802,6 +8830,11 @@ class MarkDependenceInst
88028830
uint8_t(MarkDependenceKind::NonEscaping);
88038831
}
88048832

8833+
void settleToEscaping() {
8834+
sharedUInt8().MarkDependenceInst.dependenceKind =
8835+
uint8_t(MarkDependenceKind::Escaping);
8836+
}
8837+
88058838
/// Visit the instructions that end the lifetime of an OSSA on-stack closure.
88068839
bool visitNonEscapingLifetimeEnds(
88078840
llvm::function_ref<bool (Operand*)> visitScopeEnd,

lib/SIL/IR/SILInstructions.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,8 @@ void BeginApplyInst::getCoroutineEndPoints(
712712
SmallVectorImpl<EndApplyInst *> &endApplyInsts,
713713
SmallVectorImpl<AbortApplyInst *> &abortApplyInsts,
714714
SmallVectorImpl<EndBorrowInst *> *endBorrowInsts) const {
715-
for (auto *tokenUse : getTokenResult()->getUses()) {
716-
auto *user = tokenUse->getUser();
715+
for (auto *use : getEndApplyUses()) {
716+
auto *user = use->getUser();
717717
if (auto *end = dyn_cast<EndApplyInst>(user)) {
718718
endApplyInsts.push_back(end);
719719
continue;
@@ -733,19 +733,19 @@ void BeginApplyInst::getCoroutineEndPoints(
733733
SmallVectorImpl<Operand *> &endApplyInsts,
734734
SmallVectorImpl<Operand *> &abortApplyInsts,
735735
SmallVectorImpl<Operand *> *endBorrowInsts) const {
736-
for (auto *tokenUse : getTokenResult()->getUses()) {
737-
auto *user = tokenUse->getUser();
736+
for (auto *use : getEndApplyUses()) {
737+
auto *user = use->getUser();
738738
if (isa<EndApplyInst>(user)) {
739-
endApplyInsts.push_back(tokenUse);
739+
endApplyInsts.push_back(use);
740740
continue;
741741
}
742742
if (isa<AbortApplyInst>(user)) {
743-
abortApplyInsts.push_back(tokenUse);
743+
abortApplyInsts.push_back(use);
744744
continue;
745745
}
746746

747747
assert(isa<EndBorrowInst>(user));
748-
abortApplyInsts.push_back(tokenUse);
748+
abortApplyInsts.push_back(use);
749749
}
750750
}
751751

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,8 +694,7 @@ bool BorrowingOperand::visitScopeEndingUses(
694694
}
695695
case BorrowingOperandKind::BeginApply: {
696696
bool deadApply = true;
697-
auto *user = cast<BeginApplyInst>(op->getUser());
698-
for (auto *use : user->getTokenResult()->getUses()) {
697+
for (auto *use : cast<BeginApplyInst>(op->getUser())->getEndApplyUses()) {
699698
deadApply = false;
700699
if (!visitScopeEnd(use))
701700
return false;

lib/SIL/Verifier/SILOwnershipVerifier.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,7 @@ bool SILValueOwnershipChecker::checkYieldWithoutLifetimeEndingUses(
583583
// If we have a guaranteed value, make sure that all uses are before our
584584
// end_yield.
585585
SmallVector<Operand *, 4> coroutineEndUses;
586-
for (auto *use : yield->getParent<BeginApplyInst>()->
587-
getTokenResult()->getUses()) {
586+
for (auto *use : yield->getParent<BeginApplyInst>()->getEndApplyUses()) {
588587
coroutineEndUses.push_back(use);
589588
}
590589

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,8 +2682,8 @@ void ApplyRewriter::convertBeginApplyWithOpaqueYield() {
26822682
SILValue load =
26832683
resultBuilder.emitLoadBorrowOperation(callLoc, &newResult);
26842684
oldResult.replaceAllUsesWith(load);
2685-
for (auto *user : origCall->getTokenResult()->getUsers()) {
2686-
pass.getBuilder(user->getIterator())
2685+
for (auto *use : origCall->getEndApplyUses()) {
2686+
pass.getBuilder(use->getUser()->getIterator())
26872687
.createEndBorrow(pass.genLoc(), load);
26882688
}
26892689
} else {

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,8 @@ static bool visitScopeEndsRequiringInit(
453453
// Check for yields from a modify coroutine.
454454
if (auto bai =
455455
dyn_cast_or_null<BeginApplyInst>(operand->getDefiningInstruction())) {
456-
for (auto *inst : bai->getTokenResult()->getUsers()) {
456+
for (auto *use : bai->getEndApplyUses()) {
457+
auto *inst = use->getUser();
457458
assert(isa<EndApplyInst>(inst) || isa<AbortApplyInst>(inst) ||
458459
isa<EndBorrowInst>(inst));
459460
visit(inst, ScopeRequiringFinalInit::Coroutine);

lib/SILOptimizer/Transforms/TempRValueElimination.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,8 @@ collectLoads(Operand *addressUse, CopyAddrInst *originalCopy,
210210
// Register 'end_apply'/'abort_apply' as loads as well
211211
// 'checkNoSourceModification' should check instructions until
212212
// 'end_apply'/'abort_apply'.
213-
for (auto tokenUse : beginApply->getTokenResult()->getUses()) {
214-
SILInstruction *tokenUser = tokenUse->getUser();
213+
for (auto *tokenUse : beginApply->getEndApplyUses()) {
214+
auto *tokenUser = tokenUse->getUser();
215215
if (tokenUser->getParent() != block)
216216
return false;
217217
loadInsts.insert(tokenUser);

lib/SILOptimizer/Utils/Devirtualize.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -643,14 +643,11 @@ replaceBeginApplyInst(SILBuilder &builder, SILPassManager *pm, SILLocation loc,
643643
if (newArgBorrows.empty())
644644
return {newBAI, changedCFG};
645645

646-
SILValue token = newBAI->getTokenResult();
647-
648-
// The token will only be used by end_apply and abort_apply. Use that to
649-
// insert the end_borrows we need /after/ those uses.
650-
for (auto *use : token->getUses()) {
646+
// Insert the end_borrows after end_apply and abort_apply users.
647+
for (auto *use : newBAI->getEndApplyUses()) {
651648
SILBuilderWithScope borrowBuilder(
652-
&*std::next(use->getUser()->getIterator()),
653-
builder.getBuilderContext());
649+
&*std::next(use->getUser()->getIterator()),
650+
builder.getBuilderContext());
654651
for (SILValue borrow : newArgBorrows) {
655652
borrowBuilder.createEndBorrow(loc, borrow);
656653
}

lib/SILOptimizer/Utils/LoopUtils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,8 @@ bool swift::canDuplicateLoopInstruction(SILLoop *L, SILInstruction *I) {
309309
// contains an end_apply or abort_apply of an external begin_apply ---
310310
// because that wouldn't be structurally valid in the first place.
311311
if (auto BAI = dyn_cast<BeginApplyInst>(I)) {
312-
for (auto UI : BAI->getTokenResult()->getUses()) {
313-
auto User = UI->getUser();
312+
for (auto *Use : BAI->getEndApplyUses()) {
313+
auto *User = Use->getUser();
314314
assert(isa<EndApplyInst>(User) || isa<AbortApplyInst>(User) ||
315315
isa<EndBorrowInst>(User));
316316
if (!L->contains(User))

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ bool SILInliner::canInlineBeginApply(BeginApplyInst *BA) {
3737
// handle this in general, we'd need to separately clone the resume/unwind
3838
// paths into each end/abort.
3939
bool hasEndApply = false, hasAbortApply = false;
40-
for (auto tokenUse : BA->getTokenResult()->getUses()) {
41-
auto user = tokenUse->getUser();
40+
for (auto *use : BA->getEndApplyUses()) {
41+
auto *user = use->getUser();
4242
if (isa<EndApplyInst>(user)) {
4343
if (hasEndApply) return false;
4444
hasEndApply = true;

0 commit comments

Comments
 (0)