@@ -2318,8 +2318,9 @@ void PatternMatchEmission::initSharedCaseBlockDest(CaseStmt *caseBlock,
2318
2318
2319
2319
auto *block = SGF.createBasicBlock ();
2320
2320
result.first ->second .first = block;
2321
-
2322
- // Add args for any pattern variables
2321
+
2322
+ // If we do not have any bound decls, we do not need to setup any phi
2323
+ // arguments for the shared case block. Just bail early.
2323
2324
if (!caseBlock->hasBoundDecls ()) {
2324
2325
return ;
2325
2326
}
@@ -2353,6 +2354,7 @@ void PatternMatchEmission::emitAddressOnlyAllocations() {
2353
2354
for (auto &entry : SharedCases) {
2354
2355
CaseStmt *caseBlock = entry.first ;
2355
2356
2357
+ // If we do not have any bound decls, we can bail early.
2356
2358
if (!caseBlock->hasBoundDecls ()) {
2357
2359
continue ;
2358
2360
}
@@ -2426,11 +2428,9 @@ void PatternMatchEmission::emitSharedCaseBlocks() {
2426
2428
SGF.B .setInsertionPoint (predBB);
2427
2429
2428
2430
} else {
2429
- // FIXME: Figure out why this is necessary.
2430
- if (caseBB->pred_empty ()) {
2431
- SGF.eraseBasicBlock (caseBB);
2432
- continue ;
2433
- }
2431
+ // If we did not need a shared case block, we shouldn't have emitted one.
2432
+ assert (!caseBB->pred_empty () &&
2433
+ " Shared case block without predecessors?!" );
2434
2434
2435
2435
// Otherwise, move the block to after the first predecessor.
2436
2436
auto predBB = *caseBB->pred_begin ();
@@ -2646,32 +2646,36 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
2646
2646
auto caseBlock = row.getClientData <CaseStmt>();
2647
2647
SGF.emitProfilerIncrement (caseBlock);
2648
2648
2649
- // Certain case statements can be entered along multiple paths, either
2650
- // because they have multiple labels or because of fallthrough. When we
2651
- // need multiple entrance path, we factor the paths with a shared block.
2652
- if (!caseBlock->hasBoundDecls ()) {
2653
- // Don't emit anything yet, we emit it at the cleanup level of the switch
2654
- // statement.
2655
- JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2656
- SGF.Cleanups .emitBranchAndCleanups (sharedDest, caseBlock);
2657
- return ;
2658
- }
2659
-
2660
- // If we don't have a fallthrough or a multi-pattern 'case', we can just
2661
- // emit the body inline and save some dead blocks. Emit the statement here.
2649
+ // Certain case statements can be entered along multiple paths, either because
2650
+ // they have multiple labels or because of fallthrough. When we need multiple
2651
+ // entrance path, we factor the paths with a shared block. If we don't have a
2652
+ // fallthrough or a multi-pattern 'case', we can just emit the body inline and
2653
+ // save some dead blocks. Emit the statement here and bail early.
2662
2654
if (!row.hasFallthroughTo () && caseBlock->getCaseLabelItems ().size () == 1 ) {
2663
2655
emission.emitCaseBody (caseBlock);
2664
2656
return ;
2665
2657
}
2666
2658
2659
+ // Ok, at this point we know that we have a multiple entrance block. Grab our
2660
+ // shared destination in preperation for branching to it.
2661
+ //
2662
+ // NOTE: We do not emit anything yet, since we will emit the shared block
2663
+ // later.
2667
2664
JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2668
2665
2669
- // Generate the arguments from this row's pattern in the case block's
2670
- // expected order, and keep those arguments from being cleaned up, as
2671
- // we're passing the +1 along to the shared case block dest. (The
2672
- // cleanups still happen, as they are threaded through here messily,
2673
- // but the explicit retains here counteract them, and then the
2674
- // retain/release pair gets optimized out.)
2666
+ // If we do not have any bound decls, we do not need to setup any
2667
+ // variables. Just jump to the shared destination.
2668
+ if (!caseBlock->hasBoundDecls ()) {
2669
+ JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2670
+ SGF.Cleanups .emitBranchAndCleanups (sharedDest, caseBlock);
2671
+ return ;
2672
+ }
2673
+
2674
+ // Generate the arguments from this row's pattern in the case block's expected
2675
+ // order, and keep those arguments from being cleaned up, as we're passing the
2676
+ // +1 along to the shared case block dest. (The cleanups still happen, as they
2677
+ // are threaded through here messily, but the explicit retains here counteract
2678
+ // them, and then the retain/release pair gets optimized out.)
2675
2679
ArrayRef<CaseLabelItem> labelItems = caseBlock->getCaseLabelItems ();
2676
2680
SmallVector<SILValue, 4 > args;
2677
2681
SmallVector<VarDecl *, 4 > expectedVarOrder;
@@ -2741,9 +2745,10 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2741
2745
clauseRows.reserve (S->getRawCases ().size ());
2742
2746
bool hasFallthrough = false ;
2743
2747
for (auto caseBlock : S->getCases ()) {
2744
- if (!caseBlock->hasBoundDecls () ||
2745
- caseBlock->getCaseLabelItems ().size () > 1 ||
2746
- hasFallthrough) {
2748
+ // If the previous block falls through into this block or we have multiple
2749
+ // case label itmes, create a shared case block to generate the shared
2750
+ // block.
2751
+ if (hasFallthrough || caseBlock->getCaseLabelItems ().size () > 1 ) {
2747
2752
emission.initSharedCaseBlockDest (caseBlock, hasFallthrough);
2748
2753
}
2749
2754
0 commit comments