@@ -2318,8 +2318,9 @@ void PatternMatchEmission::initSharedCaseBlockDest(CaseStmt *caseBlock,
23182318
23192319 auto *block = SGF.createBasicBlock ();
23202320 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.
23232324 if (!caseBlock->hasBoundDecls ()) {
23242325 return ;
23252326 }
@@ -2355,6 +2356,7 @@ void PatternMatchEmission::emitAddressOnlyAllocations() {
23552356 for (auto &entry : SharedCases) {
23562357 CaseStmt *caseBlock = entry.first ;
23572358
2359+ // If we do not have any bound decls, we can bail early.
23582360 if (!caseBlock->hasBoundDecls ()) {
23592361 continue ;
23602362 }
@@ -2429,11 +2431,9 @@ void PatternMatchEmission::emitSharedCaseBlocks() {
24292431 SGF.B .setInsertionPoint (predBB);
24302432
24312433 } 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?!" );
24372437
24382438 // Otherwise, move the block to after the first predecessor.
24392439 auto predBB = *caseBB->pred_begin ();
@@ -2651,32 +2651,36 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26512651 auto caseBlock = row.getClientData <CaseStmt>();
26522652 SGF.emitProfilerIncrement (caseBlock);
26532653
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.
26672659 if (!row.hasFallthroughTo () && caseBlock->getCaseLabelItems ().size () == 1 ) {
26682660 emission.emitCaseBody (caseBlock);
26692661 return ;
26702662 }
26712663
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.
26722669 JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
26732670
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.)
26802684 ArrayRef<CaseLabelItem> labelItems = caseBlock->getCaseLabelItems ();
26812685 SmallVector<SILValue, 4 > args;
26822686 SmallVector<VarDecl *, 4 > expectedVarOrder;
@@ -2746,9 +2750,10 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
27462750 clauseRows.reserve (S->getRawCases ().size ());
27472751 bool hasFallthrough = false ;
27482752 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 ) {
27522757 emission.initSharedCaseBlockDest (caseBlock, hasFallthrough);
27532758 }
27542759
0 commit comments