diff --git a/src/coreclr/jit/redundantbranchopts.cpp b/src/coreclr/jit/redundantbranchopts.cpp index 3fde336a8efead..bcf34fdb97af77 100644 --- a/src/coreclr/jit/redundantbranchopts.cpp +++ b/src/coreclr/jit/redundantbranchopts.cpp @@ -1585,6 +1585,7 @@ static bool optGetThreadedSsaNumForBlock(JumpThreadInfo& jti, GenTreeLclVar* phi assert(jti.m_numAmbiguousPreds != 0); bool foundReplacement = false; + BitVec coveredPreds = BitVecOps::MakeEmpty(&jti.traits); unsigned replacementSsa = SsaConfig::RESERVED_SSA_NUM; GenTreePhi* const phi = phiDef->Data()->AsPhi(); @@ -1598,6 +1599,8 @@ static bool optGetThreadedSsaNumForBlock(JumpThreadInfo& jti, GenTreeLclVar* phi continue; } + BitVecOps::AddElemD(&jti.traits, coveredPreds, predBlock->bbPostorderNum); + if (!foundReplacement) { replacementSsa = phiArgNode->GetSsaNum(); @@ -1609,7 +1612,7 @@ static bool optGetThreadedSsaNumForBlock(JumpThreadInfo& jti, GenTreeLclVar* phi } } - if (!foundReplacement) + if (!foundReplacement || !BitVecOps::Equal(&jti.traits, coveredPreds, jti.m_ambiguousPreds)) { return false; } @@ -1643,7 +1646,34 @@ static bool optGetThreadedSsaNumForSuccessor(JumpThreadInfo& jti, *hasThreadedPreds = false; *replacementSsaNum = SsaConfig::RESERVED_SSA_NUM; + BitVec expectedPreds = BitVecOps::MakeCopy(&jti.traits, jti.m_ambiguousPreds); + for (BasicBlock* const predBlock : jti.m_block->PredBlocks()) + { + if (BitVecOps::IsMember(&jti.traits, jti.m_ambiguousPreds, predBlock->bbPostorderNum)) + { + continue; + } + + BasicBlock* predTarget = nullptr; + if (BitVecOps::IsMember(&jti.traits, jti.m_truePreds, predBlock->bbPostorderNum)) + { + predTarget = jti.m_trueTarget; + } + else + { + assert(jti.m_numFalsePreds != 0); + predTarget = jti.m_falseTarget; + } + + if (predTarget == successor) + { + BitVecOps::AddElemD(&jti.traits, expectedPreds, predBlock->bbPostorderNum); + *hasThreadedPreds = true; + } + } + bool foundReplacement = false; + BitVec coveredPreds = BitVecOps::MakeEmpty(&jti.traits); unsigned replacementSsa = SsaConfig::RESERVED_SSA_NUM; GenTreePhi* const phi = phiDef->Data()->AsPhi(); @@ -1651,20 +1681,13 @@ static bool optGetThreadedSsaNumForSuccessor(JumpThreadInfo& jti, { GenTreePhiArg* const phiArgNode = use.GetNode()->AsPhiArg(); BasicBlock* const predBlock = phiArgNode->gtPredBB; - bool const isTruePred = BitVecOps::IsMember(&jti.traits, jti.m_truePreds, predBlock->bbPostorderNum); - bool const isAmbiguousPred = BitVecOps::IsMember(&jti.traits, jti.m_ambiguousPreds, predBlock->bbPostorderNum); - - if (!isAmbiguousPred) + if (!BitVecOps::IsMember(&jti.traits, expectedPreds, predBlock->bbPostorderNum)) { - BasicBlock* const predTarget = isTruePred ? jti.m_trueTarget : jti.m_falseTarget; - if (predTarget != successor) - { - continue; - } - - *hasThreadedPreds = true; + continue; } + BitVecOps::AddElemD(&jti.traits, coveredPreds, predBlock->bbPostorderNum); + if (!foundReplacement) { replacementSsa = phiArgNode->GetSsaNum(); @@ -1677,7 +1700,7 @@ static bool optGetThreadedSsaNumForSuccessor(JumpThreadInfo& jti, } *replacementSsaNum = replacementSsa; - return foundReplacement; + return foundReplacement && BitVecOps::Equal(&jti.traits, coveredPreds, expectedPreds); } //------------------------------------------------------------------------ diff --git a/src/tests/JIT/opt/RedundantBranch/JumpThreadPhi.cs b/src/tests/JIT/opt/RedundantBranch/JumpThreadPhi.cs index 64fa4824bd23f9..71c27d77d5970b 100644 --- a/src/tests/JIT/opt/RedundantBranch/JumpThreadPhi.cs +++ b/src/tests/JIT/opt/RedundantBranch/JumpThreadPhi.cs @@ -28,4 +28,41 @@ public static void TestPhi00() Assert.Equal(100, Phi_00(1)); Assert.Equal(103, Phi_00(8)); } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static int Phi_01(bool q, bool r, int u, int v) + { + int z = 0, w = 0, m = 0, n = 0; + if (r) + { + m = v; + n = 1; + goto Target; + } + + if (q) + { + z = u; + w = 1; + } + + if (z != w) + { + return -1; + } + + Target: + if (m == n) + { + return 200; + } + + return 100 + n; + } + + [Fact] + public static void TestPhi01() + { + Assert.Equal(200, Phi_01(false, false, 0, 0)); + } }