Skip to content

Commit 5a9362f

Browse files
authored
JIT: Add an "init BB" invariant (#110404)
This adds an invariant that there always exists an "init BB" throughout the JIT's phases. The init BB has the following properties: - It is only executed once, so it does not have any predecessors - It is not inside a try region, hence it dominates all other blocks in the function There are no further requirements on the BB. The init BB does not have to be `BBJ_ALWAYS` (unlike the old "scratch BB" concept). This is mainly because it philosophically does not make sense to insert IR at the end of the init BB, since earlier phases can have inserted arbitrary IR in them.
1 parent c95667c commit 5a9362f

File tree

16 files changed

+283
-363
lines changed

16 files changed

+283
-363
lines changed

src/coreclr/jit/codegenlinear.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,6 @@ void CodeGen::genCodeForBBlist()
156156

157157
genMarkLabelsForCodegen();
158158

159-
assert(!compiler->fgFirstBBScratch ||
160-
compiler->fgFirstBB == compiler->fgFirstBBScratch); // compiler->fgFirstBBScratch
161-
// has to be first.
162-
163159
/* Initialize structures used in the block list iteration */
164160
genInitialize();
165161

@@ -367,9 +363,9 @@ void CodeGen::genCodeForBBlist()
367363
siBeginBlock(block);
368364

369365
// BBF_INTERNAL blocks don't correspond to any single IL instruction.
370-
if (compiler->opts.compDbgInfo && block->HasFlag(BBF_INTERNAL) &&
371-
!compiler->fgBBisScratch(block)) // If the block is the distinguished first scratch block, then no need to
372-
// emit a NO_MAPPING entry, immediately after the prolog.
366+
// Add a NoMapping entry unless this is right after the prolog where it
367+
// is unnecessary.
368+
if (compiler->opts.compDbgInfo && block->HasFlag(BBF_INTERNAL) && !block->IsFirst())
373369
{
374370
genIPmappingAdd(IPmappingDscKind::NoMapping, DebugInfo(), true);
375371
}
@@ -388,17 +384,17 @@ void CodeGen::genCodeForBBlist()
388384

389385
#ifdef SWIFT_SUPPORT
390386
// Reassemble Swift struct parameters on the local stack frame in the
391-
// scratch BB right after the prolog. There can be arbitrary amounts of
387+
// init BB right after the prolog. There can be arbitrary amounts of
392388
// codegen related to doing this, so it cannot be done in the prolog.
393-
if (compiler->fgBBisScratch(block) && compiler->lvaHasAnySwiftStackParamToReassemble())
389+
if (block->IsFirst() && compiler->lvaHasAnySwiftStackParamToReassemble())
394390
{
395391
genHomeSwiftStructParameters(/* handleStack */ true);
396392
}
397393
#endif
398394

399-
// Emit poisoning into scratch BB that comes right after prolog.
395+
// Emit poisoning into the init BB that comes right after prolog.
400396
// We cannot emit this code in the prolog as it might make the prolog too large.
401-
if (compiler->compShouldPoisonFrame() && compiler->fgBBisScratch(block))
397+
if (compiler->compShouldPoisonFrame() && block->IsFirst())
402398
{
403399
genPoisonFrame(newLiveRegSet);
404400
}

src/coreclr/jit/compiler.cpp

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3743,20 +3743,6 @@ void Compiler::compInitDebuggingInfo()
37433743
compInitScopeLists();
37443744
}
37453745

3746-
if (opts.compDbgCode && (info.compVarScopesCount > 0))
3747-
{
3748-
/* Create a new empty basic block. fgExtendDbgLifetimes() may add
3749-
initialization of variables which are in scope right from the
3750-
start of the (real) first BB (and therefore artificially marked
3751-
as alive) into this block.
3752-
*/
3753-
3754-
fgEnsureFirstBBisScratch();
3755-
3756-
fgNewStmtAtEnd(fgFirstBB, gtNewNothingNode());
3757-
3758-
JITDUMP("Debuggable code - Add new %s to perform initialization of variables\n", fgFirstBB->dspToString());
3759-
}
37603746
/*-------------------------------------------------------------------------
37613747
*
37623748
* Read the stmt-offsets table and the line-number table
@@ -4526,6 +4512,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
45264512
activePhaseChecks |= PhaseChecks::CHECK_PROFILE;
45274513
DoPhase(this, PHASE_INCPROFILE, &Compiler::fgIncorporateProfileData);
45284514

4515+
activePhaseChecks |= PhaseChecks::CHECK_FG_INIT_BLOCK;
4516+
DoPhase(this, PHASE_CANONICALIZE_ENTRY, &Compiler::fgCanonicalizeFirstBB);
4517+
45294518
// If we are doing OSR, update flow to initially reach the appropriate IL offset.
45304519
//
45314520
if (opts.IsOSR())
@@ -4694,10 +4683,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
46944683

46954684
if (opts.OptimizationEnabled())
46964685
{
4697-
// Canonicalize entry to have unique entry BB to put IR in for the upcoming phases
4698-
//
4699-
DoPhase(this, PHASE_CANONICALIZE_ENTRY, &Compiler::fgCanonicalizeFirstBB);
4700-
47014686
// Build post-order and remove dead blocks
47024687
//
47034688
DoPhase(this, PHASE_DFS_BLOCKS2, &Compiler::fgDfsBlocksAndRemove);
@@ -4792,10 +4777,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
47924777
return fgHeadTailMerge(false);
47934778
});
47944779

4795-
// Canonicalize entry to give a unique dominator tree root
4796-
//
4797-
DoPhase(this, PHASE_CANONICALIZE_ENTRY, &Compiler::fgCanonicalizeFirstBB);
4798-
47994780
// Compute DFS tree and remove all unreachable blocks.
48004781
//
48014782
DoPhase(this, PHASE_DFS_BLOCKS3, &Compiler::fgDfsBlocksAndRemove);
@@ -5027,12 +5008,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
50275008

50285009
assert(opts.optRepeat);
50295010

5030-
// We may have optimized away the canonical entry BB that SSA
5031-
// depends on above, so if we are going for another iteration then
5032-
// make sure we still have a canonical entry.
5033-
//
5034-
DoPhase(this, PHASE_CANONICALIZE_ENTRY, &Compiler::fgCanonicalizeFirstBB);
5035-
50365011
ResetOptAnnotations();
50375012
RecomputeFlowGraphAnnotations();
50385013

src/coreclr/jit/compiler.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,7 @@ enum class PhaseChecks : unsigned int
15421542
CHECK_LIKELIHOODS = 1 << 5, // profile data likelihood integrity
15431543
CHECK_PROFILE = 1 << 6, // profile data full integrity
15441544
CHECK_LINKED_LOCALS = 1 << 7, // check linked list of locals
1545+
CHECK_FG_INIT_BLOCK = 1 << 8, // flow graph has an init block
15451546
};
15461547

15471548
inline constexpr PhaseChecks operator ~(PhaseChecks a)
@@ -5197,8 +5198,6 @@ class Compiler
51975198
BasicBlock* fgEntryBB = nullptr; // For OSR, the original method's entry point
51985199
BasicBlock* fgOSREntryBB = nullptr; // For OSR, the logical entry point (~ patchpoint)
51995200
BasicBlock* fgFirstFuncletBB = nullptr; // First block of outlined funclets (to allow block insertion before the funclets)
5200-
BasicBlock* fgFirstBBScratch = nullptr; // Block inserted for initialization stuff. Is nullptr if no such block has been
5201-
// created.
52025201
BasicBlockList* fgReturnBlocks = nullptr; // list of BBJ_RETURN blocks
52035202
unsigned fgEdgeCount = 0; // # of control flow edges between the BBs
52045203
unsigned fgBBcount = 0; // # of BBs in the method (in the linked list that starts with fgFirstBB)
@@ -5246,10 +5245,6 @@ class Compiler
52465245
return getAllocator(cmk).allocate<T>(fgBBNumMax + 1);
52475246
}
52485247

5249-
bool fgEnsureFirstBBisScratch();
5250-
bool fgFirstBBisScratch();
5251-
bool fgBBisScratch(BasicBlock* block);
5252-
52535248
void fgExtendEHRegionBefore(BasicBlock* block);
52545249
void fgExtendEHRegionAfter(BasicBlock* block);
52555250

@@ -5439,6 +5434,7 @@ class Compiler
54395434
};
54405435

54415436
PhaseStatus fgMorphBlocks();
5437+
BasicBlock* fgGetFirstILBlock();
54425438
void fgMorphBlock(BasicBlock* block, MorphUnreachableInfo* unreachableInfo = nullptr);
54435439
void fgMorphStmts(BasicBlock* block);
54445440

@@ -6158,6 +6154,7 @@ class Compiler
61586154
bool fgCheckRemoveStmt(BasicBlock* block, Statement* stmt);
61596155

61606156
PhaseStatus fgCanonicalizeFirstBB();
6157+
void fgCreateNewInitBB();
61616158

61626159
void fgSetEHRegionForNewPreheaderOrExit(BasicBlock* preheader);
61636160

@@ -6179,6 +6176,8 @@ class Compiler
61796176

61806177
bool fgCanCompactBlock(BasicBlock* block);
61816178

6179+
bool fgCanCompactInitBlock();
6180+
61826181
void fgCompactBlock(BasicBlock* block);
61836182

61846183
BasicBlock* fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst);
@@ -6355,6 +6354,7 @@ class Compiler
63556354
void fgDebugCheckBBNumIncreasing();
63566355
void fgDebugCheckBBlist(bool checkBBNum = false, bool checkBBRefs = true);
63576356
void fgDebugCheckBlockLinks();
6357+
void fgDebugCheckInitBB();
63586358
void fgDebugCheckLinks(bool morphTrees = false);
63596359
void fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees);
63606360
void fgDebugCheckNodeLinks(BasicBlock* block, Statement* stmt);

0 commit comments

Comments
 (0)