Skip to content
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: Reuse LSRA's block sequence for initial layout during block reordering #110921

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5226,7 +5226,6 @@ class Compiler
BasicBlock* fgOSREntryBB = nullptr; // For OSR, the logical entry point (~ patchpoint)
BasicBlock* fgFirstFuncletBB = nullptr; // First block of outlined funclets (to allow block insertion before the funclets)
BasicBlockList* fgReturnBlocks = nullptr; // list of BBJ_RETURN blocks
unsigned fgEdgeCount = 0; // # of control flow edges between the BBs
unsigned fgBBcount = 0; // # of BBs in the method (in the linked list that starts with fgFirstBB)
#ifdef DEBUG
jitstd::vector<BasicBlock*>* fgBBOrder = nullptr; // ordered vector of BBs
Expand All @@ -5237,8 +5236,6 @@ class Compiler
bool fgMightHaveNaturalLoops = false;

unsigned fgBBNumMax = 0; // The max bbNum that has been assigned to basic blocks
unsigned fgDomBBcount = 0; // # of BBs for which we have dominator and reachability information
BasicBlock** fgBBReversePostorder; // Blocks in reverse postorder

FlowGraphDfsTree* m_dfsTree = nullptr;
// The next members are annotations on the flow graph used during the
Expand Down
4 changes: 1 addition & 3 deletions src/coreclr/jit/fgdiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,9 +993,7 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
{
fprintf(fgxFile, "\n </blocks>");

fprintf(fgxFile, "\n <edges");
fprintf(fgxFile, "\n edgeCount=\"%d\"", fgEdgeCount);
fprintf(fgxFile, ">");
fprintf(fgxFile, "\n <edges>");
}

if (fgPredsComputed)
Expand Down
40 changes: 24 additions & 16 deletions src/coreclr/jit/fgopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4687,27 +4687,35 @@ void Compiler::fgDoReversePostOrderLayout()
#endif // DEBUG

// Compute DFS of all blocks in the method, using profile data to determine the order successors are visited in.
// Then, identify any loops in the DFS tree so we can keep their bodies compact.
//
FlowGraphDfsTree* const dfsTree = fgComputeDfs</* useProfile */ true>();
FlowGraphNaturalLoops* const loops = FlowGraphNaturalLoops::Find(dfsTree);
BasicBlock** const rpoSequence = new (this, CMK_BasicBlock) BasicBlock*[dfsTree->GetPostOrderCount()];
unsigned index = dfsTree->GetPostOrderCount();
auto addToSequence = [rpoSequence, &index](BasicBlock* block) {
assert(index != 0);
rpoSequence[--index] = block;
};
FlowGraphDfsTree* const dfsTree = fgComputeDfs</* useProfile */ true>();

// If LSRA didn't create any new blocks, we can reuse its loop-aware RPO traversal,
// which is cached in Compiler::fgBBs.
// If the cache isn't available, we need to recompute the loop-aware RPO.
//
BasicBlock** rpoSequence = fgBBs;

fgVisitBlocksInLoopAwareRPO(dfsTree, loops, addToSequence);
if (rpoSequence == nullptr)
{
rpoSequence = new (this, CMK_BasicBlock) BasicBlock*[dfsTree->GetPostOrderCount()];
FlowGraphNaturalLoops* const loops = FlowGraphNaturalLoops::Find(dfsTree);
unsigned index = 0;
auto addToSequence = [rpoSequence, &index](BasicBlock* block) {
rpoSequence[index++] = block;
};

fgVisitBlocksInLoopAwareRPO(dfsTree, loops, addToSequence);
}

// Fast path: We don't have any EH regions, so just reorder the blocks
//
if (compHndBBtabCount == 0)
{
for (unsigned i = dfsTree->GetPostOrderCount() - 1; i != 0; i--)
for (unsigned i = 1; i < dfsTree->GetPostOrderCount(); i++)
{
BasicBlock* const block = rpoSequence[i];
BasicBlock* const blockToMove = rpoSequence[i - 1];
BasicBlock* const block = rpoSequence[i - 1];
BasicBlock* const blockToMove = rpoSequence[i];

if (!block->NextIs(blockToMove))
{
Expand Down Expand Up @@ -4756,10 +4764,10 @@ void Compiler::fgDoReversePostOrderLayout()

// Reorder blocks
//
for (unsigned i = dfsTree->GetPostOrderCount() - 1; i != 0; i--)
for (unsigned i = 1; i < dfsTree->GetPostOrderCount(); i++)
{
BasicBlock* const block = rpoSequence[i];
BasicBlock* const blockToMove = rpoSequence[i - 1];
BasicBlock* const block = rpoSequence[i - 1];
BasicBlock* const blockToMove = rpoSequence[i];

// Only reorder blocks within the same EH region -- we don't want to make them non-contiguous
//
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/jit/lsra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,18 @@ PhaseStatus LinearScan::doLinearScan()

compiler->compLSRADone = true;

// If edge resolution didn't create new blocks,
// cache the block sequence so it can be used as an initial layout during block reordering.
if (compiler->fgBBcount == bbSeqCount)
{
compiler->fgBBs = blockSequence;
}
else
{
assert(compiler->fgBBcount > bbSeqCount);
compiler->fgBBs = nullptr;
}

return PhaseStatus::MODIFIED_EVERYTHING;
}

Expand Down
Loading