Skip to content

Commit cccda30

Browse files
committed
JIT: morph blocks in RPO
When optimizing, process blocks in RPO. Disallow creation of new blocks and new flow edges (the latter with certain preapproved exceptions). Morph does not yet take advantage of the RPO to enable more optimization. Contributes to dotnet#93246.
1 parent a7b0249 commit cccda30

File tree

6 files changed

+75
-11
lines changed

6 files changed

+75
-11
lines changed

src/coreclr/jit/block.h

+1
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ enum BasicBlockFlags : unsigned __int64
440440
BBF_TAILCALL_SUCCESSOR = MAKE_BBFLAG(40), // BB has pred that has potential tail call
441441
BBF_RECURSIVE_TAILCALL = MAKE_BBFLAG(41), // Block has recursive tailcall that may turn into a loop
442442
BBF_NO_CSE_IN = MAKE_BBFLAG(42), // Block should kill off any incoming CSE
443+
BBF_CAN_ADD_PRED = MAKE_BBFLAG(43), // Ok to add pred edge to this block, even when "safe" edge creation disabled
443444

444445
// The following are sets of flags.
445446

src/coreclr/jit/compiler.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -3215,10 +3215,11 @@ class Compiler
32153215
//=========================================================================
32163216
// BasicBlock functions
32173217
#ifdef DEBUG
3218-
// This is a debug flag we will use to assert when creating block during codegen
3219-
// as this interferes with procedure splitting. If you know what you're doing, set
3220-
// it to true before creating the block. (DEBUG only)
3218+
// When false, assert when creating a new basic block.
32213219
bool fgSafeBasicBlockCreation;
3220+
3221+
// When false, assert when creating a new flow edge
3222+
bool fgSafeFlowEdgeCreation;
32223223
#endif
32233224

32243225
/*

src/coreclr/jit/fgbasic.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ void Compiler::fgInit()
8484

8585
#ifdef DEBUG
8686
fgSafeBasicBlockCreation = true;
87+
fgSafeFlowEdgeCreation = true;
8788
#endif // DEBUG
8889

8990
fgLocalVarLivenessDone = false;

src/coreclr/jit/fgflow.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ FlowEdge* Compiler::fgAddRefPred(BasicBlock* block, BasicBlock* blockPred, FlowE
162162
}
163163
else
164164
{
165+
// Create a new edge
166+
//
167+
// We may be disallowing edge creation, except for edges targeting special blocks.
168+
//
169+
assert(fgSafeFlowEdgeCreation || ((block->bbFlags & BBF_CAN_ADD_PRED) != 0));
165170

166171
#if MEASURE_BLOCK_SIZE
167172
genFlowNodeCnt += 1;

src/coreclr/jit/flowgraph.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2228,7 +2228,7 @@ class MergedReturns
22282228
// Add 'return' expression to the return block
22292229
comp->fgNewStmtAtEnd(newReturnBB, returnExpr);
22302230
// Flag that this 'return' was generated by return merging so that subsequent
2231-
// return block morhping will know to leave it alone.
2231+
// return block merging will know to leave it alone.
22322232
returnExpr->gtFlags |= GTF_RET_MERGED;
22332233

22342234
#ifdef DEBUG

src/coreclr/jit/morph.cpp

+63-7
Original file line numberDiff line numberDiff line change
@@ -7472,7 +7472,6 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa
74727472
//------------------------------------------------------------------------------
74737473
// fgAssignRecursiveCallArgToCallerParam : Assign argument to a recursive call to the corresponding caller parameter.
74747474
//
7475-
//
74767475
// Arguments:
74777476
// arg - argument to assign
74787477
// late - whether to use early or late arg
@@ -13892,13 +13891,70 @@ PhaseStatus Compiler::fgMorphBlocks()
1389213891

1389313892
// Morph all blocks.
1389413893
//
13895-
// Note morph can add blocks downstream from the current block,
13896-
// and alter (but not null out) the current block's bbNext;
13897-
// this iterator ensures they all get visited.
13898-
//
13899-
for (BasicBlock* block : Blocks())
13894+
if (!optLocalAssertionProp)
1390013895
{
13901-
fgMorphBlock(block);
13896+
// If we aren't optimizing, we just morph in normal bbNext order.
13897+
//
13898+
// Note morph can add blocks downstream from the current block,
13899+
// and alter (but not null out) the current block's bbNext;
13900+
// this iterator ensures they all get visited.
13901+
//
13902+
for (BasicBlock* block : Blocks())
13903+
{
13904+
fgMorphBlock(block);
13905+
}
13906+
}
13907+
else
13908+
{
13909+
// We are optimizing. Process in RPO.
13910+
//
13911+
fgRenumberBlocks();
13912+
EnsureBasicBlockEpoch();
13913+
fgComputeEnterBlocksSet();
13914+
fgDfsReversePostorder();
13915+
13916+
// Disallow general creation of new blocks or edges as it
13917+
// would invalidate RPO.
13918+
//
13919+
// Removal of edges, or altering dup counts, is OK.
13920+
//
13921+
INDEBUG(fgSafeBasicBlockCreation = false;);
13922+
INDEBUG(fgSafeFlowEdgeCreation = false;);
13923+
13924+
// Allow edge creation to genReturnBB (target of return merging)
13925+
// and the scratch block successor (target for tail call to loop).
13926+
// This will also disallow dataflow into these blocks.
13927+
//
13928+
if (genReturnBB != nullptr)
13929+
{
13930+
genReturnBB->bbFlags |= BBF_CAN_ADD_PRED;
13931+
}
13932+
if (fgFirstBBisScratch())
13933+
{
13934+
fgFirstBB->Next()->bbFlags |= BBF_CAN_ADD_PRED;
13935+
}
13936+
13937+
unsigned const bbNumMax = fgBBNumMax;
13938+
for (unsigned i = 1; i <= bbNumMax; i++)
13939+
{
13940+
BasicBlock* const block = fgBBReversePostorder[i];
13941+
fgMorphBlock(block);
13942+
}
13943+
13944+
// Re-enable block and edge creation, and revoke
13945+
// special treatment of genReturnBB and the "first" bb
13946+
//
13947+
INDEBUG(fgSafeBasicBlockCreation = true;);
13948+
INDEBUG(fgSafeFlowEdgeCreation = true;);
13949+
13950+
if (genReturnBB != nullptr)
13951+
{
13952+
genReturnBB->bbFlags &= ~BBF_CAN_ADD_PRED;
13953+
}
13954+
if (fgFirstBBisScratch())
13955+
{
13956+
fgFirstBB->Next()->bbFlags &= ~BBF_CAN_ADD_PRED;
13957+
}
1390213958
}
1390313959

1390413960
// Under OSR, we no longer need to specially protect the original method entry

0 commit comments

Comments
 (0)