From bac1caa5370c60cd7f37abf7b7d68d71638ffda6 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 17:58:58 -0700 Subject: [PATCH 1/7] Fix GetOperForHWIntrinsicId testing isScalar pointer instead of value The scalar-only IsScalarZero refinement guarded on the isScalar pointer (always non-null) rather than *isScalar, so a packed SUB-mapped intrinsic with a constant op1 whose low element is zero -- but which is not all-zero, e.g. Vector128.Create(0, 5, 6, 7) - x -- was mis-mapped to GT_NEG. morph consumes the packed effective oper and drops the real constant, a latent miscompile. Dereference the flag so the refinement only applies to scalar ops. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/coreclr/jit/gentree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index bbec675a6f07a1..0279735529e7e0 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -31103,7 +31103,7 @@ genTreeOps GenTreeHWIntrinsic::GetOperForHWIntrinsicId(bool* isScalar, bool getE { oper = GT_NEG; } - else if (isScalar && op1->IsCnsVec() && op1->AsVecCon()->IsScalarZero(simdBaseType)) + else if (*isScalar && op1->IsCnsVec() && op1->AsVecCon()->IsScalarZero(simdBaseType)) { oper = GT_NEG; } From 24b5cea60e1dee566459fae559bd763c9caeb03f Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 17:59:54 -0700 Subject: [PATCH 2/7] Fix stray block clobbering needsFixup in gtNewSimdMinMaxNode The min-branch signed-zero fast path computed eedsFixup per isNumber/isScalar, then an unconditional trailing block overwrote it with IsVectorNegativeZero for all four cases -- so scalar and non-negative-zero vector cases got the wrong value. When it wrongly lands alse, the const-fold fast path is taken without the required AVX512 fixup, a latent miscompile of Min with a signed-zero constant. Mirror the correct max branch: the non-scalar non-number case uses IsVectorNegativeZero and the stray block is removed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/coreclr/jit/gentree.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 0279735529e7e0..f288fcf0386960 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -25982,9 +25982,6 @@ GenTree* Compiler::gtNewSimdMinMaxNode(var_types type, needsFixup = cnsNode->IsFloatNegativeZero(); } else - { - needsFixup = cnsNode->IsVectorZero(); - } { needsFixup = cnsNode->IsVectorNegativeZero(simdBaseType); } From b30845a9af83ef9fd6e956881ae3064ff1e2f699 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 18:42:30 -0700 Subject: [PATCH 3/7] Add regression test for GetOperForHWIntrinsicId isScalar fix Covers packed integer `(cns - v1) + v2` where the constant's low lane is zero, which was previously miscompiled by dropping the constant. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../JitBlue/Runtime_130830/Runtime_130830.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_130830/Runtime_130830.cs diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_130830/Runtime_130830.cs b/src/tests/JIT/Regression/JitBlue/Runtime_130830/Runtime_130830.cs new file mode 100644 index 00000000000000..a9d09d08828f84 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_130830/Runtime_130830.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Runtime_130830; + +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using Xunit; + +public static class Runtime_130830 +{ + [Fact] + public static void TestEntryPoint() + { + Vector128 result = Test(Vector128.Create(10), Vector128.Create(100)); + Assert.Equal(Vector128.Create(90, 91, 92, 93), result); + } + + // The low lane of the constant is zero but the constant is not all-zero, so the + // subtract must not be treated as a negate; otherwise the constant is dropped and + // the result collapses to <90, 90, 90, 90>. + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static Vector128 Test(Vector128 v1, Vector128 v2) + { + return (Vector128.Create(0, 1, 2, 3) - v1) + v2; + } +} From ac4ba64b3cad77d25210857da4df93d41b117841 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 18:42:38 -0700 Subject: [PATCH 4/7] Add regression test for gtNewSimdMinMaxNode needsFixup fix Covers Min/MinNumber with a signed-zero constant, the finite opposite-signed-zero case that Runtime_98068 never exercised. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../JitBlue/Runtime_130831/Runtime_130831.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs b/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs new file mode 100644 index 00000000000000..037a5c5cc1fd01 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Runtime_130831; + +using System.Runtime.CompilerServices; +using Xunit; + +public static class Runtime_130831 +{ + // xunit's Assert.Equal for float/double compares bitwise, so it distinguishes -0.0 from +0.0. + [Fact] + public static void TestEntryPoint() + { + Assert.Equal(-0.0, MinNegZeroConst(+0.0)); + Assert.Equal(-0.0, MinNumberZeroConst(-0.0)); + + Assert.Equal(-0.0f, MinNegZeroConst(+0.0f)); + Assert.Equal(-0.0f, MinNumberZeroConst(-0.0f)); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static double MinNegZeroConst(double value) => double.Min(value, -0.0); + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static double MinNumberZeroConst(double value) => double.MinNumber(value, +0.0); + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static float MinNegZeroConst(float value) => float.Min(value, -0.0f); + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static float MinNumberZeroConst(float value) => float.MinNumber(value, +0.0f); +} From 2ad2d7e9320177a6bcdb0d342682f89b5a8ca739 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 18:58:05 -0700 Subject: [PATCH 5/7] Compare signed-zero results bitwise in Runtime_130831 Double/Single.Equals treat -0.0 and +0.0 as equal, so the original Assert.Equal assertions did not observe a wrong-signed-zero result. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../JitBlue/Runtime_130831/Runtime_130831.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs b/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs index 037a5c5cc1fd01..42a58b1d9c5b48 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs @@ -3,20 +3,22 @@ namespace Runtime_130831; +using System; using System.Runtime.CompilerServices; using Xunit; public static class Runtime_130831 { - // xunit's Assert.Equal for float/double compares bitwise, so it distinguishes -0.0 from +0.0. + // Compare the exact bit pattern: Double/Single.Equals treat -0.0 and +0.0 as equal, + // so a plain Assert.Equal would not observe a wrong-signed-zero result. [Fact] public static void TestEntryPoint() { - Assert.Equal(-0.0, MinNegZeroConst(+0.0)); - Assert.Equal(-0.0, MinNumberZeroConst(-0.0)); + Assert.Equal(BitConverter.DoubleToInt64Bits(-0.0), BitConverter.DoubleToInt64Bits(MinNegZeroConst(+0.0))); + Assert.Equal(BitConverter.DoubleToInt64Bits(-0.0), BitConverter.DoubleToInt64Bits(MinNumberZeroConst(-0.0))); - Assert.Equal(-0.0f, MinNegZeroConst(+0.0f)); - Assert.Equal(-0.0f, MinNumberZeroConst(-0.0f)); + Assert.Equal(BitConverter.SingleToInt32Bits(-0.0f), BitConverter.SingleToInt32Bits(MinNegZeroConst(+0.0f))); + Assert.Equal(BitConverter.SingleToInt32Bits(-0.0f), BitConverter.SingleToInt32Bits(MinNumberZeroConst(-0.0f))); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] From 45c9dfe3b26431e9282bbbb6078c7973d0db59c2 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:24:29 -0700 Subject: [PATCH 6/7] Reference new JitBlue tests from Regression_ro_2.csproj The merged JitBlue tests need an explicit Compile entry to be built and run in CI; without it Runtime_130830 and Runtime_130831 were not exercised. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/tests/JIT/Regression/Regression_ro_2.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/JIT/Regression/Regression_ro_2.csproj b/src/tests/JIT/Regression/Regression_ro_2.csproj index f37653b74cbc16..690df1246b734d 100644 --- a/src/tests/JIT/Regression/Regression_ro_2.csproj +++ b/src/tests/JIT/Regression/Regression_ro_2.csproj @@ -114,6 +114,8 @@ + + From 683376a6890924870f0a165614b0ededfcd379a1 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 20 Jul 2026 19:11:00 -0700 Subject: [PATCH 7/7] Skip Runtime_130831 on Mono for signed-zero Min divergence Mono's Min/MinNumber lowering doesn't preserve the sign of zero, tracked by #131130. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs b/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs index 42a58b1d9c5b48..37597d88bc61ea 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_130831/Runtime_130831.cs @@ -12,6 +12,7 @@ public static class Runtime_130831 // Compare the exact bit pattern: Double/Single.Equals treat -0.0 and +0.0 as equal, // so a plain Assert.Equal would not observe a wrong-signed-zero result. [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/131130", TestPlatforms.Any)] public static void TestEntryPoint() { Assert.Equal(BitConverter.DoubleToInt64Bits(-0.0), BitConverter.DoubleToInt64Bits(MinNegZeroConst(+0.0)));