diff --git a/src/coreclr/jit/inductionvariableopts.cpp b/src/coreclr/jit/inductionvariableopts.cpp index 86d0d5e8802b9c..1a519204f24bea 100644 --- a/src/coreclr/jit/inductionvariableopts.cpp +++ b/src/coreclr/jit/inductionvariableopts.cpp @@ -921,7 +921,11 @@ bool Compiler::optWidenPrimaryIV(FlowGraphNaturalLoop* loop, unsigned lclNum, Sc BasicBlock* preheader = loop->EntryEdge(0)->getSourceBlock(); BasicBlock* initBlock = preheader; - if ((startSsaDsc->GetBlock() != nullptr) && (startSsaDsc->GetDefNode() != nullptr)) + // Prefer to initialize the widened IV in the same block as the reaching def + // of the narrow IV, but only if the reaching def is not a phi. RBO's jump threading + // can leave stale SSA with the once-containing block being unreachable. + if ((startSsaDsc->GetBlock() != nullptr) && (startSsaDsc->GetDefNode() != nullptr) && + !startSsaDsc->GetDefNode()->IsPhiDefn()) { initBlock = startSsaDsc->GetBlock(); } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_130189/Runtime_130189.cs b/src/tests/JIT/Regression/JitBlue/Runtime_130189/Runtime_130189.cs new file mode 100644 index 00000000000000..f5b79aa5ea4b4f --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_130189/Runtime_130189.cs @@ -0,0 +1,52 @@ +// 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; +using Xunit; + +// Regression test for https://github.com/dotnet/runtime/issues/130189 +// +// Redundant branch opts' dominator-based jump threading used to bypass a block +// that contained a globally-used PHI def without updating SSA. That left the +// loop reading a stale (soon to be dead) PHI value, which subsequent induction +// variable widening then miscompiled, producing a wrong result. + +public sealed class Runtime_130189 +{ + ushort[] d = [0, 0, 1, 65535, 1, 0, 1, 65535, 65535]; + int[] a = [0, 4]; + int i; + + bool Next(out int p) + { + bool r; + if (r = i < a.Length) + p = a[i++]; + else + p = -1; + return r; + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + internal long Sum() + { + i = 0; + long s = 0; + int x, p; + while (Next(out p)) + { + while ((x = d[p]) != 65535) + { + s += x; + p++; + } + } + return s; + } + + [Fact] + public static void TestEntryPoint() + { + Assert.Equal(3, new Runtime_130189().Sum()); + } +} diff --git a/src/tests/JIT/Regression/Regression_ro_2.csproj b/src/tests/JIT/Regression/Regression_ro_2.csproj index 0e0038ffd073b3..9eb24d812fa553 100644 --- a/src/tests/JIT/Regression/Regression_ro_2.csproj +++ b/src/tests/JIT/Regression/Regression_ro_2.csproj @@ -109,6 +109,7 @@ +