Skip to content

Commit b8169f2

Browse files
authored
Merge pull request #13256 from gottesmm/pr-32910d38250e0b4150eb84cd3ae8d42ccf6661a6
2 parents 1006a6e + 4ac14ce commit b8169f2

File tree

1 file changed

+61
-42
lines changed

1 file changed

+61
-42
lines changed

lib/SILGen/SILGenEpilog.cpp

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -67,36 +67,36 @@ static SILValue buildReturnValue(SILGenFunction &SGF, SILLocation loc,
6767
return SGF.B.createTuple(loc, resultType, directResults);
6868
}
6969

70-
std::pair<Optional<SILValue>, SILLocation>
71-
SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
72-
assert(ReturnDest.getBlock() && "no epilog bb prepared?!");
73-
SILBasicBlock *epilogBB = ReturnDest.getBlock();
74-
SILLocation ImplicitReturnFromTopLevel =
75-
ImplicitReturnLocation::getImplicitReturnLoc(TopLevel);
76-
SmallVector<SILValue, 4> directResults;
77-
Optional<SILLocation> returnLoc = None;
78-
79-
// If the current BB isn't terminated, and we require a return, then we
70+
static Optional<SILLocation>
71+
prepareForEpilogBlockEmission(SILGenFunction &SGF, SILLocation topLevel,
72+
SILBasicBlock *epilogBB,
73+
SmallVectorImpl<SILValue> &directResults) {
74+
SILLocation implicitReturnFromTopLevel =
75+
ImplicitReturnLocation::getImplicitReturnLoc(topLevel);
76+
77+
// If the current BB we are inserting into isn't terminated, and we require a
78+
// return, then we
8079
// are not allowed to fall off the end of the function and can't reach here.
81-
if (NeedsReturn && B.hasValidInsertionPoint())
82-
B.createUnreachable(ImplicitReturnFromTopLevel);
80+
if (SGF.NeedsReturn && SGF.B.hasValidInsertionPoint())
81+
SGF.B.createUnreachable(implicitReturnFromTopLevel);
8382

8483
if (epilogBB->pred_empty()) {
8584
// If the epilog was not branched to at all, kill the BB and
8685
// just emit the epilog into the current BB.
8786
while (!epilogBB->empty())
8887
epilogBB->back().eraseFromParent();
89-
eraseBasicBlock(epilogBB);
88+
SGF.eraseBasicBlock(epilogBB);
9089

9190
// If the current bb is terminated then the epilog is just unreachable.
92-
if (!B.hasValidInsertionPoint())
93-
return { None, TopLevel };
91+
if (!SGF.B.hasValidInsertionPoint())
92+
return None;
9493

9594
// We emit the epilog at the current insertion point.
96-
returnLoc = ImplicitReturnFromTopLevel;
95+
return implicitReturnFromTopLevel;
96+
}
9797

98-
} else if (std::next(epilogBB->pred_begin()) == epilogBB->pred_end()
99-
&& !B.hasValidInsertionPoint()) {
98+
if (std::next(epilogBB->pred_begin()) == epilogBB->pred_end() &&
99+
!SGF.B.hasValidInsertionPoint()) {
100100
// If the epilog has a single predecessor and there's no current insertion
101101
// point to fall through from, then we can weld the epilog to that
102102
// predecessor BB.
@@ -113,52 +113,71 @@ SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
113113
epilogBB->getArgument(index)->replaceAllUsesWith(result);
114114
}
115115

116+
Optional<SILLocation> returnLoc;
116117
// If we are optimizing, we should use the return location from the single,
117118
// previously processed, return statement if any.
118119
if (predBranch->getLoc().is<ReturnLocation>()) {
119120
returnLoc = predBranch->getLoc();
120121
} else {
121-
returnLoc = ImplicitReturnFromTopLevel;
122+
returnLoc = implicitReturnFromTopLevel;
122123
}
123-
124+
124125
// Kill the branch to the now-dead epilog BB.
125126
pred->erase(predBranch);
126127

127128
// Move any instructions from the EpilogBB to the end of the 'pred' block.
128129
pred->spliceAtEnd(epilogBB);
129130

130131
// Finally we can erase the epilog BB.
131-
eraseBasicBlock(epilogBB);
132+
SGF.eraseBasicBlock(epilogBB);
132133

133134
// Emit the epilog into its former predecessor.
134-
B.setInsertionPoint(pred);
135-
} else {
136-
// Move the epilog block to the end of the ordinary section.
137-
auto endOfOrdinarySection = StartOfPostmatter;
138-
B.moveBlockTo(epilogBB, endOfOrdinarySection);
135+
SGF.B.setInsertionPoint(pred);
136+
return returnLoc;
137+
}
139138

140-
// Emit the epilog into the epilog bb. Its arguments are the
141-
// direct results.
142-
directResults.append(epilogBB->args_begin(), epilogBB->args_end());
139+
// Move the epilog block to the end of the ordinary section.
140+
auto endOfOrdinarySection = SGF.StartOfPostmatter;
141+
SGF.B.moveBlockTo(epilogBB, endOfOrdinarySection);
143142

144-
// If we are falling through from the current block, the return is implicit.
145-
B.emitBlock(epilogBB, ImplicitReturnFromTopLevel);
146-
}
147-
148-
// Emit top-level cleanups into the epilog block.
149-
assert(!Cleanups.hasAnyActiveCleanups(getCleanupsDepth(),
150-
ReturnDest.getDepth()) &&
151-
"emitting epilog in wrong scope");
143+
// Emit the epilog into the epilog bb. Its arguments are the
144+
// direct results.
145+
directResults.append(epilogBB->args_begin(), epilogBB->args_end());
152146

153-
auto cleanupLoc = CleanupLocation::get(TopLevel);
154-
Cleanups.emitCleanupsForReturn(cleanupLoc);
147+
// If we are falling through from the current block, the return is implicit.
148+
SGF.B.emitBlock(epilogBB, implicitReturnFromTopLevel);
155149

156150
// If the return location is known to be that of an already
157151
// processed return, use it. (This will get triggered when the
158152
// epilog logic is simplified.)
159153
//
160154
// Otherwise make the ret instruction part of the cleanups.
161-
if (!returnLoc) returnLoc = cleanupLoc;
155+
auto cleanupLoc = CleanupLocation::get(topLevel);
156+
return cleanupLoc;
157+
}
158+
159+
std::pair<Optional<SILValue>, SILLocation>
160+
SILGenFunction::emitEpilogBB(SILLocation topLevel) {
161+
assert(ReturnDest.getBlock() && "no epilog bb prepared?!");
162+
SILBasicBlock *epilogBB = ReturnDest.getBlock();
163+
SmallVector<SILValue, 8> directResults;
164+
165+
// Prepare the epilog block for emission. If we need to actually emit the
166+
// block, we return a real SILLocation. Otherwise, the epilog block is
167+
// actually unreachable and we can just return early.
168+
auto returnLoc =
169+
prepareForEpilogBlockEmission(*this, topLevel, epilogBB, directResults);
170+
if (!returnLoc.hasValue()) {
171+
return {None, topLevel};
172+
}
173+
174+
// Emit top-level cleanups into the epilog block.
175+
assert(!Cleanups.hasAnyActiveCleanups(getCleanupsDepth(),
176+
ReturnDest.getDepth()) &&
177+
"emitting epilog in wrong scope");
178+
179+
auto cleanupLoc = CleanupLocation::get(topLevel);
180+
Cleanups.emitCleanupsForReturn(cleanupLoc);
162181

163182
// Build the return value. We don't do this if there are no direct
164183
// results; this can happen for void functions, but also happens when
@@ -167,10 +186,10 @@ SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
167186
SILValue returnValue;
168187
if (!directResults.empty()) {
169188
assert(directResults.size() == F.getConventions().getNumDirectSILResults());
170-
returnValue = buildReturnValue(*this, TopLevel, directResults);
189+
returnValue = buildReturnValue(*this, topLevel, directResults);
171190
}
172191

173-
return { returnValue, *returnLoc };
192+
return {returnValue, *returnLoc};
174193
}
175194

176195
SILLocation SILGenFunction::

0 commit comments

Comments
 (0)