diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 65efdbf479e06f..53ebf9ad82ef55 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -11434,6 +11434,28 @@ void Lowering::LowerStoreCoalescing(GenTree* node) assert(newType != TYP_UNDEF); + // Validate the constants before removing the previous store or widening the current one. + uint64_t lowerCns = 0; + uint64_t upperCns = 0; +#if defined(TARGET_AMD64) && defined(FEATURE_HW_INTRINSICS) + // Only on x64 since ARM64 has no options above SIMD16. + if (varTypeIsSIMD(oldType)) + { + if (!prevData.value->OperIs(GT_CNS_VEC) || !currData.value->OperIs(GT_CNS_VEC)) + { + return; + } + } + else +#endif // TARGET_AMD64 && FEATURE_HW_INTRINSICS + { + if (!TryGetStoreCoalescingConstantBits(prevData.value, &lowerCns) || + !TryGetStoreCoalescingConstantBits(currData.value, &upperCns)) + { + return; + } + } + if (node->OperIs(GT_STOREIND, GT_STORE_BLK)) { auto* ind = node->AsStoreInd(); @@ -11487,11 +11509,6 @@ void Lowering::LowerStoreCoalescing(GenTree* node) // Only on x64 since ARM64 has no options above SIMD16. if (varTypeIsSIMD(oldType)) { - if (!prevData.value->OperIs(GT_CNS_VEC) || !currData.value->OperIs(GT_CNS_VEC)) - { - return; - } - int8_t* lowerCns = prevData.value->AsVecCon()->gtSimdVal.i8; int8_t* upperCns = currData.value->AsVecCon()->gtSimdVal.i8; @@ -11512,14 +11529,6 @@ void Lowering::LowerStoreCoalescing(GenTree* node) // The integer path below places each constant according to its byte offset, so it doesn't need to swap the // values first. Only the SIMD packing paths above need to normalize lower/upper order explicitly. - uint64_t lowerCns = 0; - uint64_t upperCns = 0; - if (!TryGetStoreCoalescingConstantBits(prevData.value, &lowerCns) || - !TryGetStoreCoalescingConstantBits(currData.value, &upperCns)) - { - return; - } - #if defined(TARGET_64BIT) && defined(FEATURE_HW_INTRINSICS) if (varTypeIsSIMD(newType)) { diff --git a/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746.cs b/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746.cs new file mode 100644 index 00000000000000..fcbd7db88eee35 --- /dev/null +++ b/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746.cs @@ -0,0 +1,49 @@ +// 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.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using Xunit; + +public class Runtime_133746 +{ + [Fact] + [SkipLocalsInit] + public static void TestEntryPoint() + { + Vector2 pair = new Vector2(1.0f, -2.0f); + Unsafe.As(ref pair) = -1; + ValidatePair(in pair); + + Validate(Vector64.CreateScalar((sbyte)-1), (sbyte)-1); + Validate(Vector64.CreateScalar(sbyte.MinValue), sbyte.MinValue); + Validate(Vector64.CreateScalar(sbyte.MaxValue), sbyte.MaxValue); + Validate(Vector64.CreateScalar((short)-1), (short)-1); + Validate(Vector64.CreateScalar(short.MinValue), short.MinValue); + Validate(Vector64.CreateScalar(short.MaxValue), short.MaxValue); + Validate(Vector64.CreateScalar(-1), -1); + Validate(Vector64.CreateScalar(int.MinValue), int.MinValue); + Validate(Vector64.CreateScalar(int.MaxValue), int.MaxValue); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void ValidatePair(in Vector2 value) + { + int expected = BitConverter.IsLittleEndian ? 0x3F8000FF : unchecked((int)0xFF800000); + Assert.Equal(expected, BitConverter.SingleToInt32Bits(value.X)); + Assert.Equal(-2.0f, value.Y); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Validate(in Vector64 value, T expected) where T : struct + { + Assert.Equal(expected, value.GetElement(0)); + + for (int i = 1; i < Vector64.Count; i++) + { + Assert.Equal(default(T), value.GetElement(i)); + } + } +} diff --git a/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746.csproj b/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746.csproj new file mode 100644 index 00000000000000..1f27ad399707ce --- /dev/null +++ b/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746.csproj @@ -0,0 +1,12 @@ + + + True + True + 1 + true + + + + + + diff --git a/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746_nohw.csproj b/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746_nohw.csproj new file mode 100644 index 00000000000000..3c7768cefd8423 --- /dev/null +++ b/src/tests/JIT/Regression_2/Runtime_133746/Runtime_133746_nohw.csproj @@ -0,0 +1,6 @@ + + + + + +