Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Forstall <brucefo@microsoft.com>2021-06-08 02:16:51 +0300
committerGitHub <noreply@github.com>2021-06-08 02:16:51 +0300
commit5788ea0d7a081dc2a821d5dd5a5a0dcdf1e017fb (patch)
treebad4a66b80ee48c858c1bbea57d0e822fa5159c4 /src/coreclr/jit/flowgraph.cpp
parentd173ccaf29e4d6aca217951e88abf29fa8f18461 (diff)
Add more iterators to JIT (#52515)
Add more iterators compatible with range-based `for` syntax for various data structures. These iterators all assume (and some check) that the underlying data structures determining the iteration are not changed during the iteration. For example, don't use these to iterate over the predecessor edges if you are changing the order or contents of the predecessor edge list. - BasicBlock: iterate over all blocks in the function, a subset starting not at the first block, or a specified range of blocks. Removed uses of the `foreach_block` macro. E.g.: ``` for (BasicBlock* const block : Blocks()) // all blocks in function for (BasicBlock* const block : BasicBlockSimpleList(fgFirstBB->bbNext)) // all blocks starting at fgFirstBB->bbNext for (BasicBlock* const testBlock : BasicBlockRangeList(firstNonLoopBlock, lastNonLoopBlock)) // all blocks in range (inclusive) ``` - block predecessors: iterate over all predecessor edges, or all predecessor blocks, e.g.: ``` for (flowList* const edge : block->PredEdges()) for (BasicBlock* const predBlock : block->PredBlocks()) ``` - block successors: iterate over all block successors using the `NumSucc()/GetSucc()`, or `NumSucc(Compiler*)/GetSucc(Compiler*)` pairs, e.g.: ``` for (BasicBlock* const succ : Succs()) for (BasicBlock* const succ : Succs(compiler)) ``` Note that there already exists the "AllSuccessorsIter" which iterates over block successors including possible EH successors, e.g.: ``` for (BasicBlock* succ : block->GetAllSuccs(m_pCompiler)) ``` - switch targets, (namely, the successors of `BBJ_SWITCH` blocks), e.g.: ``` for (BasicBlock* const bTarget : block->SwitchTargets()) ``` - loops blocks: iterate over all the blocks in a loop, e.g.: ``` for (BasicBlock* const blk : optLoopTable[loopInd].LoopBlocks()) ``` - Statements: added an iterator shortcut for the non-phi statements, e.g.: ``` for (Statement* const stmt : block->NonPhiStatements()) ``` Note that there already exists an iterator over all statements, e.g.: ``` for (Statement* const stmt : block->Statements()) ``` - EH clauses, e.g.: ``` for (EHblkDsc* const HBtab : EHClauses(this)) ``` - GenTree in linear order (but not LIR, which already has an iterator), namely, using the `gtNext` links, e.g.: ``` for (GenTree* const call : stmt->TreeList()) ``` This is a no-diff change.
Diffstat (limited to 'src/coreclr/jit/flowgraph.cpp')
-rw-r--r--src/coreclr/jit/flowgraph.cpp69
1 files changed, 23 insertions, 46 deletions
diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp
index a76cc93dc40..e7a281cdeca 100644
--- a/src/coreclr/jit/flowgraph.cpp
+++ b/src/coreclr/jit/flowgraph.cpp
@@ -25,11 +25,11 @@
static bool blockNeedsGCPoll(BasicBlock* block)
{
bool blockMayNeedGCPoll = false;
- for (Statement* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->GetNextStmt())
+ for (Statement* const stmt : block->NonPhiStatements())
{
if ((stmt->GetRootNode()->gtFlags & GTF_CALL) != 0)
{
- for (GenTree* tree = stmt->GetTreeList(); tree != nullptr; tree = tree->gtNext)
+ for (GenTree* const tree : stmt->TreeList())
{
if (tree->OperGet() == GT_CALL)
{
@@ -91,7 +91,7 @@ PhaseStatus Compiler::fgInsertGCPolls()
BasicBlock* block;
// Walk through the blocks and hunt for a block that needs a GC Poll
- for (block = fgFirstBB; block; block = block->bbNext)
+ for (block = fgFirstBB; block != nullptr; block = block->bbNext)
{
// When optimizations are enabled, we can't rely on BBF_HAS_SUPPRESSGC_CALL flag:
// the call could've been moved, e.g., hoisted from a loop, CSE'd, etc.
@@ -629,7 +629,7 @@ PhaseStatus Compiler::fgImport()
// Note this includes (to some extent) the impact of importer folded
// branches, provided the folded tree covered the entire block's IL.
unsigned importedILSize = 0;
- for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
if ((block->bbFlags & BBF_IMPORTED) != 0)
{
@@ -1395,8 +1395,6 @@ inline void Compiler::fgLoopCallTest(BasicBlock* srcBB, BasicBlock* dstBB)
void Compiler::fgLoopCallMark()
{
- BasicBlock* block;
-
/* If we've already marked all the block, bail */
if (fgLoopCallMarked)
@@ -1408,7 +1406,7 @@ void Compiler::fgLoopCallMark()
/* Walk the blocks, looking for backward edges */
- for (block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
switch (block->bbJumpKind)
{
@@ -1420,17 +1418,10 @@ void Compiler::fgLoopCallMark()
break;
case BBJ_SWITCH:
-
- unsigned jumpCnt;
- jumpCnt = block->bbJumpSwt->bbsCount;
- BasicBlock** jumpPtr;
- jumpPtr = block->bbJumpSwt->bbsDstTab;
-
- do
+ for (BasicBlock* const bTarget : block->SwitchTargets())
{
- fgLoopCallTest(block, *jumpPtr);
- } while (++jumpPtr, --jumpCnt);
-
+ fgLoopCallTest(block, bTarget);
+ }
break;
default:
@@ -1849,7 +1840,7 @@ void Compiler::fgAddSyncMethodEnterExit()
fgCreateMonitorTree(lvaMonAcquired, lvaCopyThis, faultBB, false /*exit*/);
// non-exceptional cases
- for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
if (block->bbJumpKind == BBJ_RETURN)
{
@@ -2091,7 +2082,7 @@ bool Compiler::fgMoreThanOneReturnBlock()
{
unsigned retCnt = 0;
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
if (block->bbJumpKind == BBJ_RETURN)
{
@@ -2920,10 +2911,10 @@ void Compiler::fgFindOperOrder()
/* Walk the basic blocks and for each statement determine
* the evaluation order, cost, FP levels, etc... */
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
compCurBB = block;
- for (Statement* stmt : block->Statements())
+ for (Statement* const stmt : block->Statements())
{
/* Recursively process the statement */
@@ -2953,7 +2944,7 @@ void Compiler::fgSimpleLowering()
unsigned outgoingArgSpaceSize = 0;
#endif // FEATURE_FIXED_OUT_ARGS
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
// Walk the statement trees in this basic block.
compCurBB = block; // Used in fgRngChkTarget.
@@ -3187,9 +3178,8 @@ void Compiler::fgInsertFuncletPrologBlock(BasicBlock* block)
// the handler go to the prolog. Edges coming from with the handler are back-edges, and
// go to the existing 'block'.
- for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
+ for (BasicBlock* const predBlock : block->PredBlocks())
{
- BasicBlock* predBlock = pred->getBlock();
if (!fgIsIntraHandlerPred(predBlock, block))
{
// It's a jump from outside the handler; add it to the newHead preds list and remove
@@ -3235,11 +3225,9 @@ void Compiler::fgCreateFuncletPrologBlocks()
noway_assert(!fgDomsComputed); // this function doesn't maintain the dom sets
assert(!fgFuncletsCreated);
- bool prologBlocksCreated = false;
- EHblkDsc* HBtabEnd;
- EHblkDsc* HBtab;
+ bool prologBlocksCreated = false;
- for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
+ for (EHblkDsc* const HBtab : EHClauses(this))
{
BasicBlock* head = HBtab->ebdHndBeg;
@@ -4295,7 +4283,7 @@ void Compiler::fgSetBlockOrder()
/* If we don't compute the doms, then we never mark blocks as loops. */
if (fgDomsComputed)
{
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
/* If this block is a loop header, mark it appropriately */
@@ -4310,11 +4298,7 @@ void Compiler::fgSetBlockOrder()
/* If we don't have the dominators, use an abbreviated test for fully interruptible. If there are
* any back edges, check the source and destination blocks to see if they're GC Safe. If not, then
* go fully interruptible. */
-
- /* XXX Mon 1/21/2008
- * Wouldn't it be nice to have a block iterator that can do this loop?
- */
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
// true if the edge is forward, or if it is a back edge and either the source and dest are GC safe.
#define EDGE_IS_GC_SAFE(src, dst) \
@@ -4329,17 +4313,10 @@ void Compiler::fgSetBlockOrder()
break;
case BBJ_SWITCH:
-
- unsigned jumpCnt;
- jumpCnt = block->bbJumpSwt->bbsCount;
- BasicBlock** jumpPtr;
- jumpPtr = block->bbJumpSwt->bbsDstTab;
-
- do
+ for (BasicBlock* const bTarget : block->SwitchTargets())
{
- partiallyInterruptible &= EDGE_IS_GC_SAFE(block, *jumpPtr);
- } while (++jumpPtr, --jumpCnt);
-
+ partiallyInterruptible &= EDGE_IS_GC_SAFE(block, bTarget);
+ }
break;
default:
@@ -4363,7 +4340,7 @@ void Compiler::fgSetBlockOrder()
}
}
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* const block : Blocks())
{
#if FEATURE_FASTTAILCALL
@@ -4482,7 +4459,7 @@ void Compiler::fgSetStmtSeq(Statement* stmt)
void Compiler::fgSetBlockOrder(BasicBlock* block)
{
- for (Statement* stmt : block->Statements())
+ for (Statement* const stmt : block->Statements())
{
fgSetStmtSeq(stmt);