-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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: Add loop-aware RPO, and use as LSRA's block sequence #108086
Changes from 3 commits
2d21d9e
9db278a
cff70ec
5732b31
79201ce
79026f1
8d4b0b5
ff4293d
12565ea
9141887
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4120,6 +4120,80 @@ FlowGraphDfsTree* Compiler::fgComputeDfs() | |
template FlowGraphDfsTree* Compiler::fgComputeDfs<false>(); | ||
template FlowGraphDfsTree* Compiler::fgComputeDfs<true>(); | ||
|
||
//------------------------------------------------------------------------ | ||
// fgComputeLoopAwareDfs: Compute a depth-first search tree for the flow graph | ||
// where in the RPO traversal, loop bodies are visited before loop successors. | ||
// | ||
// Returns: | ||
// The tree. | ||
// | ||
// Notes: | ||
// If the flow graph has loops, the DFS will be reordered such that loop bodies are compact. | ||
// This will invalidate BasicBlock::bbPreorderNum and BasicBlock::bbPostorderNum. | ||
// | ||
FlowGraphDfsTree* Compiler::fgComputeLoopAwareDfs() | ||
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. Is there anything gained from trying to represent this as an actual The "compute DFS tree" into "identify loops" into "now create another DFS tree" seems wasteful and conceptually a bit odd. 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.
Probably not.
That sounds sensible -- I'll try modeling this after |
||
{ | ||
if (m_dfsTree == nullptr) | ||
{ | ||
// Computing a profile-aware RPO means the DFS computation won't match the debug check's expectations, | ||
// so make sure these checks have already been disabled. | ||
assert(!hasFlag(activePhaseChecks, PhaseChecks::CHECK_FG_ANNOTATIONS)); | ||
m_dfsTree = fgComputeDfs</* useProfile */ true>(); | ||
} | ||
|
||
if (!m_dfsTree->HasCycle()) | ||
{ | ||
// No need to search for loops | ||
return m_dfsTree; | ||
} | ||
|
||
if (m_loops == nullptr) | ||
{ | ||
m_loops = FlowGraphNaturalLoops::Find(m_dfsTree); | ||
} | ||
|
||
m_blockToLoop = BlockToNaturalLoopMap::Build(m_loops); | ||
|
||
EnsureBasicBlockEpoch(); | ||
BlockSet visitedBlocks(BlockSetOps::MakeEmpty(this)); | ||
|
||
BasicBlock** loopAwarePostOrder = new (this, CMK_DepthFirstSearch) BasicBlock*[fgBBcount]; | ||
const unsigned numBlocks = m_dfsTree->GetPostOrderCount(); | ||
unsigned newIndex = numBlocks - 1; | ||
|
||
auto visitBlock = [this, loopAwarePostOrder, &visitedBlocks, &newIndex](BasicBlock* block) -> BasicBlockVisit { | ||
// If this block is in a loop, we will try to visit it more than once | ||
// (first when we visit its containing loop, and then later as we iterate | ||
// through the initial RPO). | ||
// Thus, we need to keep track of visited blocks. | ||
if (!BlockSetOps::IsMember(this, visitedBlocks, block->bbNum)) | ||
{ | ||
loopAwarePostOrder[newIndex--] = block; | ||
BlockSetOps::AddElemD(this, visitedBlocks, block->bbNum); | ||
} | ||
|
||
return BasicBlockVisit::Continue; | ||
}; | ||
|
||
for (unsigned i = numBlocks; i != 0; i--) | ||
{ | ||
BasicBlock* const block = m_dfsTree->GetPostOrder(i - 1); | ||
FlowGraphNaturalLoop* const loop = m_blockToLoop->GetLoop(block); | ||
|
||
// If this block is a loop header, visit the entire loop before moving on | ||
if ((loop != nullptr) && (block == loop->GetHeader())) | ||
{ | ||
loop->VisitLoopBlocksReversePostOrder(visitBlock); | ||
} | ||
else | ||
{ | ||
visitBlock(block); | ||
} | ||
} | ||
|
||
return new (this, CMK_DepthFirstSearch) FlowGraphDfsTree(this, loopAwarePostOrder, numBlocks, /* hasCycle */ true); | ||
} | ||
|
||
//------------------------------------------------------------------------ | ||
// fgInvalidateDfsTree: Invalidate computed DFS tree and dependent annotations | ||
// (like loops, dominators and SSA). | ||
|
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.
I don't think we have any dependencies on
bbPreorderNum
orbbPostorderNum
in the backend, but if we want to use loop-aware RPOs elsewhere in the JIT, I can work on making these members consistent.