-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JIT: Revise DFS RPO computation #82752
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -745,16 +745,23 @@ bool Compiler::fgRemoveDeadBlocks() | |
} | ||
|
||
//------------------------------------------------------------- | ||
// fgDfsInvPostOrder: Helper function for computing dominance information. | ||
// fgDfsReversePostorder: Depth first search to establish block | ||
// preorder and reverse postorder numbers, plus a reverse postorder for blocks. | ||
// | ||
// In order to be able to compute dominance, we need to first get a DFS reverse post order sort on the basic flow | ||
// graph for the dominance algorithm to operate correctly. The reason why we need the DFS sort is because we will | ||
// build the dominance sets using the partial order induced by the DFS sorting. With this precondition not | ||
// holding true, the algorithm doesn't work properly. | ||
// Notes: | ||
// Assumes caller has computed the fgEnterBlkSet. | ||
// | ||
// Assumes caller has allocated the fgBBReversePostorder array. | ||
// It will be filled in with blocks in reverse post order. | ||
// | ||
// This algorithm only pays attention to the actual blocks. It ignores any imaginary entry block. | ||
// | ||
void Compiler::fgDfsInvPostOrder() | ||
void Compiler::fgDfsReversePostorder() | ||
{ | ||
// NOTE: This algorithm only pays attention to the actual blocks. It ignores the imaginary entry block. | ||
// Make sure fgEnterBlks are still there in startNodes, even if they participate in a loop (i.e., there is | ||
// an incoming edge into the block). | ||
assert(fgEnterBlksSetValid); | ||
assert(fgBBReversePostorder != nullptr); | ||
|
||
// visited : Once we run the DFS post order sort recursive algorithm, we mark the nodes we visited to avoid | ||
// backtracking. | ||
|
@@ -765,28 +772,26 @@ void Compiler::fgDfsInvPostOrder() | |
// mark in this step. | ||
BlockSet_ValRet_T startNodes = fgDomFindStartNodes(); | ||
|
||
// Make sure fgEnterBlks are still there in startNodes, even if they participate in a loop (i.e., there is | ||
// an incoming edge into the block). | ||
assert(fgEnterBlksSetValid); | ||
|
||
BlockSetOps::UnionD(this, startNodes, fgEnterBlks); | ||
assert(BlockSetOps::IsMember(this, startNodes, fgFirstBB->bbNum)); | ||
|
||
// Call the flowgraph DFS traversal helper. | ||
unsigned postIndex = 1; | ||
unsigned preorderIndex = 1; | ||
unsigned postorderIndex = 1; | ||
for (BasicBlock* const block : Blocks()) | ||
{ | ||
// If the block has no predecessors, and we haven't already visited it (because it's in fgEnterBlks but also | ||
// reachable from the first block), go ahead and traverse starting from this block. | ||
if (BlockSetOps::IsMember(this, startNodes, block->bbNum) && | ||
!BlockSetOps::IsMember(this, visited, block->bbNum)) | ||
{ | ||
fgDfsInvPostOrderHelper(block, visited, &postIndex); | ||
fgDfsReversePostorderHelper(block, visited, preorderIndex, postorderIndex); | ||
} | ||
} | ||
|
||
// After the DFS reverse postorder is completed, we must have visited all the basic blocks. | ||
noway_assert(postIndex == fgBBcount + 1); | ||
noway_assert(preorderIndex == fgBBcount + 1); | ||
noway_assert(postorderIndex == fgBBcount + 1); | ||
noway_assert(fgBBNumMax == fgBBcount); | ||
|
||
#ifdef DEBUG | ||
|
@@ -795,7 +800,7 @@ void Compiler::fgDfsInvPostOrder() | |
printf("\nAfter doing a post order traversal of the BB graph, this is the ordering:\n"); | ||
for (unsigned i = 1; i <= fgBBNumMax; ++i) | ||
{ | ||
printf("%02u -> " FMT_BB "\n", i, fgBBInvPostOrder[i]->bbNum); | ||
printf("%02u -> " FMT_BB "\n", i, fgBBReversePostorder[i]->bbNum); | ||
} | ||
printf("\n"); | ||
} | ||
|
@@ -841,18 +846,22 @@ BlockSet_ValRet_T Compiler::fgDomFindStartNodes() | |
} | ||
|
||
//------------------------------------------------------------------------ | ||
// fgDfsInvPostOrderHelper: Helper to assign post-order numbers to blocks. | ||
// fgDfsReversevPostorderHelper: Helper to assign post-order numbers to blocks. | ||
// | ||
// Arguments: | ||
// block - The starting entry block | ||
// visited - The set of visited blocks | ||
// count - Pointer to the Dfs counter | ||
// preorderIndex - preorder visit counter | ||
// postorderIndex - postorder visit counter | ||
// | ||
// Notes: | ||
// Compute a non-recursive DFS traversal of the flow graph using an | ||
// evaluation stack to assign post-order numbers. | ||
// evaluation stack to assign pre and post-order numbers. | ||
// | ||
void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, unsigned* count) | ||
void Compiler::fgDfsReversePostorderHelper(BasicBlock* block, | ||
BlockSet& visited, | ||
unsigned& preorderIndex, | ||
unsigned& postorderIndex) | ||
{ | ||
// Assume we haven't visited this node yet (callers ensure this). | ||
assert(!BlockSetOps::IsMember(this, visited, block->bbNum)); | ||
|
@@ -881,6 +890,8 @@ void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, uns | |
// are guaranteed to only process it after all of its successors | ||
// pre and post actions are processed. | ||
stack.Push(DfsBlockEntry(DSS_Post, currentBlock)); | ||
currentBlock->bbPreorderNum = preorderIndex; | ||
preorderIndex++; | ||
|
||
for (BasicBlock* const succ : currentBlock->Succs(this)) | ||
{ | ||
|
@@ -903,12 +914,15 @@ void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, uns | |
// actions applied. | ||
|
||
assert(current.dfsStackState == DSS_Post); | ||
currentBlock->bbPostorderNum = postorderIndex; | ||
|
||
unsigned invCount = fgBBcount - *count + 1; | ||
assert(1 <= invCount && invCount <= fgBBNumMax); | ||
fgBBInvPostOrder[invCount] = currentBlock; | ||
currentBlock->bbPostOrderNum = invCount; | ||
++(*count); | ||
// Compute the index of this in the reverse postorder and | ||
// update the reverse postorder accordingly. | ||
// | ||
assert(postorderIndex <= fgBBcount); | ||
unsigned reversePostorderIndex = fgBBcount - postorderIndex + 1; | ||
fgBBReversePostorder[reversePostorderIndex] = currentBlock; | ||
postorderIndex++; | ||
} | ||
} | ||
} | ||
|
@@ -945,10 +959,10 @@ void Compiler::fgComputeDoms() | |
|
||
BlockSet processedBlks(BlockSetOps::MakeEmpty(this)); | ||
|
||
fgBBInvPostOrder = new (this, CMK_DominatorMemory) BasicBlock*[fgBBNumMax + 1]{}; | ||
fgBBReversePostorder = new (this, CMK_DominatorMemory) BasicBlock*[fgBBNumMax + 1]{}; | ||
|
||
fgDfsInvPostOrder(); | ||
noway_assert(fgBBInvPostOrder[0] == nullptr); | ||
fgDfsReversePostorder(); | ||
noway_assert(fgBBReversePostorder[0] == nullptr); | ||
|
||
// flRoot and bbRoot represent an imaginary unique entry point in the flow graph. | ||
// All the orphaned EH blocks and fgFirstBB will temporarily have its predecessors list | ||
|
@@ -961,12 +975,12 @@ void Compiler::fgComputeDoms() | |
bbRoot.bbPreds = nullptr; | ||
bbRoot.bbNum = 0; | ||
bbRoot.bbIDom = &bbRoot; | ||
bbRoot.bbPostOrderNum = 0; | ||
bbRoot.bbPostorderNum = fgBBNumMax + 1; | ||
bbRoot.bbFlags = BBF_EMPTY; | ||
|
||
FlowEdge flRoot(&bbRoot, nullptr); | ||
|
||
fgBBInvPostOrder[0] = &bbRoot; | ||
fgBBReversePostorder[0] = &bbRoot; | ||
|
||
// Mark both bbRoot and fgFirstBB processed | ||
BlockSetOps::AddElemD(this, processedBlks, 0); // bbRoot == block #0 | ||
|
@@ -1020,7 +1034,7 @@ void Compiler::fgComputeDoms() | |
{ | ||
FlowEdge* first = nullptr; | ||
BasicBlock* newidom = nullptr; | ||
block = fgBBInvPostOrder[i]; | ||
block = fgBBReversePostorder[i]; | ||
|
||
// If we have a block that has bbRoot as its bbIDom | ||
// it means we flag it as processed and as an entry block so | ||
|
@@ -1279,11 +1293,11 @@ BasicBlock* Compiler::fgIntersectDom(BasicBlock* a, BasicBlock* b) | |
BasicBlock* finger2 = b; | ||
while (finger1 != finger2) | ||
{ | ||
while (finger1->bbPostOrderNum > finger2->bbPostOrderNum) | ||
while (finger1->bbPostorderNum < finger2->bbPostorderNum) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note this method is now very similar to the SSA builder's |
||
{ | ||
finger1 = finger1->bbIDom; | ||
} | ||
while (finger2->bbPostOrderNum > finger1->bbPostOrderNum) | ||
while (finger2->bbPostorderNum < finger1->bbPostorderNum) | ||
{ | ||
finger2 = finger2->bbIDom; | ||
} | ||
|
@@ -6596,7 +6610,7 @@ void Compiler::fgCompDominatedByExceptionalEntryBlocks() | |
{ | ||
for (unsigned i = 1; i <= fgBBNumMax; ++i) | ||
{ | ||
BasicBlock* block = fgBBInvPostOrder[i]; | ||
BasicBlock* block = fgBBReversePostorder[i]; | ||
if (BlockSetOps::IsMember(this, fgEnterBlks, block->bbNum)) | ||
{ | ||
if (fgFirstBB != block) // skip the normal entry. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one subtle part I got wrong initially -- the fake "root" BB must now have a postnumber larger than the maximum possible postnumber instead of a reverse postnumber smaller than the the minimum possible reverse postnumber.