Skip to content

Commit 8acb13b

Browse files
authored
JIT: Use post order computed by SSA in VN (#94623)
VN tries hard to dynamically compute a reverse post-order to visit the flow graph in. However, SSA has already computed such an order, so simply pass this along to VN instead. A few positive diffs are expected. As Andy has pointed out recently the "dynamic RPO" VN was doing does not necessarily result in an actual RPO, so using SSA's order is expected to be a better order than what VN ends up with today.
1 parent 4f3bae5 commit 8acb13b

File tree

5 files changed

+105
-262
lines changed

5 files changed

+105
-262
lines changed

src/coreclr/jit/compiler.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4493,6 +4493,8 @@ class Compiler
44934493
unsigned fgBBNumMax; // The max bbNum that has been assigned to basic blocks
44944494
unsigned fgDomBBcount; // # of BBs for which we have dominator and reachability information
44954495
BasicBlock** fgBBReversePostorder; // Blocks in reverse postorder
4496+
BasicBlock** fgSSAPostOrder; // Blocks in postorder, computed during SSA
4497+
unsigned fgSSAPostOrderCount; // Number of blocks in fgSSAPostOrder
44964498

44974499
// After the dominance tree is computed, we cache a DFS preorder number and DFS postorder number to compute
44984500
// dominance queries in O(1). fgDomTreePreOrder and fgDomTreePostOrder are arrays giving the block's preorder and
@@ -5057,7 +5059,7 @@ class Compiler
50575059

50585060
// The value numbers for this compilation.
50595061
ValueNumStore* vnStore;
5060-
struct ValueNumberState* vnVisitState;
5062+
class ValueNumberState* vnState;
50615063

50625064
public:
50635065
ValueNumStore* GetValueNumStore()
@@ -5723,7 +5725,7 @@ class Compiler
57235725

57245726
protected:
57255727
friend class SsaBuilder;
5726-
friend struct ValueNumberState;
5728+
friend class ValueNumberState;
57275729

57285730
//--------------------- Detect the basic blocks ---------------------------
57295731

src/coreclr/jit/fgopt.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,6 @@ bool Compiler::fgRemoveDeadBlocks()
769769
// Notes:
770770
// Each block's `bbPreorderNum` and `bbPostorderNum` is set.
771771
// The `fgBBReversePostorder` array is filled in with the `BasicBlock*` in reverse post-order.
772-
// This algorithm only pays attention to the actual blocks. It ignores any imaginary entry block.
773772
//
774773
// Unreachable blocks will have higher pre and post order numbers than reachable blocks.
775774
// Hence they will appear at lower indices in the fgBBReversePostorder array.

src/coreclr/jit/ssabuilder.cpp

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ PhaseStatus Compiler::fgSsaBuild()
6969
JitTestCheckSSA();
7070
#endif // DEBUG
7171

72+
fgSSAPostOrder = builder.GetPostOrder(&fgSSAPostOrderCount);
73+
7274
return PhaseStatus::MODIFIED_EVERYTHING;
7375
}
7476

@@ -144,7 +146,7 @@ SsaBuilder::SsaBuilder(Compiler* pCompiler)
144146
// Return Value:
145147
// The number of nodes visited while performing DFS on the graph.
146148
//
147-
int SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count)
149+
unsigned SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count)
148150
{
149151
Compiler* comp = m_pCompiler;
150152

@@ -179,7 +181,7 @@ int SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count)
179181
};
180182

181183
// Compute order.
182-
int postIndex = 0;
184+
unsigned postIndex = 0;
183185
BasicBlock* block = comp->fgFirstBB;
184186
BitVecOps::AddElemD(&m_visitedTraits, m_visited, block->bbNum);
185187

@@ -206,16 +208,13 @@ int SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count)
206208
// all successors have been visited
207209
blocks.Pop();
208210

209-
DBG_SSA_JITDUMP("[SsaBuilder::TopologicalSort] postOrder[%d] = " FMT_BB "\n", postIndex, block->bbNum);
211+
DBG_SSA_JITDUMP("[SsaBuilder::TopologicalSort] postOrder[%u] = " FMT_BB "\n", postIndex, block->bbNum);
210212
postOrder[postIndex] = block;
211213
block->bbPostorderNum = postIndex;
212214
postIndex++;
213215
}
214216
}
215217

216-
// In the absence of EH (because catch/finally have no preds), this should be valid.
217-
// assert(postIndex == (count - 1));
218-
219218
return postIndex;
220219
}
221220

@@ -1500,16 +1499,7 @@ void SsaBuilder::Build()
15001499

15011500
// Allocate the postOrder array for the graph.
15021501

1503-
BasicBlock** postOrder;
1504-
1505-
if (blockCount > DEFAULT_MIN_OPTS_BB_COUNT)
1506-
{
1507-
postOrder = new (m_allocator) BasicBlock*[blockCount];
1508-
}
1509-
else
1510-
{
1511-
postOrder = (BasicBlock**)_alloca(blockCount * sizeof(BasicBlock*));
1512-
}
1502+
m_postOrder = new (m_allocator) BasicBlock*[blockCount];
15131503

15141504
m_visitedTraits = BitVecTraits(blockCount, m_pCompiler);
15151505
m_visited = BitVecOps::MakeEmpty(&m_visitedTraits);
@@ -1527,12 +1517,12 @@ void SsaBuilder::Build()
15271517
}
15281518

15291519
// Topologically sort the graph.
1530-
int count = TopologicalSort(postOrder, blockCount);
1520+
m_postOrderCount = TopologicalSort(m_postOrder, blockCount);
15311521
JITDUMP("[SsaBuilder] Topologically sorted the graph.\n");
15321522
EndPhase(PHASE_BUILD_SSA_TOPOSORT);
15331523

15341524
// Compute IDom(b).
1535-
ComputeImmediateDom(postOrder, count);
1525+
ComputeImmediateDom(m_postOrder, m_postOrderCount);
15361526

15371527
m_pCompiler->fgSsaDomTree = m_pCompiler->fgBuildDomTree();
15381528
EndPhase(PHASE_BUILD_SSA_DOMS);
@@ -1551,7 +1541,7 @@ void SsaBuilder::Build()
15511541
}
15521542

15531543
// Insert phi functions.
1554-
InsertPhiFunctions(postOrder, count);
1544+
InsertPhiFunctions(m_postOrder, m_postOrderCount);
15551545

15561546
// Rename local variables and collect UD information for each ssa var.
15571547
RenameVariables();

src/coreclr/jit/ssabuilder.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ class SsaBuilder
3333
// variable are stored in the "per SSA data" on the local descriptor.
3434
void Build();
3535

36+
BasicBlock** GetPostOrder(unsigned* count)
37+
{
38+
*count = m_postOrderCount;
39+
return m_postOrder;
40+
}
41+
3642
private:
3743
// Ensures that the basic block graph has a root for the dominator graph, by ensuring
3844
// that there is a first block that is not in a try region (adding an empty block for that purpose
@@ -44,7 +50,7 @@ class SsaBuilder
4450
// the blocks in post order (i.e., a node's children first) in the array. Returns the
4551
// number of nodes visited while sorting the graph. In other words, valid entries in
4652
// the output array.
47-
int TopologicalSort(BasicBlock** postOrder, int count);
53+
unsigned TopologicalSort(BasicBlock** postOrder, int count);
4854

4955
// Requires "postOrder" to hold the blocks of the flowgraph in topologically sorted
5056
// order. Requires count to be the valid entries in the "postOrder" array. Computes
@@ -101,4 +107,6 @@ class SsaBuilder
101107
BitVec m_visited;
102108

103109
SsaRenameState m_renameStack;
110+
BasicBlock** m_postOrder = nullptr;
111+
unsigned m_postOrderCount = 0;
104112
};

0 commit comments

Comments
 (0)