From d86b525cc7b2233960e2d23c9f9e031a514e3bde Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 17 Apr 2026 19:05:18 -0700 Subject: [PATCH] JIT: Renable SSA-aware PHI jump threading Teach redundant branch elimination to keep jump threading through PHI-based blocks when the PHI uses can be fully accounted for in the block and its immediate successors. Rewrite the affected successor SSA/VN uses, keep dominating-block threading conservative, and add focused regression coverage for the new PHI-based cases. Fix included here that was not in #126812: ensure that field uses of locals get the proper VN updates. Fixes #126976. --- src/coreclr/jit/redundantbranchopts.cpp | 36 ++++++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/redundantbranchopts.cpp b/src/coreclr/jit/redundantbranchopts.cpp index fbe16664ab7609..6063caf46a65d0 100644 --- a/src/coreclr/jit/redundantbranchopts.cpp +++ b/src/coreclr/jit/redundantbranchopts.cpp @@ -1764,7 +1764,7 @@ Compiler::JumpThreadCheckResult Compiler::optJumpThreadCheck(BasicBlock* const b { JITDUMP(FMT_BB " has global phi for V%02u.%u; no phi-based threading\n", block->bbNum, lclNum, ssaNum); - return JumpThreadCheckResult::CannotThread; + hasGlobalPhiUses = true; } } @@ -2303,23 +2303,45 @@ bool Compiler::optJumpThreadCore(JumpThreadInfo& jti) GenTreeLclVarCommon* const use = phiUse.m_use; unsigned const oldSsaNum = use->GetSsaNum(); + unsigned const lclNum = use->GetLclNum(); - if (oldSsaNum == phiUse.m_replacementSsaNum) - { - continue; - } + assert(oldSsaNum != phiUse.m_replacementSsaNum); JITDUMP("Updating [%06u] in " FMT_BB " from u:%u to u:%u\n", dspTreeID(use), phiUse.m_block->bbNum, oldSsaNum, phiUse.m_replacementSsaNum); - LclSsaVarDsc* const replacementSsaDef = lvaGetDesc(use->GetLclNum())->GetPerSsaData(phiUse.m_replacementSsaNum); + LclSsaVarDsc* const replacementSsaDef = lvaGetDesc(lclNum)->GetPerSsaData(phiUse.m_replacementSsaNum); use->SetSsaNum(phiUse.m_replacementSsaNum); // Keep the use's value number in sync with the rewritten SSA def. + // if (use->gtVNPair != replacementSsaDef->m_vnPair) { - use->SetVNs(replacementSsaDef->m_vnPair); + ValueNumPair newVNPair = replacementSsaDef->m_vnPair; + + // If this is a field use, get the proper field VN. + + if (use->OperIs(GT_LCL_FLD)) + { + GenTreeLclFld* const lclFld = use->AsLclFld(); + + newVNPair = vnStore->VNPairForLoad(replacementSsaDef->m_vnPair, lvaLclValueSize(lclNum), + lclFld->TypeGet(), lclFld->GetLclOffs(), lclFld->GetValueSize()); + } + else + { + assert(use->OperIs(GT_LCL_VAR)); + } + + JITDUMP("Updating [%06u] VN from ", dspTreeID(use)); + JITDUMPEXEC(vnpPrint(use->gtVNPair, 1)); + JITDUMP(" to "); + JITDUMPEXEC(vnpPrint(newVNPair, 1)); + JITDUMP("\n"); + + use->SetVNs(newVNPair); + GenTree* node = use; GenTree* parent = node->gtGetParent(nullptr);