@@ -382,36 +382,26 @@ void Compiler::fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSw
382382 assert (fgPredsComputed);
383383
384384 // Walk the switch's jump table, updating the predecessor for each branch.
385- for (BasicBlock* const bJump : oldSwitchBlock->SwitchTargets ())
386- {
387- noway_assert (bJump != nullptr );
388-
389- // Note that if there are duplicate branch targets in the switch jump table,
390- // fgRemoveRefPred()/fgAddRefPred() will do the right thing: the second and
391- // subsequent duplicates will simply subtract from and add to the duplicate
392- // count (respectively).
393- //
394- // However this does the "wrong" thing with respect to edge profile
395- // data; the old edge is not returned by fgRemoveRefPred until it has
396- // a dup count of 0, and the fgAddRefPred only uses the optional
397- // old edge arg when the new edge is first created.
398- //
399- // Remove the old edge [oldSwitchBlock => bJump]
400- //
401- assert (bJump->countOfInEdges () > 0 );
402- FlowEdge* const oldEdge = fgRemoveRefPred (bJump, oldSwitchBlock);
385+ BBswtDesc* swtDesc = oldSwitchBlock->GetSwitchTargets ();
403386
404- //
405- // Create the new edge [newSwitchBlock => bJump]
406- //
407- FlowEdge* const newEdge = fgAddRefPred (bJump, newSwitchBlock );
387+ for ( unsigned i = 0 ; i < swtDesc-> bbsCount ; i++)
388+ {
389+ FlowEdge* succEdge = swtDesc-> bbsDstTab [i];
390+ assert (succEdge != nullptr );
408391
409- // Handle the profile update, once we get our hands on the old edge.
410- //
411- if (oldEdge != nullptr )
392+ if (succEdge->getSourceBlock () != oldSwitchBlock)
412393 {
413- assert (!newEdge->hasLikelihood ());
414- newEdge->setLikelihood (oldEdge->getLikelihood ());
394+ // swtDesc can have duplicate targets, so we may have updated this edge already
395+ //
396+ assert (succEdge->getSourceBlock () == newSwitchBlock);
397+ assert (succEdge->getDupCount () > 1 );
398+ }
399+ else
400+ {
401+ // Redirect edge's source block from oldSwitchBlock to newSwitchBlock,
402+ // and keep successor block's pred list in order
403+ //
404+ fgReplacePred (succEdge, newSwitchBlock);
415405 }
416406 }
417407
@@ -709,29 +699,17 @@ void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* oldTarget, Bas
709699
710700 case BBJ_SWITCH:
711701 {
712- unsigned const jumpCnt = block->GetSwitchTargets ()->bbsCount ;
713- BasicBlock ** const jumpTab = block->GetSwitchTargets ()->bbsDstTab ;
714- bool changed = false ;
702+ unsigned const jumpCnt = block->GetSwitchTargets ()->bbsCount ;
703+ FlowEdge ** const jumpTab = block->GetSwitchTargets ()->bbsDstTab ;
704+ bool changed = false ;
715705
716706 for (unsigned i = 0 ; i < jumpCnt; i++)
717707 {
718- if (jumpTab[i] == oldTarget)
708+ if (jumpTab[i]-> getDestinationBlock () == oldTarget)
719709 {
720- jumpTab[i] = newTarget;
721- changed = true ;
722- FlowEdge* const oldEdge = fgRemoveRefPred (oldTarget, block);
723- FlowEdge* const newEdge = fgAddRefPred (newTarget, block, oldEdge);
724-
725- // Handle the profile update, once we get our hands on the old edge.
726- // (see notes in fgChangeSwitchBlock for why this extra step is necessary)
727- //
728- // We do it slightly differently here so we don't lose the old
729- // edge weight propagation that would sometimes happen
730- //
731- if ((oldEdge != nullptr ) && !newEdge->hasLikelihood ())
732- {
733- newEdge->setLikelihood (oldEdge->getLikelihood ());
734- }
710+ fgRemoveRefPred (jumpTab[i]);
711+ jumpTab[i] = fgAddRefPred (newTarget, block, jumpTab[i]);
712+ changed = true ;
735713 }
736714 }
737715
@@ -3041,23 +3019,23 @@ void Compiler::fgLinkBasicBlocks()
30413019
30423020 case BBJ_SWITCH:
30433021 {
3044- unsigned jumpCnt = curBBdesc->GetSwitchTargets ()->bbsCount ;
3045- BasicBlock ** jumpPtr = curBBdesc->GetSwitchTargets ()->bbsDstTab ;
3022+ unsigned jumpCnt = curBBdesc->GetSwitchTargets ()->bbsCount ;
3023+ FlowEdge ** jumpPtr = curBBdesc->GetSwitchTargets ()->bbsDstTab ;
30463024
30473025 do
30483026 {
3049- BasicBlock* jumpDest = fgLookupBB ((unsigned )*(size_t *)jumpPtr);
3050- *jumpPtr = jumpDest;
3051- fgAddRefPred<initializingPreds>(jumpDest, curBBdesc) ;
3052- if ((*jumpPtr) ->bbNum <= curBBdesc->bbNum )
3027+ BasicBlock* jumpDest = fgLookupBB ((unsigned )*(size_t *)jumpPtr);
3028+ FlowEdge* const newEdge = fgAddRefPred<initializingPreds>( jumpDest, curBBdesc) ;
3029+ *jumpPtr = newEdge ;
3030+ if (jumpDest ->bbNum <= curBBdesc->bbNum )
30533031 {
3054- fgMarkBackwardJump (*jumpPtr , curBBdesc);
3032+ fgMarkBackwardJump (jumpDest , curBBdesc);
30553033 }
30563034 } while (++jumpPtr, --jumpCnt);
30573035
30583036 /* Default case of CEE_SWITCH (next block), is at end of jumpTab[] */
30593037
3060- noway_assert (curBBdesc->NextIs (*(jumpPtr - 1 )));
3038+ noway_assert (curBBdesc->NextIs (( *(jumpPtr - 1 ))-> getDestinationBlock ( )));
30613039 break ;
30623040 }
30633041
@@ -3220,8 +3198,8 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F
32203198 unsigned jmpBase;
32213199 unsigned jmpCnt; // # of switch cases (excluding default)
32223200
3223- BasicBlock ** jmpTab;
3224- BasicBlock ** jmpPtr;
3201+ FlowEdge ** jmpTab;
3202+ FlowEdge ** jmpPtr;
32253203
32263204 /* Allocate the switch descriptor */
32273205
@@ -3238,7 +3216,7 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F
32383216
32393217 /* Allocate the jump table */
32403218
3241- jmpPtr = jmpTab = new (this , CMK_BasicBlock) BasicBlock *[jmpCnt + 1 ];
3219+ jmpPtr = jmpTab = new (this , CMK_FlowEdge) FlowEdge *[jmpCnt + 1 ];
32423220
32433221 /* Fill in the jump table */
32443222
@@ -3248,12 +3226,12 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F
32483226 codeAddr += 4 ;
32493227
32503228 // store the offset in the pointer. We change these in fgLinkBasicBlocks().
3251- *jmpPtr++ = (BasicBlock *)(size_t )(jmpBase + jmpDist);
3229+ *jmpPtr++ = (FlowEdge *)(size_t )(jmpBase + jmpDist);
32523230 }
32533231
32543232 /* Append the default label to the target table */
32553233
3256- *jmpPtr++ = (BasicBlock *)(size_t )jmpBase;
3234+ *jmpPtr++ = (FlowEdge *)(size_t )jmpBase;
32573235
32583236 /* Make sure we found the right number of labels */
32593237
0 commit comments