Skip to content

Commit 297711d

Browse files
Merge pull request #62047 from nate-chandler/opaque-values/1/20221110
[AddressLowering] Rewrite indirect begin_applies
2 parents 47f02a7 + b64510d commit 297711d

File tree

2 files changed

+277
-30
lines changed

2 files changed

+277
-30
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ static SILFunctionConventions getLoweredCallConv(ApplySite call) {
195195
/// If \p pseudoResult represents multiple results and at least one result is
196196
/// used, then return the destructure.
197197
static DestructureTupleInst *getCallDestructure(FullApplySite apply) {
198+
if (apply.getKind() == FullApplySiteKind::BeginApplyInst)
199+
return nullptr;
198200
if (apply.getSubstCalleeConv().getNumDirectSILResults() == 1)
199201
return nullptr;
200202

@@ -640,7 +642,8 @@ void OpaqueValueVisitor::checkForIndirectApply(FullApplySite applySite) {
640642
++calleeArgIdx;
641643
}
642644

643-
if (applySite.getSubstCalleeType()->hasIndirectFormalResults()) {
645+
if (applySite.getSubstCalleeType()->hasIndirectFormalResults() ||
646+
applySite.getSubstCalleeType()->hasIndirectFormalYields()) {
644647
pass.indirectApplies.insert(applySite);
645648
}
646649
}
@@ -2120,7 +2123,16 @@ void ApplyRewriter::rewriteApply(ArrayRef<SILValue> newCallArgs) {
21202123
// will be deleted with its destructure_tuple.
21212124
}
21222125

2126+
/// Emit end_borrows for a an incomplete BorrowedValue with only nonlifetime
2127+
/// ending uses.
2128+
static void emitEndBorrows(SILValue value, AddressLoweringState &pass);
2129+
21232130
void ApplyRewriter::convertBeginApplyWithOpaqueYield() {
2131+
// Avoid revisiting this apply.
2132+
bool erased = pass.indirectApplies.erase(apply);
2133+
assert(erased && "all yields should be rewritten at the same time");
2134+
(void)erased;
2135+
21242136
auto *origCall = cast<BeginApplyInst>(apply.getInstruction());
21252137
SmallVector<SILValue, 4> opValues;
21262138

@@ -2140,11 +2152,33 @@ void ApplyRewriter::convertBeginApplyWithOpaqueYield() {
21402152
auto newResults = newCall->getAllResultsBuffer();
21412153
assert(oldResults.size() == newResults.size());
21422154
for (auto i : indices(oldResults)) {
2143-
if (oldResults[i].getType().isAddressOnly(*pass.function)) {
2144-
pass.valueStorageMap.setStorageAddress(&oldResults[i], &newResults[i]);
2145-
pass.valueStorageMap.getStorage(&oldResults[i]).markRewritten();
2155+
auto &oldResult = oldResults[i];
2156+
auto &newResult = newResults[i];
2157+
if (oldResult.getType().isAddressOnly(*pass.function)) {
2158+
if (!oldResult.getType().isAddress()) {
2159+
pass.valueStorageMap.setStorageAddress(&oldResult, &newResult);
2160+
pass.valueStorageMap.getStorage(&oldResult).markRewritten();
2161+
} else {
2162+
oldResult.replaceAllUsesWith(&newResult);
2163+
}
21462164
} else {
2147-
oldResults[i].replaceAllUsesWith(&newResults[i]);
2165+
if (oldResult.getType().isObject() && newResult.getType().isAddress()) {
2166+
if (oldResult.getOwnershipKind() == OwnershipKind::Guaranteed) {
2167+
SILValue load =
2168+
resultBuilder.emitLoadBorrowOperation(callLoc, &newResult);
2169+
oldResult.replaceAllUsesWith(load);
2170+
emitEndBorrows(load, pass);
2171+
} else {
2172+
auto *load = resultBuilder.createLoad(
2173+
callLoc, &newResult,
2174+
newResult.getType().isTrivial(*pass.function)
2175+
? LoadOwnershipQualifier::Trivial
2176+
: LoadOwnershipQualifier::Take);
2177+
oldResult.replaceAllUsesWith(load);
2178+
}
2179+
} else {
2180+
oldResult.replaceAllUsesWith(&newResult);
2181+
}
21482182
}
21492183
}
21502184
}
@@ -2762,10 +2796,6 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
27622796

27632797
void visitStoreInst(StoreInst *storeInst);
27642798

2765-
/// Emit end_borrows for a an incomplete BorrowedValue with only nonlifetime
2766-
/// ending uses.
2767-
void emitEndBorrows(SILValue value);
2768-
27692799
void emitExtract(SingleValueInstruction *extractInst);
27702800

27712801
void visitSelectEnumInst(SelectEnumInst *sei) {
@@ -2832,7 +2862,7 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
28322862
builder.emitLoadBorrowOperation(uncheckedCastInst->getLoc(), destAddr);
28332863
uncheckedCastInst->replaceAllUsesWith(load);
28342864
pass.deleter.forceDelete(uncheckedCastInst);
2835-
emitEndBorrows(load);
2865+
emitEndBorrows(load, pass);
28362866
}
28372867

28382868
void visitUnconditionalCheckedCastInst(
@@ -2944,7 +2974,7 @@ void UseRewriter::visitStoreInst(StoreInst *storeInst) {
29442974

29452975
/// Emit end_borrows for a an incomplete BorrowedValue with only nonlifetime
29462976
/// ending uses. This function inserts end_borrows on the lifetime boundary.
2947-
void UseRewriter::emitEndBorrows(SILValue value) {
2977+
static void emitEndBorrows(SILValue value, AddressLoweringState &pass) {
29482978
assert(BorrowedValue(value));
29492979

29502980
// Place end_borrows that cover the load_borrow uses. It is not necessary to
@@ -3002,7 +3032,7 @@ void UseRewriter::emitExtract(SingleValueInstruction *extractInst) {
30023032
SILValue loadElement =
30033033
builder.emitLoadBorrowOperation(extractInst->getLoc(), extractAddr);
30043034
replaceUsesWithLoad(extractInst, loadElement);
3005-
emitEndBorrows(loadElement);
3035+
emitEndBorrows(loadElement, pass);
30063036
}
30073037

30083038
void UseRewriter::visitStructExtractInst(StructExtractInst *extractInst) {
@@ -3369,14 +3399,27 @@ static void rewriteIndirectApply(FullApplySite apply,
33693399
// If all indirect args were loadable, then they still need to be rewritten.
33703400
CallArgRewriter(apply, pass).rewriteArguments();
33713401

3372-
if (!apply.getSubstCalleeType()->hasIndirectFormalResults()) {
3373-
return;
3402+
switch (apply.getKind()) {
3403+
case FullApplySiteKind::ApplyInst:
3404+
case FullApplySiteKind::TryApplyInst: {
3405+
if (!apply.getSubstCalleeType()->hasIndirectFormalResults()) {
3406+
return;
3407+
}
3408+
// If the call has indirect results and wasn't already rewritten, rewrite it
3409+
// now. This handles try_apply, which is not rewritten when DefRewriter
3410+
// visits block arguments. It also handles apply with loadable indirect
3411+
// results.
3412+
ApplyRewriter(apply, pass).convertApplyWithIndirectResults();
3413+
break;
3414+
}
3415+
case FullApplySiteKind::BeginApplyInst: {
3416+
if (!apply.getSubstCalleeType()->hasIndirectFormalYields()) {
3417+
return;
3418+
}
3419+
ApplyRewriter(apply, pass).convertBeginApplyWithOpaqueYield();
3420+
break;
3421+
}
33743422
}
3375-
3376-
// If the call has indirect results and wasn't already rewritten, rewrite it
3377-
// now. This handles try_apply, which is not rewritten when DefRewriter visits
3378-
// block arguments. It also handles apply with loadable indirect results.
3379-
ApplyRewriter(apply, pass).convertApplyWithIndirectResults();
33803423

33813424
if (!apply.getInstruction()->isDeleted()) {
33823425
assert(!getCallDestructure(apply)

0 commit comments

Comments
 (0)