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