diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 36def8fb42c917..a52d9743517467 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -9483,8 +9483,10 @@ GenTree* Compiler::fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node) break; } - // Must be working with the same types of vectors. - if (hwop1->TypeGet() != retType) + // Must have matching vector sizes and compatible element types. + // Signedness-only differences preserve the broadcast bits. + if ((hwop1->TypeGet() != retType) || + (varTypeToSigned(hwop1->GetSimdBaseType()) != varTypeToSigned(simdBaseType))) { break; } diff --git a/src/tests/JIT/Regression_ro_2/Runtime_134479.cs b/src/tests/JIT/Regression_ro_2/Runtime_134479.cs new file mode 100644 index 00000000000000..2071f0484bf163 --- /dev/null +++ b/src/tests/JIT/Regression_ro_2/Runtime_134479.cs @@ -0,0 +1,46 @@ +// 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 Xunit; + +public class Runtime_134479 +{ + [Theory] + [InlineData(1, 8, 8u)] + [InlineData(-1, -8, 65528u)] + [InlineData(32767, -8, 65528u)] + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void Widening128(int value, int expectedSigned, uint expectedUnsigned) + { + Vector128 signed = Vector128.Create((short)value); + Vector128 unsigned = signed.AsUInt16(); + Assert.Equal(Vector128.Create(expectedSigned), Vector128.Create((int)Vector128.Dot(signed, Vector128.One))); + Assert.Equal(Vector128.Create(expectedUnsigned), Vector128.Create((uint)Vector128.Dot(unsigned, Vector128.One))); + } + + [Theory] + [InlineData(1, 8, 8u)] + [InlineData(-1, -8, 248u)] + [InlineData(127, -8, 248u)] + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void Widening64(int value, int expectedSigned, uint expectedUnsigned) + { + Vector64 signed = Vector64.Create((sbyte)value); + Vector64 unsigned = signed.AsByte(); + Assert.Equal(Vector64.Create(expectedSigned), Vector64.Create((int)Vector64.Dot(signed, Vector64.One))); + Assert.Equal(Vector64.Create(expectedUnsigned), Vector64.Create((uint)Vector64.Dot(unsigned, Vector64.One))); + } + + [Theory] + [InlineData(1, 4, 4u)] + [InlineData(-1, -4, 4294967292u)] + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void CompatibleBroadcasts(int value, int expectedSigned, uint expectedUnsigned) + { + Vector128 vector = Vector128.Create(value); + Assert.Equal(Vector128.Create(expectedSigned), Vector128.Create(Vector128.Dot(vector, Vector128.One))); + Assert.Equal(Vector128.Create(expectedUnsigned), Vector128.Create(unchecked((uint)Vector128.Dot(vector, Vector128.One)))); + } +}