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
+
+
+
+
+
+
+
+
+