diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index ffad32a61b2001..bdf7fc3c182c10 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -763,7 +763,7 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse break; case O2K_SUBRANGE: - printf("[%d..%d]", curAssertion->op2.u2.loBound, curAssertion->op2.u2.hiBound); + printf("[%u..%u]", curAssertion->op2.u2.loBound, curAssertion->op2.u2.hiBound); break; default: @@ -2325,7 +2325,7 @@ AssertionIndex Compiler::optFindComplementary(AssertionIndex assertIndex) /***************************************************************************** * * Given a lclNum, a fromType and a toType, return assertion index of the assertion that - * claims that a variable's value is always a valid subrange of the formType. + * claims that a variable's value is always a valid subrange of the fromType. * Thus we can discard or omit a cast to fromType. Returns NO_ASSERTION_INDEX * if one such assertion could not be found in "assertions." */ @@ -4830,6 +4830,15 @@ class AssertionPropFlowCallback // It means we can propagate only assertions that are valid for the whole try region. void MergeHandler(BasicBlock* block, BasicBlock* firstTryBlock, BasicBlock* lastTryBlock) { + if (VerboseDataflow()) + { + JITDUMP("Merge : " FMT_BB " ", block->bbNum); + Compiler::optDumpAssertionIndices("in -> ", block->bbAssertionIn, "; "); + JITDUMP("firstTryBlock " FMT_BB " ", firstTryBlock->bbNum); + Compiler::optDumpAssertionIndices("in -> ", firstTryBlock->bbAssertionIn, "; "); + JITDUMP("lastTryBlock " FMT_BB " ", lastTryBlock->bbNum); + Compiler::optDumpAssertionIndices("out -> ", lastTryBlock->bbAssertionOut, "\n"); + } BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, firstTryBlock->bbAssertionIn); BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, lastTryBlock->bbAssertionOut); } @@ -4933,8 +4942,8 @@ ASSERT_TP* Compiler::optComputeAssertionGen() } else // is jump edge assertion { - valueAssertionIndex = optFindComplementary(info.GetAssertionIndex()); jumpDestAssertionIndex = info.GetAssertionIndex(); + valueAssertionIndex = optFindComplementary(jumpDestAssertionIndex); } if (valueAssertionIndex != NO_ASSERTION_INDEX) diff --git a/src/coreclr/jit/clrjit.natvis b/src/coreclr/jit/clrjit.natvis index b3c187474900f2..8eb3d683847e26 100644 --- a/src/coreclr/jit/clrjit.natvis +++ b/src/coreclr/jit/clrjit.natvis @@ -30,6 +30,7 @@ Documentation for VS debugger format specifiers: https://docs.microsoft.com/en-u + [{gtOper,en}, {gtType,en}] @@ -53,6 +54,16 @@ Documentation for VS debugger format specifiers: https://docs.microsoft.com/en-u [{gtOper,en}, {gtType,en}] + + + + this->m_treeList + this->gtNext + this + + + + [{lvType,en}] [{lvType,en}-{lvReason,s}] diff --git a/src/coreclr/jit/redundantbranchopts.cpp b/src/coreclr/jit/redundantbranchopts.cpp index 34fe9da3503995..b52193f3157fc5 100644 --- a/src/coreclr/jit/redundantbranchopts.cpp +++ b/src/coreclr/jit/redundantbranchopts.cpp @@ -297,6 +297,13 @@ bool Compiler::optJumpThread(BasicBlock* const block, BasicBlock* const domBlock JITDUMP("Both successors of %sdom " FMT_BB " reach " FMT_BB " -- attempting jump threading\n", isIDom ? "i" : "", domBlock->bbNum, block->bbNum); + // If the block is the first block of try-region, then skip jump threading + if (bbIsTryBeg(block)) + { + JITDUMP(FMT_BB " is first block of try-region; no threading\n", block->bbNum); + return false; + } + // Since flow is going to bypass block, make sure there // is nothing in block that can cause a side effect. // diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55131/Runtime_55131.cs b/src/tests/JIT/Regression/JitBlue/Runtime_55131/Runtime_55131.cs new file mode 100644 index 00000000000000..65a7ebaebc2929 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55131/Runtime_55131.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +public class Runtime_55131 +{ + // When merging the assertion props for the finally block, we should consider the assertions + // out of the BBJ_CALLFINALLY block. Otherwise, we could propagate the wrong assertions inside + // the finally block. + // + // Althogh there can be several ways to reproduce this problem, an easier way is to turn off + // finally cloning for below example. + [MethodImpl(MethodImplOptions.NoInlining)] + static bool False() => false; + + static ushort s_6; + static uint[] s_15 = new uint[] { 0 }; + static bool s_19 = false; + private static int Main() + { + bool condition = False(); + int result = 100; + if (condition) + { + result -= 1; + } + + try + { + if (condition) + { + result -= 1; + } + } + finally + { + if (condition) + { + result -= 1; + } + } + return result; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55131/Runtime_55131.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_55131/Runtime_55131.csproj new file mode 100644 index 00000000000000..420168c991729b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55131/Runtime_55131.csproj @@ -0,0 +1,20 @@ + + + Exe + True + None + + + + + + + + +