Skip to content

Commit 2ccf715

Browse files
JIT: Enable reusing profile-aware DFS trees between phases (#112198)
Revival of #112105. Add a switch to FlowGraphDfsTree that indicates if its traversal used edge likelihoods to determine the order in which successors were visited. This switch can then be used by debug checks that verify the DFS's correctness to check both types of trees. This functionality means we can frequently reuse the DFS tree annotations computed by LSRA throughout block layout.
1 parent 53a3e33 commit 2ccf715

File tree

5 files changed

+48
-18
lines changed

5 files changed

+48
-18
lines changed

src/coreclr/jit/compiler.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1938,12 +1938,16 @@ class FlowGraphDfsTree
19381938
// Whether the DFS that produced the tree found any backedges.
19391939
bool m_hasCycle;
19401940

1941+
// Whether the DFS that produced the tree used edge likelihoods to influence successor visitation order.
1942+
bool m_profileAware;
1943+
19411944
public:
1942-
FlowGraphDfsTree(Compiler* comp, BasicBlock** postOrder, unsigned postOrderCount, bool hasCycle)
1945+
FlowGraphDfsTree(Compiler* comp, BasicBlock** postOrder, unsigned postOrderCount, bool hasCycle, bool profileAware)
19431946
: m_comp(comp)
19441947
, m_postOrder(postOrder)
19451948
, m_postOrderCount(postOrderCount)
19461949
, m_hasCycle(hasCycle)
1950+
, m_profileAware(profileAware)
19471951
{
19481952
}
19491953

@@ -1978,6 +1982,11 @@ class FlowGraphDfsTree
19781982
return m_hasCycle;
19791983
}
19801984

1985+
bool IsProfileAware() const
1986+
{
1987+
return m_profileAware;
1988+
}
1989+
19811990
#ifdef DEBUG
19821991
void Dump() const;
19831992
#endif // DEBUG

src/coreclr/jit/fgdiagnostic.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4742,15 +4742,30 @@ void Compiler::fgDebugCheckFlowGraphAnnotations()
47424742
return;
47434743
}
47444744

4745-
unsigned count = fgRunDfs(
4746-
[](BasicBlock* block, unsigned preorderNum) {
4745+
auto visitPreorder = [](BasicBlock* block, unsigned preorderNum) {
47474746
assert(block->bbPreorderNum == preorderNum);
4748-
},
4749-
[=](BasicBlock* block, unsigned postorderNum) {
4747+
};
4748+
4749+
auto visitPostorder = [=](BasicBlock* block, unsigned postorderNum) {
47504750
assert(block->bbPostorderNum == postorderNum);
47514751
assert(m_dfsTree->GetPostOrder(postorderNum) == block);
4752-
},
4753-
[](BasicBlock* block, BasicBlock* succ) {});
4752+
};
4753+
4754+
auto visitEdge = [](BasicBlock* block, BasicBlock* succ) {};
4755+
4756+
unsigned count;
4757+
if (m_dfsTree->IsProfileAware())
4758+
{
4759+
count = fgRunDfs<decltype(visitPreorder), decltype(visitPostorder), decltype(visitEdge), true>(visitPreorder,
4760+
visitPostorder,
4761+
visitEdge);
4762+
}
4763+
else
4764+
{
4765+
count = fgRunDfs<decltype(visitPreorder), decltype(visitPostorder), decltype(visitEdge), false>(visitPreorder,
4766+
visitPostorder,
4767+
visitEdge);
4768+
}
47544769

47554770
assert(m_dfsTree->GetPostOrderCount() == count);
47564771

src/coreclr/jit/fgopt.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4663,10 +4663,6 @@ void Compiler::fgDoReversePostOrderLayout()
46634663
}
46644664
#endif // DEBUG
46654665

4666-
// Compute DFS of all blocks in the method, using profile data to determine the order successors are visited in.
4667-
//
4668-
m_dfsTree = fgComputeDfs</* useProfile */ true>();
4669-
46704666
// If LSRA didn't create any new blocks, we can reuse its loop-aware RPO traversal,
46714667
// which is cached in Compiler::fgBBs.
46724668
// If the cache isn't available, we need to recompute the loop-aware RPO.
@@ -4675,15 +4671,21 @@ void Compiler::fgDoReversePostOrderLayout()
46754671

46764672
if (rpoSequence == nullptr)
46774673
{
4678-
rpoSequence = new (this, CMK_BasicBlock) BasicBlock*[m_dfsTree->GetPostOrderCount()];
4674+
assert(m_dfsTree == nullptr);
4675+
m_dfsTree = fgComputeDfs</* useProfile */ true>();
46794676
FlowGraphNaturalLoops* const loops = FlowGraphNaturalLoops::Find(m_dfsTree);
4680-
unsigned index = 0;
4681-
auto addToSequence = [rpoSequence, &index](BasicBlock* block) {
4677+
rpoSequence = new (this, CMK_BasicBlock) BasicBlock*[m_dfsTree->GetPostOrderCount()];
4678+
unsigned index = 0;
4679+
auto addToSequence = [rpoSequence, &index](BasicBlock* block) {
46824680
rpoSequence[index++] = block;
46834681
};
46844682

46854683
fgVisitBlocksInLoopAwareRPO(m_dfsTree, loops, addToSequence);
46864684
}
4685+
else
4686+
{
4687+
assert(m_dfsTree != nullptr);
4688+
}
46874689

46884690
// Fast path: We don't have any EH regions, so just reorder the blocks
46894691
//

src/coreclr/jit/flowgraph.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4353,7 +4353,7 @@ FlowGraphDfsTree* Compiler::fgComputeDfs()
43534353
fgRunDfs<decltype(visitPreorder), decltype(visitPostorder), decltype(visitEdge), useProfile>(visitPreorder,
43544354
visitPostorder,
43554355
visitEdge);
4356-
return new (this, CMK_DepthFirstSearch) FlowGraphDfsTree(this, postOrder, numBlocks, hasCycle);
4356+
return new (this, CMK_DepthFirstSearch) FlowGraphDfsTree(this, postOrder, numBlocks, hasCycle, useProfile);
43574357
}
43584358

43594359
// Add explicit instantiations.

src/coreclr/jit/lsra.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -947,13 +947,16 @@ void LinearScan::setBlockSequence()
947947
bbVisitedSet = BitVecOps::MakeEmpty(traits);
948948

949949
assert((blockSequence == nullptr) && (bbSeqCount == 0));
950-
FlowGraphDfsTree* const dfsTree = compiler->fgComputeDfs</* useProfile */ true>();
950+
951+
compiler->m_dfsTree = compiler->fgComputeDfs</* useProfile */ true>();
952+
FlowGraphDfsTree* const dfsTree = compiler->m_dfsTree;
951953
blockSequence = new (compiler, CMK_LSRA) BasicBlock*[compiler->fgBBcount];
952954

953955
if (compiler->opts.OptimizationEnabled() && dfsTree->HasCycle())
954956
{
955-
// Ensure loop bodies are compact in the visitation order
956-
FlowGraphNaturalLoops* const loops = FlowGraphNaturalLoops::Find(dfsTree);
957+
// Ensure loop bodies are compact in the visitation order.
958+
compiler->m_loops = FlowGraphNaturalLoops::Find(dfsTree);
959+
FlowGraphNaturalLoops* const loops = compiler->m_loops;
957960
unsigned index = 0;
958961

959962
auto addToSequence = [this, &index](BasicBlock* block) {
@@ -1319,6 +1322,7 @@ PhaseStatus LinearScan::doLinearScan()
13191322
{
13201323
assert(compiler->fgBBcount > bbSeqCount);
13211324
compiler->fgBBs = nullptr;
1325+
compiler->fgInvalidateDfsTree();
13221326
}
13231327

13241328
return PhaseStatus::MODIFIED_EVERYTHING;

0 commit comments

Comments
 (0)