Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove fgReplaceSwitchJumpTarget; increase usage of fgReplaceJumpTarget #97664

Merged
merged 4 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5861,15 +5861,13 @@ class Compiler

void fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSwitchBlock);

void fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget);

void fgChangeEhfBlock(BasicBlock* oldBlock, BasicBlock* newBlock);

void fgReplaceEhfSuccessor(BasicBlock* block, BasicBlock* oldSucc, BasicBlock* newSucc);

void fgRemoveEhfSuccessor(BasicBlock* block, BasicBlock* succ);

void fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget);
void fgReplaceJumpTarget(BasicBlock* block, BasicBlock* oldTarget, BasicBlock* newTarget);

void fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred);

Expand Down
185 changes: 25 additions & 160 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,81 +421,6 @@ void Compiler::fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSw
}
}

//------------------------------------------------------------------------
// fgReplaceSwitchJumpTarget: update BBJ_SWITCH block so that all control
// that previously flowed to oldTarget now flows to newTarget.
//
// Arguments:
// blockSwitch - block ending in a switch
// newTarget - new branch target
// oldTarget - old branch target
//
// Notes:
// Updates the jump table and the cached unique target set (if any).
//
void Compiler::fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget)
{
noway_assert(blockSwitch != nullptr);
noway_assert(newTarget != nullptr);
noway_assert(oldTarget != nullptr);
noway_assert(blockSwitch->KindIs(BBJ_SWITCH));
assert(fgPredsComputed);

// For the jump targets values that match oldTarget of our BBJ_SWITCH
// replace predecessor 'blockSwitch' with 'newTarget'

unsigned jumpCnt = blockSwitch->GetSwitchTargets()->bbsCount;
BasicBlock** jumpTab = blockSwitch->GetSwitchTargets()->bbsDstTab;

unsigned i = 0;

// Walk the switch's jump table looking for blocks to update the preds for
while (i < jumpCnt)
{
if (jumpTab[i] == oldTarget) // We will update when jumpTab[i] matches
{
// Remove the old edge [oldTarget from blockSwitch]
//
fgRemoveAllRefPreds(oldTarget, blockSwitch);

//
// Change the jumpTab entry to branch to the new location
//
jumpTab[i] = newTarget;

//
// Create the new edge [newTarget from blockSwitch]
//
FlowEdge* const newEdge = fgAddRefPred(newTarget, blockSwitch);

// Now set the correct value of newEdge's DupCount
// and replace any other jumps in jumpTab[] that go to oldTarget.
//
i++;
while (i < jumpCnt)
{
if (jumpTab[i] == oldTarget)
{
//
// We also must update this entry in the jumpTab
//
jumpTab[i] = newTarget;
newTarget->bbRefs++;
newEdge->incrementDupCount();
}
i++; // Check the next entry in jumpTab[]
}

// Maintain, if necessary, the set of unique targets of "block."
UpdateSwitchTableTarget(blockSwitch, oldTarget, newTarget);

return; // We have replaced the jumps to oldTarget with newTarget
}
i++; // Check the next entry in jumpTab[] for a match
}
noway_assert(!"Did not find oldTarget in jumpTab[]");
}

//------------------------------------------------------------------------
// fgChangeEhfBlock: We have a BBJ_EHFINALLYRET block at 'oldBlock' and we want to move this
// to 'newBlock'. All of the 'oldBlock' successors need to have their predecessor lists updated
Expand Down Expand Up @@ -536,8 +461,8 @@ void Compiler::fgChangeEhfBlock(BasicBlock* oldBlock, BasicBlock* newBlock)
//
// Arguments:
// block - BBJ_EHFINALLYRET block
// oldSucc - old successor
// newSucc - new successor
// oldSucc - old successor
//
void Compiler::fgReplaceEhfSuccessor(BasicBlock* block, BasicBlock* oldSucc, BasicBlock* newSucc)
{
Expand Down Expand Up @@ -670,7 +595,7 @@ void Compiler::fgRemoveEhfSuccessor(BasicBlock* block, BasicBlock* succ)
// 3. The predecessor lists are updated.
// 4. If any switch table entry was updated, the switch table "unique successor" cache is invalidated.
//
void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget)
void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* oldTarget, BasicBlock* newTarget)
{
assert(block != nullptr);
assert(fgPredsComputed);
Expand All @@ -683,49 +608,48 @@ void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, Bas
case BBJ_EHCATCHRET:
case BBJ_EHFILTERRET:
case BBJ_LEAVE: // This function can be called before import, so we still have BBJ_LEAVE

if (block->TargetIs(oldTarget))
{
block->SetTarget(newTarget);
fgRemoveRefPred(oldTarget, block);
fgAddRefPred(newTarget, block);
}
assert(block->TargetIs(oldTarget));
block->SetTarget(newTarget);
fgRemoveRefPred(oldTarget, block);
fgAddRefPred(newTarget, block);
break;

case BBJ_COND:
{
FlowEdge* oldEdge = fgRemoveRefPred(oldTarget, block);

if (block->TrueTargetIs(oldTarget))
{
if (block->FalseTargetIs(oldTarget))
{
// fgRemoveRefPred returns nullptr for BBJ_COND blocks with two flow edges to target
assert(oldEdge == nullptr);
fgRemoveConditionalJump(block);
assert(block->KindIs(BBJ_ALWAYS));
assert(block->TargetIs(oldTarget));
block->SetTarget(newTarget);
}
else
{
// fgRemoveRefPred should have removed the flow edge
assert(oldEdge != nullptr);
block->SetTrueTarget(newTarget);
}

// fgRemoveRefPred should have removed the flow edge
FlowEdge* oldEdge = fgRemoveRefPred(oldTarget, block);
assert(oldEdge != nullptr);

// TODO-NoFallThrough: Proliferate weight from oldEdge
// (we avoid doing so when updating the true target to reduce diffs for now, as a quirk)
// (as a quirk, we avoid doing so for the true target to reduce diffs for now)
fgAddRefPred(newTarget, block);
}
else
{
assert(block->FalseTargetIs(oldTarget));

// fgRemoveRefPred should have removed the flow edge
FlowEdge* oldEdge = fgRemoveRefPred(oldTarget, block);
assert(oldEdge != nullptr);
assert(block->FalseTargetIs(oldTarget));
block->SetFalseTarget(newTarget);
fgAddRefPred(newTarget, block, oldEdge);
}
break;
}

case BBJ_SWITCH:
{
Expand Down Expand Up @@ -5054,36 +4978,11 @@ BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ)
JITDUMP("Splitting edge from " FMT_BB " to " FMT_BB "; adding " FMT_BB "\n", curr->bbNum, succ->bbNum,
newBlock->bbNum);

if (curr->KindIs(BBJ_COND))
{
if (curr->TrueTargetIs(succ))
{
curr->SetTrueTarget(newBlock);
}
else
{
assert(curr->FalseTargetIs(succ));
curr->SetFalseTarget(newBlock);
}
// newBlock replaces succ as curr's successor.
fgReplaceJumpTarget(curr, succ, newBlock);

fgReplacePred(succ, curr, newBlock);
fgAddRefPred(newBlock, curr);
}
else if (curr->KindIs(BBJ_SWITCH))
{
// newBlock replaces 'succ' in the switch.
fgReplaceSwitchJumpTarget(curr, newBlock, succ);

// And 'succ' has 'newBlock' as a new predecessor.
fgAddRefPred(succ, newBlock);
}
else
{
assert(curr->KindIs(BBJ_ALWAYS));
fgReplacePred(succ, curr, newBlock);
curr->SetTarget(newBlock);
fgAddRefPred(newBlock, curr);
}
// And succ has newBlock as a new predecessor.
fgAddRefPred(succ, newBlock);

// This isn't accurate, but it is complex to compute a reasonable number so just assume that we take the
// branch 50% of the time.
Expand Down Expand Up @@ -5220,11 +5119,6 @@ BasicBlock* Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
BasicBlock* bPrev = block->Prev();
BasicBlock* bNext = block->Next();

// If we've cached any mappings from switch blocks to SwitchDesc's (which contain only the
// *unique* successors of the switch block), invalidate that cache, since an entry in one of
// the SwitchDescs might be removed.
InvalidateUniqueSwitchSuccMap();

noway_assert((block == fgFirstBB) || (bPrev && bPrev->NextIs(block)));
noway_assert(!block->HasFlag(BBF_DONT_REMOVE));

Expand Down Expand Up @@ -5343,62 +5237,33 @@ BasicBlock* Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
}

/* Update bbRefs and bbPreds.
* All blocks jumping to 'block' now jump to 'succBlock'.
* All blocks jumping to 'block' will jump to 'succBlock'.
* First, remove 'block' from the predecessor list of succBlock.
*/

fgRemoveRefPred(succBlock, block);

for (FlowEdge* const pred : block->PredEdges())
for (BasicBlock* const predBlock : block->PredBlocks())
{
BasicBlock* predBlock = pred->getSourceBlock();

/* If predBlock is a new predecessor, then add it to succBlock's
predecessor's list. */
if (!predBlock->KindIs(BBJ_SWITCH))
{
// Even if the pred is not a switch, we could have a conditional branch
// to the fallthrough, so duplicate there could be preds
for (unsigned i = 0; i < pred->getDupCount(); i++)
{
fgAddRefPred(succBlock, predBlock);
}
}

/* change all jumps to the removed block */
/* change all jumps/refs to the removed block */
switch (predBlock->GetKind())
{
default:
noway_assert(!"Unexpected bbKind in fgRemoveBlock()");
break;

case BBJ_COND:
if (predBlock->TrueTargetIs(block))
{
predBlock->SetTrueTarget(succBlock);
}

if (predBlock->FalseTargetIs(block))
{
predBlock->SetFalseTarget(succBlock);
}
break;

case BBJ_CALLFINALLY:
case BBJ_CALLFINALLYRET:
case BBJ_ALWAYS:
case BBJ_EHCATCHRET:
noway_assert(predBlock->TargetIs(block));
predBlock->SetTarget(succBlock);
case BBJ_SWITCH:
fgReplaceJumpTarget(predBlock, block, succBlock);
break;

case BBJ_EHFINALLYRET:
fgReplaceEhfSuccessor(predBlock, block, succBlock);
break;

case BBJ_SWITCH:
fgReplaceSwitchJumpTarget(predBlock, succBlock, block);
break;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/fgehopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2041,7 +2041,7 @@ PhaseStatus Compiler::fgTailMergeThrows()
case BBJ_SWITCH:
{
JITDUMP("*** " FMT_BB " now branching to " FMT_BB "\n", predBlock->bbNum, canonicalBlock->bbNum);
fgReplaceSwitchJumpTarget(predBlock, canonicalBlock, nonCanonicalBlock);
fgReplaceJumpTarget(predBlock, nonCanonicalBlock, canonicalBlock);
updated = true;
}
break;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/fgopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext)
while (preds.Height() > 0)
{
BasicBlock* const predBlock = preds.Pop();
fgReplaceJumpTarget(predBlock, block, bNext);
fgReplaceJumpTarget(predBlock, bNext, block);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/fgprofile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ void BlockCountInstrumentor::RelocateProbes()

// Redirect any jumps
//
m_comp->fgReplaceJumpTarget(pred, intermediary, block);
m_comp->fgReplaceJumpTarget(pred, block, intermediary);
}
}
}
Expand Down Expand Up @@ -1689,7 +1689,7 @@ void EfficientEdgeCountInstrumentor::RelocateProbes()
while (criticalPreds.Height() > 0)
{
BasicBlock* const pred = criticalPreds.Pop();
m_comp->fgReplaceJumpTarget(pred, intermediary, block);
m_comp->fgReplaceJumpTarget(pred, block, intermediary);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/jiteh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2254,7 +2254,7 @@ bool Compiler::fgNormalizeEHCase2()

// Change pred branches.
//
fgReplaceJumpTarget(predBlock, newTryStart, insertBeforeBlk);
fgReplaceJumpTarget(predBlock, insertBeforeBlk, newTryStart);

JITDUMP("Redirect " FMT_BB " target from " FMT_BB " to " FMT_BB ".\n", predBlock->bbNum,
insertBeforeBlk->bbNum, newTryStart->bbNum);
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1724,7 +1724,7 @@ void Compiler::optRedirectPrevUnrollIteration(FlowGraphNaturalLoop* loop, BasicB
JITDUMP("Redirecting " FMT_BB " -> " FMT_BB " to " FMT_BB " -> " FMT_BB "\n", entering->bbNum,
loop->GetHeader()->bbNum, entering->bbNum, target->bbNum);
assert(!entering->KindIs(BBJ_COND)); // Ensured by canonicalization
fgReplaceJumpTarget(entering, target, loop->GetHeader());
fgReplaceJumpTarget(entering, loop->GetHeader(), target);
}
}
}
Expand Down Expand Up @@ -3081,7 +3081,7 @@ bool Compiler::optCreatePreheader(FlowGraphNaturalLoop* loop)
JITDUMP("Entry edge " FMT_BB " -> " FMT_BB " becomes " FMT_BB " -> " FMT_BB "\n", enterBlock->bbNum,
header->bbNum, enterBlock->bbNum, preheader->bbNum);

fgReplaceJumpTarget(enterBlock, preheader, header);
fgReplaceJumpTarget(enterBlock, header, preheader);
}

optSetPreheaderWeight(loop, preheader);
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/redundantbranchopts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1771,15 +1771,15 @@ bool Compiler::optJumpThreadCore(JumpThreadInfo& jti)
" implies predicate true; we can safely redirect flow to be " FMT_BB " -> " FMT_BB "\n",
predBlock->bbNum, jti.m_block->bbNum, predBlock->bbNum, jti.m_trueTarget->bbNum);

fgReplaceJumpTarget(predBlock, jti.m_trueTarget, jti.m_block);
fgReplaceJumpTarget(predBlock, jti.m_block, jti.m_trueTarget);
}
else
{
JITDUMP("Jump flow from pred " FMT_BB " -> " FMT_BB
" implies predicate false; we can safely redirect flow to be " FMT_BB " -> " FMT_BB "\n",
predBlock->bbNum, jti.m_block->bbNum, predBlock->bbNum, jti.m_falseTarget->bbNum);

fgReplaceJumpTarget(predBlock, jti.m_falseTarget, jti.m_block);
fgReplaceJumpTarget(predBlock, jti.m_block, jti.m_falseTarget);
}
}

Expand Down
Loading