diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 0aa3dda05359a7..4eb1dff521bd81 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -2766,7 +2766,23 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, if (setMethodHandle && (retNode != nullptr)) { - retNode->AsHWIntrinsic()->SetMethodHandle(this, method R2RARG(*entryPoint)); + GenTree* userCall = retNode; + +#if defined(TARGET_XARCH) + if (userCall->OperIsConvertMaskToVector()) + { + // A mask-producing intrinsic was wrapped in a mask-to-vector conversion, but the user call + // replaces the inner node, so attach the handle there to keep its operands. ConvertMaskToVector + // is always unary, so its sole operand is the mask node being tagged. + GenTreeHWIntrinsic* cvtMaskToVector = userCall->AsHWIntrinsic(); + assert(cvtMaskToVector->GetOperandCount() == 1); + + userCall = cvtMaskToVector->Op(1); + assert(userCall->TypeIs(TYP_MASK)); + } +#endif // TARGET_XARCH + + userCall->AsHWIntrinsic()->SetMethodHandle(this, method R2RARG(*entryPoint)); } #if defined(FEATURE_MASKED_HW_INTRINSICS) && defined(TARGET_ARM64) diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_131472/GitHub_131472.cs b/src/tests/JIT/Regression/JitBlue/GitHub_131472/GitHub_131472.cs new file mode 100644 index 00000000000000..ccd86b63562d70 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/GitHub_131472/GitHub_131472.cs @@ -0,0 +1,51 @@ +// 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 System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +public class GitHub_131472 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + private static FloatComparisonMode Opaque(FloatComparisonMode value) => value; + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static Vector256 Compare(Vector256 l, Vector256 r, FloatComparisonMode m) => Avx.Compare(l, r, m); + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + private static Vector256 Reference(Vector256 l, Vector256 r, FloatComparisonMode m) => Avx.Compare(l, r, m); + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static Vector512 Compare(Vector512 l, Vector512 r, FloatComparisonMode m) => Avx512F.Compare(l, r, m); + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + private static Vector512 Reference(Vector512 l, Vector512 r, FloatComparisonMode m) => Avx512F.Compare(l, r, m); + + [Fact] + public static void TestEntryPoint() + { + // A non-constant mode must expand without leaving right/mode uninitialized when Compare is + // promoted to its mask-returning form. Vector256 exercises the optional EVEX promotion; + // Vector512 exercises the mandatory-mask path. + for (int i = 0; i <= (int)FloatComparisonMode.UnorderedTrueSignaling; i++) + { + FloatComparisonMode mode = Opaque((FloatComparisonMode)i); + + if (Avx.IsSupported) + { + Vector256 l = Vector256.Create(1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f); + Vector256 r = Vector256.Create(8f, 2f, 6f, 4f, 4f, 6f, 2f, 8f); + Assert.Equal(Reference(l, r, mode), Compare(l, r, mode)); + } + + if (Avx512F.IsSupported) + { + Vector512 l = Vector512.Create(1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f, 10f, 11f, 12f, 13f, 14f, 15f, 16f); + Vector512 r = Vector512.Create(8f, 2f, 6f, 4f, 4f, 6f, 2f, 8f, 16f, 10f, 12f, 12f, 12f, 14f, 10f, 16f); + Assert.Equal(Reference(l, r, mode), Compare(l, r, mode)); + } + } + } +} diff --git a/src/tests/JIT/Regression/Regression_ro_2.csproj b/src/tests/JIT/Regression/Regression_ro_2.csproj index 9c69e5397bb479..1ed19e58c238b3 100644 --- a/src/tests/JIT/Regression/Regression_ro_2.csproj +++ b/src/tests/JIT/Regression/Regression_ro_2.csproj @@ -122,6 +122,7 @@ +