diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index da63679b4319cb..7b29e586dbb645 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -4304,17 +4304,19 @@ PhaseStatus Compiler::optUnrollLoops() // Heuristic: Estimated cost in code size of the unrolled loop. { - ClrSafeInt loopCostSz; // Cost is size of one iteration - auto tryIndex = loop.lpTop->bbTryIndex; + ClrSafeInt loopCostSz; // Cost is size of one iteration + const BasicBlock* const top = loop.lpTop; // Besides calculating the loop cost, also ensure that all loop blocks are within the same EH // region, and count the number of BBJ_RETURN blocks in the loop. loopRetCount = 0; for (BasicBlock* const block : loop.LoopBlocks()) { - if (block->bbTryIndex != tryIndex) + if (!BasicBlock::sameEHRegion(block, top)) { // Unrolling would require cloning EH regions + // Note that only non-funclet model (x86) could actually have a loop including a handler + // but not it's corresponding `try`, if its `try` was moved due to being marked "rare". JITDUMP("Failed to unroll loop " FMT_LP ": EH constraint\n", lnum); goto DONE_LOOP; } @@ -8799,6 +8801,11 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk) } } } + + // If there is a tree node, clear its ValueNumber. This is to ensure that for those blocks that + // are unreachable, which we still handle in this loop but not during Value Numbering, + // USE THIS: + // stmt->GetRootNode()->gtVNPair.SetBoth(ValueNumStore::NoVN); } if (memoryHavoc != emptyMemoryKindSet) diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index c43bb47a36f8d4..af245db1cbab9d 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -8086,6 +8086,22 @@ PhaseStatus Compiler::fgValueNumber() // Compute the side effects of loops. optComputeLoopSideEffects(); + // The implementation of optComputeLoopSideEffects() can set some value numbers. These should not be used, + // and in fact, the implementation should probably clear them or use a side table or other implementation + // to avoid touching the value number field, as for reachable blocks they will get overridden below. + { + for (BasicBlock* const blk : Blocks()) + { + for (Statement* const stmt : blk->NonPhiStatements()) + { + for (GenTree* const tree : stmt->TreeList()) + { + tree->gtVNPair.SetBoth(ValueNumStore::NoVN); + } + } + } + } + // At the block level, we will use a modified worklist algorithm. We will have two // "todo" sets of unvisited blocks. Blocks (other than the entry block) are put in a // todo set only when some predecessor has been visited, so all blocks have at least one diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_81675/Runtime_81675.cs b/src/tests/JIT/Regression/JitBlue/Runtime_81675/Runtime_81675.cs new file mode 100644 index 00000000000000..c71f83f10471c2 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_81675/Runtime_81675.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v1.5 on 2023-02-06 00:41:34 +// Run on X86 Windows +// Seed: 12611629827253727687 +// Reduced from 444.9 KiB to 1.1 KiB in 00:13:23 +// Hits JIT assert in Release: +// Assertion failed '!"Jump into the middle of handler region"' in 'Program:Main(Fuzzlyn.ExecutionServer.IRuntime)' during 'Unroll loops' (IL size 131; hash 0xade6b36b; FullOpts) +// +// File: D:\a\_work\1\s\src\coreclr\jit\fgdiagnostic.cpp Line: 2609 +// +public interface I0 +{ +} + +public class C0 : I0 +{ + public sbyte F3; +} + +public class Runtime_81675 +{ + public static ushort s_11; + public static bool[][] s_18; + public static C0 s_26; + public static short[] s_42; + public static void Main() + { + short vr7 = default(short); + for (int vr8 = 0; vr8 < 0; vr8++) + { + try + { + System.Console.WriteLine(32767); + } + finally + { + I0 vr9 = new C0(); + } + } + + for (int vr10 = 0; vr10 < 0; vr10++) + { + if (s_18[0][0]) + { + var vr11 = s_26.F3; + } + else + { + System.Console.WriteLine(0); + } + + if (!((ushort)(-s_11++) >= 0)) + { + vr7 = vr7; + try + { + vr7 = 0; + } + finally + { + vr7 = s_42[0]; + } + } + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_81675/Runtime_81675.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_81675/Runtime_81675.csproj new file mode 100644 index 00000000000000..c0a5f3d0484e39 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_81675/Runtime_81675.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + \ No newline at end of file