diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 5a65ddcadf0943..4f1f0395a7fc12 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -33828,7 +33828,17 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) case FloatComparisonMode::OrderedFalseNonSignaling: case FloatComparisonMode::OrderedFalseSignaling: { - resultNode = gtNewZeroConNode(retType); + if (ni == NI_AVX_CompareScalar) + { + // CompareScalar preserves upper elements from op1, + // so we can't fold to a full zero vector + break; + } + // CompareMask returns TYP_MASK which gtNewZeroConNode doesn't handle, + // so use the SIMD vector type instead; the mask conversion at the end + // of this function will wrap it with CvtVectorToMask + resultNode = gtNewZeroConNode(varTypeIsMask(retType) ? getSIMDTypeForSize(simdSize) + : retType); resultNode = gtWrapWithSideEffects(resultNode, tree, GTF_ALL_EFFECT); break; } @@ -33836,7 +33846,17 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) case FloatComparisonMode::UnorderedTrueNonSignaling: case FloatComparisonMode::UnorderedTrueSignaling: { - resultNode = gtNewAllBitsSetConNode(retType); + if (ni == NI_AVX_CompareScalar) + { + // CompareScalar preserves upper elements from op1, + // so we can't fold to a full AllBitsSet vector + break; + } + // CompareMask returns TYP_MASK which gtNewAllBitsSetConNode doesn't handle, + // so use the SIMD vector type instead; the mask conversion at the end + // of this function will wrap it with CvtVectorToMask + resultNode = gtNewAllBitsSetConNode(varTypeIsMask(retType) ? getSIMDTypeForSize(simdSize) + : retType); resultNode = gtWrapWithSideEffects(resultNode, tree, GTF_ALL_EFFECT); break; } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_125160/Runtime_125160.cs b/src/tests/JIT/Regression/JitBlue/Runtime_125160/Runtime_125160.cs new file mode 100644 index 00000000000000..aace13ceda7813 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_125160/Runtime_125160.cs @@ -0,0 +1,69 @@ +// 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 System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +public class Runtime_125160 +{ + [ConditionalFact(typeof(Avx), nameof(Avx.IsSupported))] + public static void TestEntryPoint() + { + Assert.Equal(Vector128.Create(0f, 1f, 1f, 1f), CompareFalseFloat(Vector128.One, Vector128.Zero)); + Assert.Equal(Vector128.Create(0d, 1d), CompareFalseDouble(Vector128.One, Vector128.Zero)); + + Vector128 trueFloat = CompareTrueFloat(Vector128.One, Vector128.Zero); + Assert.Equal(BitConverter.UInt32BitsToSingle(0xFFFFFFFF), trueFloat.GetElement(0)); + Assert.Equal(1f, trueFloat.GetElement(1)); + Assert.Equal(1f, trueFloat.GetElement(2)); + Assert.Equal(1f, trueFloat.GetElement(3)); + + Vector128 trueDouble = CompareTrueDouble(Vector128.One, Vector128.Zero); + Assert.Equal(BitConverter.UInt64BitsToDouble(0xFFFFFFFFFFFFFFFF), trueDouble.GetElement(0)); + Assert.Equal(1d, trueDouble.GetElement(1)); + } + + [ConditionalFact(typeof(Avx512F), nameof(Avx512F.IsSupported))] + public static void TestCompareMask() + { + Assert.Equal(Vector512.Zero, CompareMaskFalseFloat(Vector512.One, Vector512.Zero)); + Assert.Equal(Vector512.Zero, CompareMaskFalseDouble(Vector512.One, Vector512.Zero)); + Assert.Equal(Vector512.AllBitsSet, CompareMaskTrueFloat(Vector512.One, Vector512.Zero)); + Assert.Equal(Vector512.AllBitsSet, CompareMaskTrueDouble(Vector512.One, Vector512.Zero)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 CompareFalseFloat(Vector128 x, Vector128 y) + => Avx.CompareScalar(x, y, FloatComparisonMode.OrderedFalseSignaling); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 CompareFalseDouble(Vector128 x, Vector128 y) + => Avx.CompareScalar(x, y, FloatComparisonMode.OrderedFalseNonSignaling); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 CompareTrueFloat(Vector128 x, Vector128 y) + => Avx.CompareScalar(x, y, FloatComparisonMode.UnorderedTrueSignaling); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 CompareTrueDouble(Vector128 x, Vector128 y) + => Avx.CompareScalar(x, y, FloatComparisonMode.UnorderedTrueNonSignaling); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector512 CompareMaskFalseFloat(Vector512 x, Vector512 y) + => Avx512F.Compare(x, y, FloatComparisonMode.OrderedFalseSignaling); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector512 CompareMaskFalseDouble(Vector512 x, Vector512 y) + => Avx512F.Compare(x, y, FloatComparisonMode.OrderedFalseNonSignaling); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector512 CompareMaskTrueFloat(Vector512 x, Vector512 y) + => Avx512F.Compare(x, y, FloatComparisonMode.UnorderedTrueSignaling); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector512 CompareMaskTrueDouble(Vector512 x, Vector512 y) + => Avx512F.Compare(x, y, FloatComparisonMode.UnorderedTrueNonSignaling); +} diff --git a/src/tests/JIT/Regression/Regression_ro_2.csproj b/src/tests/JIT/Regression/Regression_ro_2.csproj index 9920332e7f1c0f..5c62eb98295716 100644 --- a/src/tests/JIT/Regression/Regression_ro_2.csproj +++ b/src/tests/JIT/Regression/Regression_ro_2.csproj @@ -89,6 +89,7 @@ +