Skip to content

Commit d1cc577

Browse files
authored
JIT: fix count reconstruction when a natural loop contains an improper loop (#100449)
If a natural loop contains an improper loop, the cyclic probability computation for the natural loop will be an underestimate, as the cyclic probability computation assumes one pass convergence. In such cases count reconstruction may report convergence when it has not in fact converged, as any natural loop header ignores flow from its back edges, assuming their impact has been accounted for by the cyclic probability. So when a loop contains improper loops, fall back to normal iterative computation for the loop. We could use the cyclic probability initially as a convergence accelerator, but would need to switch over to not using it to guarantee full convergence. But that complicates the logic and these cases are rare.
1 parent fb5e93a commit d1cc577

3 files changed

Lines changed: 21 additions & 2 deletions

File tree

src/coreclr/jit/compiler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,6 +2091,9 @@ class FlowGraphNaturalLoop
20912091
// Can be used to store additional annotations for this loop on the side.
20922092
unsigned m_index = 0;
20932093

2094+
// True if this loop contains an improper loop header
2095+
bool m_containsImproperHeader = false;
2096+
20942097
FlowGraphNaturalLoop(const FlowGraphDfsTree* dfsTree, BasicBlock* head);
20952098

20962099
unsigned LoopBlockBitVecIndex(BasicBlock* block);
@@ -2179,6 +2182,11 @@ class FlowGraphNaturalLoop
21792182
bool ContainsBlock(BasicBlock* block);
21802183
bool ContainsLoop(FlowGraphNaturalLoop* childLoop);
21812184

2185+
bool ContainsImproperHeader() const
2186+
{
2187+
return m_containsImproperHeader;
2188+
}
2189+
21822190
unsigned NumLoopBlocks();
21832191

21842192
template<typename TFunc>

src/coreclr/jit/fgprofilesynthesis.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,12 +1193,14 @@ void ProfileSynthesis::GaussSeidelSolver()
11931193
//
11941194
if (block->bbPreds != nullptr)
11951195
{
1196-
// Leverage Cp for existing loop headers.
1196+
// Leverage Cp for existing loop headers, provided that
1197+
// all contained loops are proper.
1198+
//
11971199
// This is an optimization to speed convergence.
11981200
//
11991201
FlowGraphNaturalLoop* const loop = m_loops->GetLoopByHeader(block);
12001202

1201-
if (loop != nullptr)
1203+
if ((loop != nullptr) && !loop->ContainsImproperHeader())
12021204
{
12031205
// Sum all entry edges that aren't EH flow
12041206
//

src/coreclr/jit/flowgraph.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4386,6 +4386,15 @@ FlowGraphNaturalLoops* FlowGraphNaturalLoops::Find(const FlowGraphDfsTree* dfsTr
43864386
if (!FindNaturalLoopBlocks(loop, worklist))
43874387
{
43884388
loops->m_improperLoopHeaders++;
4389+
4390+
for (FlowGraphNaturalLoop* const otherLoop : loops->InPostOrder())
4391+
{
4392+
if (otherLoop->ContainsBlock(header))
4393+
{
4394+
otherLoop->m_containsImproperHeader = true;
4395+
}
4396+
}
4397+
43894398
continue;
43904399
}
43914400

0 commit comments

Comments
 (0)