Skip to content

Commit 622e701

Browse files
committed
Generalize loop pre-header creation and loop hoisting
A loop pre-header is a block that flows directly (and only) to the loop entry block. The loop pre-header is the only non-loop predecessor of the entry block. Loop invariant code can be hoisted to the loop pre-header where it is guaranteed to be executed just once (per loop entry). Currently, a loop pre-header has a number of restrictions: - it is only created for a "do-while" (top entry) loop, not for a mid-loop entry. - it isn't created if the current loop head and the loop entry block are in different EH try regions Additionally, partially due those restrictions, loop hoisting has restrictions: - it requires a "do-while" (top entry) loop - it requires the existing `head` block to dominate the loop entry block - it requires the existing `head` block to be in the same EH region as the entry block - it won't hoist if the `entry` block is the first block of a handler This change removes all these restrictions. Previously, even if we did create a pre-header, the definition of a pre-header was a little weaker: an entry predecessor could be a non-loop block and also not the pre-header, if the predecessor was dominated by the entry block. This is more complicated to reason about, so I change the pre-header creation to force entry block non-loop predecessors to branch to the pre-header instead. This case only rarely occurs, when we have what looks like an outer loop back edge but the natural loop recognition package doesn't recognize it as an outer loop. I added a "stress mode" to always create a loop pre-header immediately after loop recognition. This is disabled currently because loop cloning doesn't respect the special status and invariants of a pre-header, and so inserts all the cloning conditions and copied blocks after the pre-header, triggering new loop structure asserts. This should be improved in the future. A lot more checking of the loop table and loop annotations on blocks has been added. This revealed a number of problems with loop unrolling leaving things in a bad state for downstream phases. Loop unrolling has been updated to fix this, in particular, the loop table is rebuilt if it is detected that we unroll a loop that contains nested loops, since there will now be multiple copies of those nested loops. This is the first case where we might rebuild the loop table, so it lays the groundwork for potentially rebuilding the loop table in other cases, such as after loop cloning where we don't add the "slow path" loops to the table. There is some code refactoring to simplify the "find loops" code as well. Some change details: - `optSetBlockWeights` is elevated to a "phase" that runs prior to loop recognition. - LoopFlags is simplified: - LPFLG_DO_WHILE is removed; call `lpIsTopEntry` instead - LPFLG_ONE_EXIT is removed; check `lpExitCnt == 1` instead - LPFLG_HOISTABLE is removed (there are no restrictions anymore) - LPFLG_CONST is removed: check `lpFlags & (LPFLG_CONST_INIT | LPFLG_CONST_LIMIT) == (LPFLG_CONST_INIT | LPFLG_CONST_LIMIT)` instead (only used in one place - bool lpContainsCall is removed and replaced by LPFLG_CONTAINS_CALL - Added a `lpInitBlock` field to the loop table. For constant and variable initialization loops, code assumed that these expressions existed in the `head` block. This isn't true anymore if we insert a pre-header block. So, capture the block where these actually exist when we determine that they do exist, and explicitly use this block pointer where needed. - Added `fgComputeReturnBlocks()` to extract this code out of `fgComputeReachability` into a function - Added `optFindAndScaleGeneralLoopBlocks()` to extract this out of loop recognition to its own function. - Added `optResetLoopInfo()` to reset the loop table and block annotations related to loops - Added `fgDebugCheckBBNumIncreasing()` to allow asserting that the bbNum order of blocks is increasing. This should be used in phases that depend on this order to do bbNum comparisons. - Add a lot more loop table validation in `fgDebugCheckLoopTable()`
1 parent 62d04ca commit 622e701

File tree

12 files changed

+1061
-434
lines changed

12 files changed

+1061
-434
lines changed

src/coreclr/jit/block.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ enum BasicBlockFlags : unsigned __int64
559559

560560
// Flags that relate blocks to loop structure.
561561

562-
BBF_LOOP_FLAGS = BBF_LOOP_PREHEADER | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1,
562+
BBF_LOOP_FLAGS = BBF_LOOP_PREHEADER | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1 | BBF_LOOP_ALIGN,
563563

564564
// Flags to update when two blocks are compacted
565565

@@ -1001,6 +1001,16 @@ struct BasicBlock : private LIR::Range
10011001
bbHndIndex = from->bbHndIndex;
10021002
}
10031003

1004+
void copyTryIndex(const BasicBlock* from)
1005+
{
1006+
bbTryIndex = from->bbTryIndex;
1007+
}
1008+
1009+
void copyHndIndex(const BasicBlock* from)
1010+
{
1011+
bbHndIndex = from->bbHndIndex;
1012+
}
1013+
10041014
static bool sameTryRegion(const BasicBlock* blk1, const BasicBlock* blk2)
10051015
{
10061016
return blk1->bbTryIndex == blk2->bbTryIndex;

src/coreclr/jit/compiler.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4898,10 +4898,14 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
48984898
//
48994899
DoPhase(this, PHASE_COMPUTE_REACHABILITY, &Compiler::fgComputeReachability);
49004900

4901+
// Scale block weights and mark run rarely blocks.
4902+
//
4903+
DoPhase(this, PHASE_SET_BLOCK_WEIGHTS, &Compiler::optSetBlockWeights);
4904+
49014905
// Discover and classify natural loops (e.g. mark iterative loops as such). Also marks loop blocks
49024906
// and sets bbWeight to the loop nesting levels.
49034907
//
4904-
DoPhase(this, PHASE_FIND_LOOPS, &Compiler::optFindLoops);
4908+
DoPhase(this, PHASE_FIND_LOOPS, &Compiler::optFindLoopsPhase);
49054909

49064910
// Clone loops with optimization opportunities, and choose one based on dynamic condition evaluation.
49074911
//
@@ -5444,20 +5448,16 @@ void Compiler::ResetOptAnnotations()
54445448
// The intent of this method is to update loop structure annotations, and those
54455449
// they depend on; these annotations may have become stale during optimization,
54465450
// and need to be up-to-date before running another iteration of optimizations.
5447-
5451+
//
54485452
void Compiler::RecomputeLoopInfo()
54495453
{
54505454
assert(opts.optRepeat);
54515455
assert(JitConfig.JitOptRepeatCount() > 0);
54525456
// Recompute reachability sets, dominators, and loops.
5453-
optLoopCount = 0;
5457+
optResetLoopInfo();
54545458
fgDomsComputed = false;
5455-
for (BasicBlock* const block : Blocks())
5456-
{
5457-
block->bbFlags &= ~BBF_LOOP_FLAGS;
5458-
block->bbNatLoopNum = BasicBlock::NOT_IN_LOOP;
5459-
}
54605459
fgComputeReachability();
5460+
optSetBlockWeights();
54615461
// Rebuild the loop tree annotations themselves
54625462
optFindLoops();
54635463
}

src/coreclr/jit/compiler.h

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,15 +2468,15 @@ enum LoopFlags : unsigned short
24682468
{
24692469
LPFLG_EMPTY = 0,
24702470

2471-
LPFLG_DO_WHILE = 0x0001, // it's a do-while loop (i.e ENTRY is at the TOP)
2472-
LPFLG_ONE_EXIT = 0x0002, // the loop has only one exit
2473-
LPFLG_ITER = 0x0004, // loop of form: for (i = icon or lclVar; test_condition(); i++)
2474-
LPFLG_HOISTABLE = 0x0008, // the loop is in a form that is suitable for hoisting expressions
2471+
// LPFLG_UNUSED = 0x0001,
2472+
// LPFLG_UNUSED = 0x0002,
2473+
LPFLG_ITER = 0x0004, // loop of form: for (i = icon or lclVar; test_condition(); i++)
2474+
// LPFLG_UNUSED = 0x0008,
24752475

2476-
LPFLG_CONST = 0x0010, // loop of form: for (i=icon;i<icon;i++){ ... } - constant loop
2477-
LPFLG_VAR_INIT = 0x0020, // iterator is initialized with a local var (var # found in lpVarInit)
2478-
LPFLG_CONST_INIT = 0x0040, // iterator is initialized with a constant (found in lpConstInit)
2479-
LPFLG_SIMD_LIMIT = 0x0080, // iterator is compared with vector element count (found in lpConstLimit)
2476+
LPFLG_CONTAINS_CALL = 0x0010, // If executing the loop body *may* execute a call
2477+
LPFLG_VAR_INIT = 0x0020, // iterator is initialized with a local var (var # found in lpVarInit)
2478+
LPFLG_CONST_INIT = 0x0040, // iterator is initialized with a constant (found in lpConstInit)
2479+
LPFLG_SIMD_LIMIT = 0x0080, // iterator is compared with vector element count (found in lpConstLimit)
24802480

24812481
LPFLG_VAR_LIMIT = 0x0100, // iterator is compared with a local var (var # found in lpVarLimit)
24822482
LPFLG_CONST_LIMIT = 0x0200, // iterator is compared with a constant (found in lpConstLimit)
@@ -5079,11 +5079,12 @@ class Compiler
50795079
unsigned fgMeasureIR();
50805080
#endif // FEATURE_JIT_METHOD_PERF
50815081

5082-
bool fgModified; // True if the flow graph has been modified recently
5083-
bool fgComputePredsDone; // Have we computed the bbPreds list
5084-
bool fgCheapPredsValid; // Is the bbCheapPreds list valid?
5085-
bool fgDomsComputed; // Have we computed the dominator sets?
5086-
bool fgOptimizedFinally; // Did we optimize any try-finallys?
5082+
bool fgModified; // True if the flow graph has been modified recently
5083+
bool fgComputePredsDone; // Have we computed the bbPreds list
5084+
bool fgCheapPredsValid; // Is the bbCheapPreds list valid?
5085+
bool fgDomsComputed; // Have we computed the dominator sets?
5086+
bool fgReturnBlocksComputed; // Have we computed the return blocks list?
5087+
bool fgOptimizedFinally; // Did we optimize any try-finallys?
50875088

50885089
bool fgHasSwitch; // any BBJ_SWITCH jumps?
50895090

@@ -5685,6 +5686,8 @@ class Compiler
56855686

56865687
void fgComputeReachabilitySets(); // Compute bbReach sets. (Also sets BBF_GC_SAFE_POINT flag on blocks.)
56875688

5689+
void fgComputeReturnBlocks(); // Initialize fgReturnBlocks to a list of BBJ_RETURN blocks.
5690+
56885691
void fgComputeEnterBlocksSet(); // Compute the set of entry blocks, 'fgEnterBlks'.
56895692

56905693
bool fgRemoveUnreachableBlocks(); // Remove blocks determined to be unreachable by the bbReach sets.
@@ -5712,9 +5715,12 @@ class Compiler
57125715
// && postOrder(A) >= postOrder(B) making the computation O(1).
57135716
void fgNumberDomTree(DomTreeNode* domTree);
57145717

5715-
// When the flow graph changes, we need to update the block numbers, predecessor lists, reachability sets, and
5716-
// dominators.
5717-
void fgUpdateChangedFlowGraph(const bool computePreds = true, const bool computeDoms = true);
5718+
// When the flow graph changes, we need to update the block numbers, predecessor lists, reachability sets,
5719+
// dominators, and possibly loops.
5720+
void fgUpdateChangedFlowGraph(const bool computePreds = true,
5721+
const bool computeDoms = true,
5722+
const bool computeReturnBlocks = false,
5723+
const bool computeLoops = false);
57185724

57195725
public:
57205726
// Compute the predecessors of the blocks in the control flow graph.
@@ -5820,6 +5826,8 @@ class Compiler
58205826

58215827
BasicBlock* fgFirstBlockOfHandler(BasicBlock* block);
58225828

5829+
bool fgIsFirstBlockOfFilterOrHandler(BasicBlock* block);
5830+
58235831
flowList* fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred);
58245832

58255833
flowList* fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, flowList*** ptrToPred);
@@ -6003,6 +6011,8 @@ class Compiler
60036011
static fgWalkPreFn fgStress64RsltMulCB;
60046012
void fgStress64RsltMul();
60056013
void fgDebugCheckUpdate();
6014+
6015+
void fgDebugCheckBBNumIncreasing();
60066016
void fgDebugCheckBBlist(bool checkBBNum = false, bool checkBBRefs = true);
60076017
void fgDebugCheckBlockLinks();
60086018
void fgDebugCheckLinks(bool morphTrees = false);
@@ -6018,6 +6028,8 @@ class Compiler
60186028
void fgDebugCheckProfileData();
60196029
bool fgDebugCheckIncomingProfileData(BasicBlock* block);
60206030
bool fgDebugCheckOutgoingProfileData(BasicBlock* block);
6031+
6032+
unsigned* fgBuildBlockNumMap();
60216033
#endif
60226034

60236035
static bool fgProfileWeightsEqual(weight_t weight1, weight_t weight2);
@@ -6604,8 +6616,7 @@ class Compiler
66046616
void optHoistLoopCode();
66056617

66066618
// To represent sets of VN's that have already been hoisted in outer loops.
6607-
typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, bool> VNToBoolMap;
6608-
typedef VNToBoolMap VNSet;
6619+
typedef JitHashTable<ValueNum, JitSmallPrimitiveKeyFuncs<ValueNum>, bool> VNSet;
66096620

66106621
struct LoopHoistContext
66116622
{
@@ -6616,9 +6627,10 @@ class Compiler
66166627
public:
66176628
// Value numbers of expressions that have been hoisted in parent loops in the loop nest.
66186629
VNSet m_hoistedInParentLoops;
6630+
66196631
// Value numbers of expressions that have been hoisted in the current (or most recent) loop in the nest.
66206632
// Previous decisions on loop-invariance of value numbers in the current loop.
6621-
VNToBoolMap m_curLoopVnInvariantCache;
6633+
VNSet m_curLoopVnInvariantCache;
66226634

66236635
VNSet* GetHoistedInCurLoop(Compiler* comp)
66246636
{
@@ -6661,15 +6673,15 @@ class Compiler
66616673
void optHoistLoopBlocks(unsigned loopNum, ArrayStack<BasicBlock*>* blocks, LoopHoistContext* hoistContext);
66626674

66636675
// Return true if the tree looks profitable to hoist out of loop 'lnum'.
6664-
bool optIsProfitableToHoistableTree(GenTree* tree, unsigned lnum);
6676+
bool optIsProfitableToHoistTree(GenTree* tree, unsigned lnum);
66656677

66666678
// Performs the hoisting 'tree' into the PreHeader for loop 'lnum'
66676679
void optHoistCandidate(GenTree* tree, BasicBlock* treeBb, unsigned lnum, LoopHoistContext* hoistCtxt);
66686680

66696681
// Returns true iff the ValueNum "vn" represents a value that is loop-invariant in "lnum".
66706682
// Constants and init values are always loop invariant.
66716683
// VNPhi's connect VN's to the SSA definition, so we can know if the SSA def occurs in the loop.
6672-
bool optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNToBoolMap* recordedVNs);
6684+
bool optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNSet* recordedVNs);
66736685

66746686
// If "blk" is the entry block of a natural loop, returns true and sets "*pLnum" to the index of the loop
66756687
// in the loop table.
@@ -6709,7 +6721,10 @@ class Compiler
67096721
public:
67106722
PhaseStatus optInvertLoops(); // Invert loops so they're entered at top and tested at bottom.
67116723
PhaseStatus optOptimizeLayout(); // Optimize the BasicBlock layout of the method
6712-
PhaseStatus optFindLoops(); // Finds loops and records them in the loop table
6724+
PhaseStatus optSetBlockWeights();
6725+
PhaseStatus optFindLoopsPhase(); // Finds loops and records them in the loop table
6726+
6727+
void optFindLoops();
67136728

67146729
PhaseStatus optCloneLoops();
67156730
void optCloneLoop(unsigned loopInd, LoopCloneContext* context);
@@ -6767,7 +6782,6 @@ class Compiler
67676782
bool lpLoopHasMemoryHavoc[MemoryKindCount]; // The loop contains an operation that we assume has arbitrary
67686783
// memory side effects. If this is set, the fields below
67696784
// may not be accurate (since they become irrelevant.)
6770-
bool lpContainsCall; // True if executing the loop body *may* execute a call
67716785

67726786
VARSET_TP lpVarInOut; // The set of variables that are IN or OUT during the execution of this loop
67736787
VARSET_TP lpVarUseDef; // The set of variables that are USE or DEF during the execution of this loop
@@ -6813,6 +6827,10 @@ class Compiler
68136827

68146828
var_types lpIterOperType() const; // For overflow instructions
68156829

6830+
// Set to the block where we found the initialization for LPFLG_CONST_INIT or LPFLG_VAR_INIT loops.
6831+
// Initially, this will be 'head', but 'head' might change if we insert a loop pre-header block.
6832+
BasicBlock* lpInitBlock;
6833+
68166834
union {
68176835
int lpConstInit; // initial constant value of iterator
68186836
// : Valid if LPFLG_CONST_INIT
@@ -6843,6 +6861,21 @@ class Compiler
68436861
// : Valid if LPFLG_ARRLEN_LIMIT
68446862
bool lpArrLenLimit(Compiler* comp, ArrIndex* index) const;
68456863

6864+
// Returns "true" iff this is a "top entry" loop.
6865+
bool lpIsTopEntry() const
6866+
{
6867+
if (lpHead->bbNext == lpEntry)
6868+
{
6869+
assert(lpHead->bbFallsThrough());
6870+
assert(lpTop == lpEntry);
6871+
return true;
6872+
}
6873+
else
6874+
{
6875+
return false;
6876+
}
6877+
}
6878+
68466879
// Returns "true" iff "*this" contains the blk.
68476880
bool lpContains(BasicBlock* blk) const
68486881
{
@@ -6895,6 +6928,24 @@ class Compiler
68956928
(lpHead->bbNum < lpTop->bbNum || lpHead->bbNum > lpBottom->bbNum);
68966929
}
68976930

6931+
#ifdef DEBUG
6932+
void lpValidatePreHeader()
6933+
{
6934+
// If this is called, we expect there to be a pre-header.
6935+
assert(lpFlags & LPFLG_HAS_PREHEAD);
6936+
6937+
// The pre-header must unconditionally enter the loop.
6938+
assert(lpHead->GetUniqueSucc() == lpEntry);
6939+
6940+
// The loop block must be marked as a pre-header.
6941+
assert(lpHead->bbFlags & BBF_LOOP_PREHEADER);
6942+
6943+
// The loop entry must have a single non-loop predecessor, which is the pre-header.
6944+
// We can't assume here that the bbNum are properly ordered, so we can't do a simple lpContained()
6945+
// check. So, we defer this check, which will be done by `fgDebugCheckLoopTable()`.
6946+
}
6947+
#endif // DEBUG
6948+
68986949
// LoopBlocks: convenience method for enabling range-based `for` iteration over all the
68996950
// blocks in a loop, e.g.:
69006951
// for (BasicBlock* const block : loop->LoopBlocks()) ...
@@ -6944,11 +6995,12 @@ class Compiler
69446995
void optCheckPreds();
69456996
#endif
69466997

6998+
void optResetLoopInfo();
6999+
void optFindAndScaleGeneralLoopBlocks();
7000+
69477001
// Determine if there are any potential loops, and set BBF_LOOP_HEAD on potential loop heads.
69487002
void optMarkLoopHeads();
69497003

6950-
void optSetBlockWeights();
6951-
69527004
void optScaleLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk);
69537005

69547006
void optUnmarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk);
@@ -6959,7 +7011,7 @@ class Compiler
69597011
unsigned optIsLoopIncrTree(GenTree* incr);
69607012
bool optCheckIterInLoopTest(unsigned loopInd, GenTree* test, BasicBlock* from, BasicBlock* to, unsigned iterVar);
69617013
bool optComputeIterInfo(GenTree* incr, BasicBlock* from, BasicBlock* to, unsigned* pIterVar);
6962-
bool optPopulateInitInfo(unsigned loopInd, GenTree* init, unsigned iterVar);
7014+
bool optPopulateInitInfo(unsigned loopInd, BasicBlock* initBlock, GenTree* init, unsigned iterVar);
69637015
bool optExtractInitTestIncr(
69647016
BasicBlock* head, BasicBlock* bottom, BasicBlock* exit, GenTree** ppInit, GenTree** ppTest, GenTree** ppIncr);
69657017

@@ -7010,15 +7062,13 @@ class Compiler
70107062
// The depth of the loop described by "lnum" (an index into the loop table.) (0 == top level)
70117063
unsigned optLoopDepth(unsigned lnum)
70127064
{
7013-
unsigned par = optLoopTable[lnum].lpParent;
7014-
if (par == BasicBlock::NOT_IN_LOOP)
7015-
{
7016-
return 0;
7017-
}
7018-
else
7065+
assert(lnum < optLoopCount);
7066+
unsigned depth = 0;
7067+
while ((lnum = optLoopTable[lnum].lpParent) != BasicBlock::NOT_IN_LOOP)
70197068
{
7020-
return 1 + optLoopDepth(par);
7069+
++depth;
70217070
}
7071+
return depth;
70227072
}
70237073

70247074
// Struct used in optInvertWhileLoop to count interesting constructs to boost the profitability score.

src/coreclr/jit/compphases.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ CompPhaseNameMacro(PHASE_POST_IMPORT, "Post-import",
3131
CompPhaseNameMacro(PHASE_IBCPREP, "Profile instrumentation prep", "IBCPREP", false, -1, false)
3232
CompPhaseNameMacro(PHASE_IBCINSTR, "Profile instrumentation", "IBCINSTR", false, -1, false)
3333
CompPhaseNameMacro(PHASE_INCPROFILE, "Profile incorporation", "INCPROF", false, -1, false)
34-
CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", "MOR-INIT" ,false, -1, false)
34+
CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", "MOR-INIT", false, -1, false)
3535
CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", "MOR-INL", false, -1, true)
3636
CompPhaseNameMacro(PHASE_MORPH_ADD_INTERNAL, "Morph - Add internal blocks", "MOR-ADD", false, -1, true)
3737
CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", "ALLOC-OBJ", false, -1, false)
@@ -48,14 +48,15 @@ CompPhaseNameMacro(PHASE_PROMOTE_STRUCTS, "Morph - Promote Structs",
4848
CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", "MOR-GLOB", false, -1, false)
4949
CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", "MOR-END", false, -1, true)
5050
CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", "GS-COOK", false, -1, false)
51-
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1, false)", "EDG-WGT", false, -1, false)
51+
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1, false)","EDG-WGT", false, -1, false)
5252
#if defined(FEATURE_EH_FUNCLETS)
5353
CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", "EH-FUNC", false, -1, false)
5454
#endif // FEATURE_EH_FUNCLETS
5555
CompPhaseNameMacro(PHASE_MERGE_THROWS, "Merge throw blocks", "MRGTHROW", false, -1, false)
5656
CompPhaseNameMacro(PHASE_INVERT_LOOPS, "Invert loops", "LOOP-INV", false, -1, false)
5757
CompPhaseNameMacro(PHASE_OPTIMIZE_LAYOUT, "Optimize layout", "LAYOUT", false, -1, false)
5858
CompPhaseNameMacro(PHASE_COMPUTE_REACHABILITY, "Compute blocks reachability", "BL_REACH", false, -1, false)
59+
CompPhaseNameMacro(PHASE_SET_BLOCK_WEIGHTS, "Set block weights", "BL-WEIGHTS", false, -1, false)
5960
CompPhaseNameMacro(PHASE_ZERO_INITS, "Redundant zero Inits", "ZERO-INIT", false, -1, false)
6061
CompPhaseNameMacro(PHASE_FIND_LOOPS, "Find loops", "LOOP-FND", false, -1, false)
6162
CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1, false)
@@ -82,7 +83,7 @@ CompPhaseNameMacro(PHASE_OPTIMIZE_BRANCHES, "Redundant branch opts",
8283
CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", "AST-PROP", false, -1, false)
8384
#endif
8485
CompPhaseNameMacro(PHASE_OPT_UPDATE_FLOW_GRAPH, "Update flow graph opt pass", "UPD-FG-O", false, -1, false)
85-
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)", "EDG-WGT2", false, -1, false)
86+
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)","EDG-WGT2", false, -1, false)
8687
CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls", "GC-POLLS", false, -1, true)
8788
CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1, true)
8889
CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1, false)

src/coreclr/jit/fgbasic.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ void Compiler::fgInit()
3535
fgCalledCount = BB_ZERO_WEIGHT;
3636

3737
/* We haven't yet computed the dominator sets */
38-
fgDomsComputed = false;
38+
fgDomsComputed = false;
39+
fgReturnBlocksComputed = false;
3940

4041
#ifdef DEBUG
4142
fgReachabilitySetsValid = false;
@@ -4701,7 +4702,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
47014702
{
47024703
loopAlignCandidates++;
47034704
succBlock->bbFlags |= BBF_LOOP_ALIGN;
4704-
JITDUMP("Propagating LOOP_ALIGN flag from " FMT_BB " to " FMT_BB " for loop# %d.\n", block->bbNum,
4705+
JITDUMP("Propagating LOOP_ALIGN flag from " FMT_BB " to " FMT_BB " for " FMT_LP "\n ", block->bbNum,
47054706
succBlock->bbNum, block->bbNatLoopNum);
47064707
}
47074708

0 commit comments

Comments
 (0)