diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 45837902d85f2..afbaeeb931bff 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -11147,6 +11147,7 @@ void Compiler::fgValueNumberPhiDef(GenTreeLclVar* newSsaDef, BasicBlock* blk, bo GenTreePhi* phiNode = newSsaDef->AsLclVar()->Data()->AsPhi(); ValueNumPair sameVNP; + VNSet loopInvariantCache(getAllocator(CMK_ValueNumber)); for (GenTreePhi::Use& use : phiNode->Uses()) { @@ -11167,16 +11168,34 @@ void Compiler::fgValueNumberPhiDef(GenTreeLclVar* newSsaDef, BasicBlock* blk, bo ValueNumPair phiArgVNP = lvaGetDesc(phiArg)->GetPerSsaData(phiArg->GetSsaNum())->m_vnPair; -#ifdef DEBUG - if (verbose && isUpdate && (phiArgVNP != phiArg->gtVNPair)) + if (isUpdate && (phiArgVNP != phiArg->gtVNPair)) { - printf("Updating phi arg [%06u] VN from ", dspTreeID(phiArg)); - vnpPrint(phiArg->gtVNPair, 0); - printf(" to "); - vnpPrint(phiArgVNP, 0); - printf("\n"); - } + FlowGraphNaturalLoop* const blockLoop = m_loops->GetLoopByHeader(blk); + bool const canUseNewVN = optVNIsLoopInvariant(phiArgVNP.GetConservative(), blockLoop, &loopInvariantCache); + + if (canUseNewVN) + { +#ifdef DEBUG + if (verbose) + { + printf("Updating phi arg [%06u] VN from ", dspTreeID(phiArg)); + vnpPrint(phiArg->gtVNPair, 0); + printf(" to "); + vnpPrint(phiArgVNP, 0); + printf("\n"); + } #endif + } + else + { + JITDUMP("Can't update phi arg [%06u] with " FMT_VN " -- varies in " FMT_LP "\n", dspTreeID(phiArg), + phiArgVNP.GetConservative(), blockLoop->GetIndex()); + + // Code below uses phiArgVNP, reset to the old value + // + phiArgVNP = phiArg->gtVNPair; + } + } phiArg->gtVNPair = phiArgVNP; diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105792/Runtime_105792.cs b/src/tests/JIT/Regression/JitBlue/Runtime_105792/Runtime_105792.cs new file mode 100644 index 0000000000000..993905d864e2d --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105792/Runtime_105792.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_105792 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static int Problem1(int x) + { + int y = 0; + while (x != 0) + { + if (y == x) return -1; + y = x; + Update(ref x); + } + return x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int Problem2(int x) + { + int y = 0; + while (x != 0) + { + if (y == x + 1) return -1; + y = x + 1; + Update(ref x); + } + return x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Update(ref int x) + { + x = x - 1; + } + + [Fact] + public static int Test1() => Problem1(10) + 100; + + [Fact] + public static int Test2() => Problem2(10) + 100; +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105792/Runtime_105792.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_105792/Runtime_105792.csproj new file mode 100644 index 0000000000000..de6d5e08882e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105792/Runtime_105792.csproj @@ -0,0 +1,8 @@ + + + True + + + + +