Skip to content

Commit 5cc02f6

Browse files
authored
JIT: update fgReplaceJumpTarget to maintain pred lists (#81246)
This is used some early phases; make it pred list aware. Contributes to #80193.
1 parent d2eed6c commit 5cc02f6

4 files changed

Lines changed: 45 additions & 57 deletions

File tree

src/coreclr/jit/fgbasic.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -540,14 +540,12 @@ void Compiler::fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* ne
540540
//
541541
// Notes:
542542
// 1. Only branches are changed: BBJ_ALWAYS, the non-fallthrough path of BBJ_COND, BBJ_SWITCH, etc.
543-
// We ignore other block types.
543+
// We assert for other jump kinds.
544544
// 2. All branch targets found are updated. If there are multiple ways for a block
545545
// to reach 'oldTarget' (e.g., multiple arms of a switch), all of them are changed.
546-
// 3. The predecessor lists are not changed.
546+
// 3. The predecessor lists are updated, if they've been built.
547547
// 4. If any switch table entry was updated, the switch table "unique successor" cache is invalidated.
548548
//
549-
// This function is most useful early, before the full predecessor lists have been computed.
550-
//
551549
void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget)
552550
{
553551
assert(block != nullptr);
@@ -559,18 +557,18 @@ void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, Bas
559557
case BBJ_ALWAYS:
560558
case BBJ_EHCATCHRET:
561559
case BBJ_EHFILTERRET:
562-
case BBJ_LEAVE: // This function will be called before import, so we still have BBJ_LEAVE
560+
case BBJ_LEAVE: // This function can be called before import, so we still have BBJ_LEAVE
563561

564562
if (block->bbJumpDest == oldTarget)
565563
{
566564
block->bbJumpDest = newTarget;
567-
}
568-
break;
569565

570-
case BBJ_NONE:
571-
case BBJ_EHFINALLYRET:
572-
case BBJ_THROW:
573-
case BBJ_RETURN:
566+
if (fgComputePredsDone)
567+
{
568+
fgRemoveRefPred(oldTarget, block);
569+
fgAddRefPred(newTarget, block);
570+
}
571+
}
574572
break;
575573

576574
case BBJ_SWITCH:
@@ -585,6 +583,12 @@ void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, Bas
585583
{
586584
jumpTab[i] = newTarget;
587585
changed = true;
586+
587+
if (fgComputePredsDone)
588+
{
589+
fgRemoveRefPred(oldTarget, block);
590+
fgAddRefPred(newTarget, block);
591+
}
588592
}
589593
}
590594

@@ -596,7 +600,7 @@ void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, Bas
596600
}
597601

598602
default:
599-
assert(!"Block doesn't have a valid bbJumpKind!!!!");
603+
assert(!"Block doesn't have a jump target!");
600604
unreached();
601605
break;
602606
}

src/coreclr/jit/fgopt.cpp

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,38 +2010,36 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext)
20102010
/* both or none must have an exception handler */
20112011
noway_assert(block->hasTryIndex() == bNext->hasTryIndex());
20122012

2013-
#ifdef DEBUG
2014-
if (verbose)
2015-
{
2016-
printf("\nCompacting blocks " FMT_BB " and " FMT_BB ":\n", block->bbNum, bNext->bbNum);
2017-
}
2018-
#endif
2013+
JITDUMP("\nCompacting " FMT_BB " into " FMT_BB ":\n", bNext->bbNum, block->bbNum);
2014+
fgRemoveRefPred(bNext, block);
20192015

2020-
if (bNext->countOfInEdges() > 1)
2016+
if (bNext->countOfInEdges() > 0)
20212017
{
2022-
JITDUMP("Second block has multiple incoming edges\n");
2018+
JITDUMP("Second block has %u other incoming edges\n", bNext->countOfInEdges());
20232019
assert(block->isEmpty());
20242020

2021+
// `block` can no longer be a loop pre-header (if it was before).
2022+
//
2023+
block->bbFlags &= ~BBF_LOOP_PREHEADER;
2024+
2025+
// Retarget all the other edges incident on bNext. Do this
2026+
// in two passes as we can't both walk and modify the pred list.
2027+
//
2028+
ArrayStack<BasicBlock*> preds(getAllocator(CMK_BasicBlock), bNext->countOfInEdges());
20252029
for (BasicBlock* const predBlock : bNext->PredBlocks())
20262030
{
2031+
preds.Push(predBlock);
2032+
}
2033+
while (preds.Height() > 0)
2034+
{
2035+
BasicBlock* const predBlock = preds.Pop();
20272036
fgReplaceJumpTarget(predBlock, block, bNext);
2028-
2029-
if (predBlock != block)
2030-
{
2031-
fgAddRefPred(block, predBlock);
2032-
}
20332037
}
2034-
bNext->bbPreds = nullptr;
2035-
2036-
// `block` can no longer be a loop pre-header (if it was before).
2037-
block->bbFlags &= ~BBF_LOOP_PREHEADER;
2038-
}
2039-
else
2040-
{
2041-
noway_assert(bNext->bbPreds->flNext == nullptr);
2042-
noway_assert(bNext->bbPreds->getBlock() == block);
20432038
}
20442039

2040+
assert(bNext->countOfInEdges() == 0);
2041+
assert(bNext->bbPreds == nullptr);
2042+
20452043
/* Start compacting - move all the statements in the second block to the first block */
20462044

20472045
// First move any phi definitions of the second block after the phi defs of the first.

src/coreclr/jit/jiteh.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,10 +2435,14 @@ bool Compiler::fgNormalizeEHCase2()
24352435
fgAddCheapPred(newTryStart, predBlock);
24362436
fgRemoveCheapPred(insertBeforeBlk, predBlock);
24372437

2438-
// Now change the branch. If it was a BBJ_NONE fall-through to the top block, this will
2439-
// do nothing. Since cheap preds contains dups (for switch duplicates), we will call
2438+
// Now change pred branches.
2439+
//
2440+
// Since cheap preds contains dups (for switch duplicates), we will call
24402441
// this once per dup.
2441-
fgReplaceJumpTarget(predBlock, newTryStart, insertBeforeBlk);
2442+
if (predBlock->bbJumpKind != BBJ_NONE)
2443+
{
2444+
fgReplaceJumpTarget(predBlock, newTryStart, insertBeforeBlk);
2445+
}
24422446

24432447
// Need to adjust ref counts here since we're retargeting edges.
24442448
newTryStart->bbRefs++;

src/coreclr/jit/redundantbranchopts.cpp

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,33 +1553,15 @@ bool Compiler::optJumpThreadCore(JumpThreadInfo& jti)
15531553
" implies predicate true; we can safely redirect flow to be " FMT_BB " -> " FMT_BB "\n",
15541554
predBlock->bbNum, jti.m_block->bbNum, predBlock->bbNum, jti.m_trueTarget->bbNum);
15551555

1556-
if (predBlock->bbJumpKind == BBJ_SWITCH)
1557-
{
1558-
fgReplaceSwitchJumpTarget(predBlock, jti.m_trueTarget, jti.m_block);
1559-
}
1560-
else
1561-
{
1562-
fgRemoveRefPred(jti.m_block, predBlock);
1563-
fgReplaceJumpTarget(predBlock, jti.m_trueTarget, jti.m_block);
1564-
fgAddRefPred(jti.m_trueTarget, predBlock);
1565-
}
1556+
fgReplaceJumpTarget(predBlock, jti.m_trueTarget, jti.m_block);
15661557
}
15671558
else
15681559
{
15691560
JITDUMP("Jump flow from pred " FMT_BB " -> " FMT_BB
15701561
" implies predicate false; we can safely redirect flow to be " FMT_BB " -> " FMT_BB "\n",
15711562
predBlock->bbNum, jti.m_block->bbNum, predBlock->bbNum, jti.m_falseTarget->bbNum);
15721563

1573-
if (predBlock->bbJumpKind == BBJ_SWITCH)
1574-
{
1575-
fgReplaceSwitchJumpTarget(predBlock, jti.m_falseTarget, jti.m_block);
1576-
}
1577-
else
1578-
{
1579-
fgRemoveRefPred(jti.m_block, predBlock);
1580-
fgReplaceJumpTarget(predBlock, jti.m_falseTarget, jti.m_block);
1581-
fgAddRefPred(jti.m_falseTarget, predBlock);
1582-
}
1564+
fgReplaceJumpTarget(predBlock, jti.m_falseTarget, jti.m_block);
15831565
}
15841566
}
15851567

0 commit comments

Comments
 (0)