Skip to content

Commit 6f19e37

Browse files
authored
JIT: one phi arg per pred (#85546)
Revise SSA to add one phi arg per pred instead of one phi arg per ssa def. This unlocks some cases for redundant branch opts. In some pathological cases we may see extremely long phi arg lists. Will keep an eye out for that and perhaps modify the strategy if we end up with hundreds or thousands of phi args. Addresses an issue noted in #48115.
1 parent d75e811 commit 6f19e37

File tree

1 file changed

+32
-44
lines changed

1 file changed

+32
-44
lines changed

src/coreclr/jit/ssabuilder.cpp

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,8 @@ void SsaBuilder::InsertPhi(BasicBlock* block, unsigned lclNum)
551551
}
552552

553553
//------------------------------------------------------------------------
554-
// AddPhiArg: Add a new GT_PHI_ARG node to an existing GT_PHI node.
554+
// AddPhiArg: Ensure an existing GT_PHI node contains an appropriate PhiArg
555+
// for an ssa def arriving via pred
555556
//
556557
// Arguments:
557558
// block - The block that contains the statement
@@ -563,14 +564,32 @@ void SsaBuilder::InsertPhi(BasicBlock* block, unsigned lclNum)
563564
void SsaBuilder::AddPhiArg(
564565
BasicBlock* block, Statement* stmt, GenTreePhi* phi, unsigned lclNum, unsigned ssaNum, BasicBlock* pred)
565566
{
566-
#ifdef DEBUG
567-
// Make sure it isn't already present: we should only add each definition once.
567+
// If there's already a phi arg for this pred, it had better have
568+
// matching ssaNum, unless this block is a handler entry.
569+
//
570+
const bool isHandlerEntry = m_pCompiler->bbIsHandlerBeg(block);
571+
568572
for (GenTreePhi::Use& use : phi->Uses())
569573
{
570-
assert(use.GetNode()->AsPhiArg()->GetSsaNum() != ssaNum);
574+
GenTreePhiArg* const phiArg = use.GetNode()->AsPhiArg();
575+
576+
if (phiArg->gtPredBB == pred)
577+
{
578+
if (phiArg->GetSsaNum() == ssaNum)
579+
{
580+
// We already have this (pred, ssaNum) phiArg
581+
return;
582+
}
583+
584+
// Add another ssaNum for this pred?
585+
// Should only be possible at handler entries.
586+
//
587+
noway_assert(isHandlerEntry);
588+
}
571589
}
572-
#endif // DEBUG
573590

591+
// Didn't find a match, add a new phi arg
592+
//
574593
var_types type = m_pCompiler->lvaGetDesc(lclNum)->TypeGet();
575594

576595
GenTree* phiArg = new (m_pCompiler, GT_PHI_ARG) GenTreePhiArg(type, lclNum, ssaNum, pred);
@@ -1186,29 +1205,12 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block)
11861205
break;
11871206
}
11881207

1189-
GenTree* tree = stmt->GetRootNode();
1190-
GenTreePhi* phi = tree->gtGetOp2()->AsPhi();
1191-
1192-
unsigned lclNum = tree->AsOp()->gtOp1->AsLclVar()->GetLclNum();
1193-
unsigned ssaNum = m_renameStack.Top(lclNum);
1194-
// Search the arglist for an existing definition for ssaNum.
1195-
// (Can we assert that its the head of the list? This should only happen when we add
1196-
// during renaming for a definition that occurs within a try, and then that's the last
1197-
// value of the var within that basic block.)
1208+
GenTree* tree = stmt->GetRootNode();
1209+
GenTreePhi* phi = tree->gtGetOp2()->AsPhi();
1210+
unsigned lclNum = tree->AsOp()->gtOp1->AsLclVar()->GetLclNum();
1211+
unsigned ssaNum = m_renameStack.Top(lclNum);
11981212

1199-
bool found = false;
1200-
for (GenTreePhi::Use& use : phi->Uses())
1201-
{
1202-
if (use.GetNode()->AsPhiArg()->GetSsaNum() == ssaNum)
1203-
{
1204-
found = true;
1205-
break;
1206-
}
1207-
}
1208-
if (!found)
1209-
{
1210-
AddPhiArg(succ, stmt, phi, lclNum, ssaNum, block);
1211-
}
1213+
AddPhiArg(succ, stmt, phi, lclNum, ssaNum, block);
12121214
}
12131215

12141216
// Now handle memory.
@@ -1333,24 +1335,10 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block)
13331335
continue;
13341336
}
13351337

1336-
GenTreePhi* phi = tree->gtGetOp2()->AsPhi();
1337-
1338-
unsigned ssaNum = m_renameStack.Top(lclNum);
1338+
GenTreePhi* phi = tree->gtGetOp2()->AsPhi();
1339+
unsigned ssaNum = m_renameStack.Top(lclNum);
13391340

1340-
// See if this ssaNum is already an arg to the phi.
1341-
bool alreadyArg = false;
1342-
for (GenTreePhi::Use& use : phi->Uses())
1343-
{
1344-
if (use.GetNode()->AsPhiArg()->GetSsaNum() == ssaNum)
1345-
{
1346-
alreadyArg = true;
1347-
break;
1348-
}
1349-
}
1350-
if (!alreadyArg)
1351-
{
1352-
AddPhiArg(handlerStart, stmt, phi, lclNum, ssaNum, block);
1353-
}
1341+
AddPhiArg(handlerStart, stmt, phi, lclNum, ssaNum, block);
13541342
}
13551343

13561344
// Now handle memory.

0 commit comments

Comments
 (0)