@@ -421,27 +421,6 @@ static SILValue insertMarkDependenceForCapturedArguments(PartialApplyInst *pai,
421421 return curr;
422422}
423423
424- // / Returns the (single) "endAsyncLetLifetime" builtin if \p startAsyncLet is a
425- // / "startAsyncLetWithLocalBuffer" builtin.
426- static BuiltinInst *getEndAsyncLet (BuiltinInst *startAsyncLet) {
427- if (startAsyncLet->getBuiltinKind () != BuiltinValueKind::StartAsyncLetWithLocalBuffer)
428- return nullptr ;
429-
430- BuiltinInst *endAsyncLet = nullptr ;
431- for (Operand *op : startAsyncLet->getUses ()) {
432- auto *endBI = dyn_cast<BuiltinInst>(op->getUser ());
433- if (endBI && endBI->getBuiltinKind () == BuiltinValueKind::EndAsyncLetLifetime) {
434- // At this stage of the pipeline, it's always the case that a
435- // startAsyncLet has an endAsyncLet: that's how SILGen generates it.
436- // Just to be on the safe side, do this check.
437- if (endAsyncLet)
438- return nullptr ;
439- endAsyncLet = endBI;
440- }
441- }
442- return endAsyncLet;
443- }
444-
445424// / Call the \p insertFn with a builder at all insertion points after
446425// / a closure is used by \p closureUser.
447426static void insertAfterClosureUser (SILInstruction *closureUser,
@@ -467,14 +446,21 @@ static void insertAfterClosureUser(SILInstruction *closureUser,
467446 }
468447 }
469448
470- if (auto *startAsyncLet = dyn_cast<BuiltinInst>(closureUser)) {
471- BuiltinInst *endAsyncLet = getEndAsyncLet (startAsyncLet);
472- if (!endAsyncLet)
473- return ;
474- SILBuilderWithScope builder (std::next (endAsyncLet->getIterator ()));
475- insertFn (builder);
449+ // If the user is a startAsyncLet builtin, emit the code after all of the
450+ // endAsyncLetLifetime builtins.
451+ if (auto *startAsyncLet =
452+ isBuiltinInst (closureUser, BuiltinValueKind::StartAsyncLetWithLocalBuffer)) {
453+ for (Operand *op : startAsyncLet->getUses ()) {
454+ auto endAsyncLet = isBuiltinInst (op->getUser (),
455+ BuiltinValueKind::EndAsyncLetLifetime);
456+ if (!endAsyncLet) continue ;
457+
458+ SILBuilderWithScope builder (std::next (endAsyncLet->getIterator ()));
459+ insertFn (builder);
460+ }
476461 return ;
477462 }
463+
478464 FullApplySite fas = FullApplySite::isa (closureUser);
479465 assert (fas);
480466 fas.insertAfterApplication (insertFn);
@@ -1009,32 +995,43 @@ static bool tryExtendLifetimeToLastUse(
1009995 return false ;
1010996
1011997 // Handle apply instructions and startAsyncLet.
1012- BuiltinInst *endAsyncLet = nullptr ;
998+ BuiltinInst *startAsyncLet = nullptr ;
1013999 if (FullApplySite::isa (singleUser)) {
10141000 // TODO: Enable begin_apply/end_apply. It should work, but is not tested yet.
10151001 if (isa<BeginApplyInst>(singleUser))
10161002 return false ;
1017- } else if (auto *bi = dyn_cast<BuiltinInst>(singleUser)) {
1018- endAsyncLet = getEndAsyncLet (bi);
1019- if (!endAsyncLet)
1020- return false ;
1003+ } else if ((startAsyncLet = isBuiltinInst (singleUser,
1004+ BuiltinValueKind::StartAsyncLetWithLocalBuffer))) {
1005+ // continue
10211006 } else if (!isa<BeginBorrowInst>(singleUser)) {
10221007 return false ;
10231008 }
10241009
10251010 if (SILValue closureOp = tryRewriteToPartialApplyStack (
10261011 cvt, singleUser, dominanceAnalysis, deleter, memoized,
10271012 reachableBlocks, /* const*/ modifiedCFG)) {
1028- if (endAsyncLet) {
1013+ if (startAsyncLet) {
1014+ // Collect all of the endAsyncLet calls in one pass so that we can
1015+ // safely mutate the use-def chain in the second.
1016+ SmallVector<BuiltinInst*, 4 > endAsyncLets;
1017+ for (auto use: startAsyncLet->getUses ()) {
1018+ if (auto endAsyncLet =
1019+ isBuiltinInst (use->getUser (), BuiltinValueKind::EndAsyncLetLifetime)) {
1020+ endAsyncLets.push_back (endAsyncLet);
1021+ }
1022+ }
1023+
10291024 // Add the closure as a second operand to the endAsyncLet builtin.
10301025 // This ensures that the closure arguments are kept alive until the
10311026 // endAsyncLet builtin.
1032- assert (endAsyncLet->getNumOperands () == 1 );
1033- SILBuilderWithScope builder (endAsyncLet);
1034- builder.createBuiltin (endAsyncLet->getLoc (), endAsyncLet->getName (),
1035- endAsyncLet->getType (), endAsyncLet->getSubstitutions (),
1036- {endAsyncLet->getOperand (0 ), closureOp});
1037- deleter.forceDelete (endAsyncLet);
1027+ for (auto endAsyncLet: endAsyncLets) {
1028+ assert (endAsyncLet->getNumOperands () == 1 );
1029+ SILBuilderWithScope builder (endAsyncLet);
1030+ builder.createBuiltin (endAsyncLet->getLoc (), endAsyncLet->getName (),
1031+ endAsyncLet->getType (), endAsyncLet->getSubstitutions (),
1032+ {endAsyncLet->getOperand (0 ), closureOp});
1033+ deleter.forceDelete (endAsyncLet);
1034+ }
10381035 }
10391036 return true ;
10401037 }
0 commit comments