Skip to content

Commit 3d995ec

Browse files
Reduce differences between successor iterators (#93445)
* Reduce differences between successor iterators The NumSucc/GetSucc/Succs iterators have two variants. It is hard to understand the distinction. The goal of this change is to reduce the differences, so the only difference is the SWITCH case (iterating either all successors or only unique successors). So: 1. BBJ_EHFILTERRET: always return the single successor, which is the first block of the filter handler. 2. BBJ_EHFINALLYRET: Move to standard successor iterator * Review comments
1 parent 82e6c60 commit 3d995ec

File tree

4 files changed

+53
-27
lines changed

4 files changed

+53
-27
lines changed

src/coreclr/jit/block.cpp

+22-2
Original file line numberDiff line numberDiff line change
@@ -1081,14 +1081,13 @@ unsigned BasicBlock::NumSucc() const
10811081
{
10821082
case BBJ_THROW:
10831083
case BBJ_RETURN:
1084-
case BBJ_EHFINALLYRET:
10851084
case BBJ_EHFAULTRET:
1086-
case BBJ_EHFILTERRET:
10871085
return 0;
10881086

10891087
case BBJ_CALLFINALLY:
10901088
case BBJ_ALWAYS:
10911089
case BBJ_EHCATCHRET:
1090+
case BBJ_EHFILTERRET:
10921091
case BBJ_LEAVE:
10931092
case BBJ_NONE:
10941093
return 1;
@@ -1103,6 +1102,23 @@ unsigned BasicBlock::NumSucc() const
11031102
return 2;
11041103
}
11051104

1105+
case BBJ_EHFINALLYRET:
1106+
// We may call this method before we realize we have invalid IL. Tolerate.
1107+
//
1108+
if (!hasHndIndex())
1109+
{
1110+
return 0;
1111+
}
1112+
1113+
// We may call this before we've computed the BBJ_EHFINALLYRET successors in the importer. Tolerate.
1114+
//
1115+
if (bbJumpEhf == nullptr)
1116+
{
1117+
return 0;
1118+
}
1119+
1120+
return bbJumpEhf->bbeCount;
1121+
11061122
case BBJ_SWITCH:
11071123
return bbJumpSwt->bbsCount;
11081124

@@ -1128,6 +1144,7 @@ BasicBlock* BasicBlock::GetSucc(unsigned i) const
11281144
case BBJ_CALLFINALLY:
11291145
case BBJ_ALWAYS:
11301146
case BBJ_EHCATCHRET:
1147+
case BBJ_EHFILTERRET:
11311148
case BBJ_LEAVE:
11321149
return bbJumpDest;
11331150

@@ -1146,6 +1163,9 @@ BasicBlock* BasicBlock::GetSucc(unsigned i) const
11461163
return bbJumpDest;
11471164
}
11481165

1166+
case BBJ_EHFINALLYRET:
1167+
return bbJumpEhf->bbeSuccs[i];
1168+
11491169
case BBJ_SWITCH:
11501170
return bbJumpSwt->bbsDstTab[i];
11511171

src/coreclr/jit/block.h

+18-11
Original file line numberDiff line numberDiff line change
@@ -887,15 +887,7 @@ struct BasicBlock : private LIR::Range
887887
// GetSucc() without a Compiler*.
888888
//
889889
// The behavior of NumSucc()/GetSucc() is different when passed a Compiler* for blocks that end in:
890-
// (1) BBJ_EHFINALLYRET (a return from a finally block)
891-
// (2) BBJ_EHFILTERRET (a return from EH filter block)
892-
// (3) BBJ_SWITCH
893-
//
894-
// For BBJ_EHFINALLYRET, if no Compiler* is passed, then the block is considered to have no
895-
// successor. If Compiler* is passed, we use the actual successors.
896-
//
897-
// Similarly, BBJ_EHFILTERRET blocks are assumed to have no successors if Compiler* is not passed; if
898-
// Compiler* is passed, NumSucc/GetSucc yields the first block of the try block's handler.
890+
// (1) BBJ_SWITCH
899891
//
900892
// For BBJ_SWITCH, if Compiler* is not passed, then all switch successors are returned. If Compiler*
901893
// is passed, then only unique switch successors are returned; the duplicate successors are omitted.
@@ -1751,9 +1743,7 @@ inline BasicBlock::BBSuccList::BBSuccList(const BasicBlock* block)
17511743
{
17521744
case BBJ_THROW:
17531745
case BBJ_RETURN:
1754-
case BBJ_EHFINALLYRET:
17551746
case BBJ_EHFAULTRET:
1756-
case BBJ_EHFILTERRET:
17571747
// We don't need m_succs.
17581748
m_begin = nullptr;
17591749
m_end = nullptr;
@@ -1762,6 +1752,7 @@ inline BasicBlock::BBSuccList::BBSuccList(const BasicBlock* block)
17621752
case BBJ_CALLFINALLY:
17631753
case BBJ_ALWAYS:
17641754
case BBJ_EHCATCHRET:
1755+
case BBJ_EHFILTERRET:
17651756
case BBJ_LEAVE:
17661757
m_succs[0] = block->GetJumpDest();
17671758
m_begin = &m_succs[0];
@@ -1791,6 +1782,22 @@ inline BasicBlock::BBSuccList::BBSuccList(const BasicBlock* block)
17911782
}
17921783
break;
17931784

1785+
case BBJ_EHFINALLYRET:
1786+
// We don't use the m_succs in-line data; use the existing successor table in the block.
1787+
// We must tolerate iterating successors early in the system, before EH_FINALLYRET successors have
1788+
// been computed.
1789+
if (block->GetJumpEhf() == nullptr)
1790+
{
1791+
m_begin = nullptr;
1792+
m_end = nullptr;
1793+
}
1794+
else
1795+
{
1796+
m_begin = block->GetJumpEhf()->bbeSuccs;
1797+
m_end = block->GetJumpEhf()->bbeSuccs + block->GetJumpEhf()->bbeCount;
1798+
}
1799+
break;
1800+
17941801
case BBJ_SWITCH:
17951802
// We don't use the m_succs in-line data for switches; use the existing jump table in the block.
17961803
assert(block->GetJumpSwt() != nullptr);

src/coreclr/jit/compiler.hpp

+2-10
Original file line numberDiff line numberDiff line change
@@ -616,12 +616,6 @@ BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func)
616616
{
617617
switch (bbJumpKind)
618618
{
619-
case BBJ_EHFILTERRET:
620-
RETURN_ON_ABORT(func(bbJumpDest));
621-
RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func));
622-
RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bbJumpDest, func));
623-
break;
624-
625619
case BBJ_EHFINALLYRET:
626620
for (unsigned i = 0; i < bbJumpEhf->bbeCount; i++)
627621
{
@@ -639,6 +633,7 @@ BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func)
639633

640634
case BBJ_CALLFINALLY:
641635
case BBJ_EHCATCHRET:
636+
case BBJ_EHFILTERRET:
642637
case BBJ_LEAVE:
643638
RETURN_ON_ABORT(func(bbJumpDest));
644639
RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func));
@@ -728,10 +723,6 @@ BasicBlockVisit BasicBlock::VisitRegularSuccs(Compiler* comp, TFunc func)
728723
{
729724
switch (bbJumpKind)
730725
{
731-
case BBJ_EHFILTERRET:
732-
RETURN_ON_ABORT(func(bbJumpDest));
733-
break;
734-
735726
case BBJ_EHFINALLYRET:
736727
for (unsigned i = 0; i < bbJumpEhf->bbeCount; i++)
737728
{
@@ -741,6 +732,7 @@ BasicBlockVisit BasicBlock::VisitRegularSuccs(Compiler* comp, TFunc func)
741732

742733
case BBJ_CALLFINALLY:
743734
case BBJ_EHCATCHRET:
735+
case BBJ_EHFILTERRET:
744736
case BBJ_LEAVE:
745737
case BBJ_ALWAYS:
746738
RETURN_ON_ABORT(func(bbJumpDest));

src/coreclr/jit/importer.cpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -11471,7 +11471,9 @@ void Compiler::impImportBlock(BasicBlock* block)
1147111471
// This will re-import all the successors of block (as well as each of their predecessors)
1147211472
impReimportSpillClique(block);
1147311473

11474-
// For blocks that haven't been imported yet, we still need to mark them as pending import.
11474+
// We don't expect to see BBJ_EHFILTERRET here.
11475+
assert(!block->KindIs(BBJ_EHFILTERRET));
11476+
1147511477
for (BasicBlock* const succ : block->Succs())
1147611478
{
1147711479
if ((succ->bbFlags & BBF_IMPORTED) == 0)
@@ -11484,10 +11486,15 @@ void Compiler::impImportBlock(BasicBlock* block)
1148411486
{
1148511487
// otherwise just import the successors of block
1148611488

11487-
/* Does this block jump to any other blocks? */
11488-
for (BasicBlock* const succ : block->Succs())
11489+
// Does this block jump to any other blocks?
11490+
// Filter successor from BBJ_EHFILTERRET have already been handled above in the call
11491+
// to impVerifyEHBlock().
11492+
if (!block->KindIs(BBJ_EHFILTERRET))
1148911493
{
11490-
impImportBlockPending(succ);
11494+
for (BasicBlock* const succ : block->Succs())
11495+
{
11496+
impImportBlockPending(succ);
11497+
}
1149111498
}
1149211499
}
1149311500
}

0 commit comments

Comments
 (0)