Skip to content

Commit b8ac8b2

Browse files
authored
JIT: Refine post-dominance check in strength reduction (#104687)
When strength reduction has to find an insertion point for the new primary IV update it needs to find a block that post-dominates all the users of the IV. This was using `optReachable` before, but that is conservative since it finds paths that may exit the loop. This implements a more precise check.
1 parent 61f08d3 commit b8ac8b2

File tree

4 files changed

+74
-12
lines changed

4 files changed

+74
-12
lines changed

src/coreclr/jit/compiler.h

+2
Original file line numberDiff line numberDiff line change
@@ -2232,6 +2232,8 @@ class FlowGraphNaturalLoop
22322232

22332233
bool MayExecuteBlockMultipleTimesPerIteration(BasicBlock* block);
22342234

2235+
bool IsPostDominatedOnLoopIteration(BasicBlock* block, BasicBlock* postDominator);
2236+
22352237
#ifdef DEBUG
22362238
static void Dump(FlowGraphNaturalLoop* loop);
22372239
#endif // DEBUG

src/coreclr/jit/flowgraph.cpp

+70
Original file line numberDiff line numberDiff line change
@@ -5801,6 +5801,76 @@ bool FlowGraphNaturalLoop::MayExecuteBlockMultipleTimesPerIteration(BasicBlock*
58015801
return false;
58025802
}
58035803

5804+
//------------------------------------------------------------------------
5805+
// IsPostDominatedOnLoopIteration:
5806+
// Check whether control will always flow through "postDominator" if starting
5807+
// at "block" and a backedge is taken.
5808+
//
5809+
// Parameters:
5810+
// block - The basic block
5811+
// postDominator - Block to query postdominance of
5812+
//
5813+
// Returns:
5814+
// True if so.
5815+
//
5816+
bool FlowGraphNaturalLoop::IsPostDominatedOnLoopIteration(BasicBlock* block, BasicBlock* postDominator)
5817+
{
5818+
assert(ContainsBlock(block) && ContainsBlock(postDominator));
5819+
5820+
unsigned index;
5821+
bool gotIndex = TryGetLoopBlockBitVecIndex(block, &index);
5822+
assert(gotIndex);
5823+
5824+
Compiler* comp = m_dfsTree->GetCompiler();
5825+
ArrayStack<BasicBlock*> stack(comp->getAllocator(CMK_Loops));
5826+
5827+
BitVecTraits traits = LoopBlockTraits();
5828+
BitVec visited(BitVecOps::MakeEmpty(&traits));
5829+
5830+
stack.Push(block);
5831+
BitVecOps::AddElemD(&traits, visited, index);
5832+
5833+
auto queueSuccs = [=, &stack, &traits, &visited](BasicBlock* succ) {
5834+
if (succ == m_header)
5835+
{
5836+
// We managed to reach the header without going through "postDominator".
5837+
return BasicBlockVisit::Abort;
5838+
}
5839+
5840+
unsigned index;
5841+
if (!TryGetLoopBlockBitVecIndex(succ, &index) || !BitVecOps::IsMember(&traits, m_blocks, index))
5842+
{
5843+
// Block is not inside loop
5844+
return BasicBlockVisit::Continue;
5845+
}
5846+
5847+
if (!BitVecOps::TryAddElemD(&traits, visited, index))
5848+
{
5849+
// Block already visited
5850+
return BasicBlockVisit::Continue;
5851+
}
5852+
5853+
stack.Push(succ);
5854+
return BasicBlockVisit::Continue;
5855+
};
5856+
5857+
while (stack.Height() > 0)
5858+
{
5859+
BasicBlock* block = stack.Pop();
5860+
if (block == postDominator)
5861+
{
5862+
continue;
5863+
}
5864+
5865+
if (block->VisitAllSuccs(comp, queueSuccs) == BasicBlockVisit::Abort)
5866+
{
5867+
return false;
5868+
}
5869+
}
5870+
5871+
return true;
5872+
}
5873+
58045874
//------------------------------------------------------------------------
58055875
// IterConst: Get the constant with which the iterator is modified
58065876
//

src/coreclr/jit/inductionvariableopts.cpp

+1-9
Original file line numberDiff line numberDiff line change
@@ -1853,16 +1853,8 @@ BasicBlock* StrengthReductionContext::FindUpdateInsertionPoint(ArrayStack<Cursor
18531853
}
18541854
else
18551855
{
1856-
if (m_comp->optReachable(cursor.Block, m_loop->GetHeader(), insertionPoint))
1856+
if (!m_loop->IsPostDominatedOnLoopIteration(cursor.Block, insertionPoint))
18571857
{
1858-
// Header is reachable without going through the insertion
1859-
// point, meaning that the insertion point does not
1860-
// post-dominate the use of an IV we want to replace.
1861-
//
1862-
// TODO-CQ: We only need to check whether the header is
1863-
// reachable from inside the loop, which is both cheaper and
1864-
// less conservative to check.
1865-
//
18661858
return nullptr;
18671859
}
18681860
}

src/coreclr/jit/redundantbranchopts.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -2224,13 +2224,11 @@ bool Compiler::optReachable(BasicBlock* const fromBlock, BasicBlock* const toBlo
22242224
return BasicBlockVisit::Abort;
22252225
}
22262226

2227-
if (BitVecOps::IsMember(optReachableBitVecTraits, optReachableBitVec, succ->bbNum))
2227+
if (!BitVecOps::TryAddElemD(optReachableBitVecTraits, optReachableBitVec, succ->bbNum))
22282228
{
22292229
return BasicBlockVisit::Continue;
22302230
}
22312231

2232-
BitVecOps::AddElemD(optReachableBitVecTraits, optReachableBitVec, succ->bbNum);
2233-
22342232
stack.Push(succ);
22352233
return BasicBlockVisit::Continue;
22362234
});

0 commit comments

Comments
 (0)