diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h index bc15e74f956cf7..73a327742b5438 100644 --- a/src/coreclr/jit/simd.h +++ b/src/coreclr/jit/simd.h @@ -1976,49 +1976,59 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) uint64_t mask; memcpy(&mask, &arg0.u8[0], sizeof(uint64_t)); - uint32_t finalOne = count; + uint32_t firstZero = count; - // A mask pattern starts with zero of more 1s and then the rest of the mask is filled with 0s. + constexpr uint64_t laneMask = (sizeof(TBase) == 8) ? ~0ull : ((1ull << sizeof(TBase)) - 1ull); + + // A mask is a vector of unsigned integers, where 1 indicates the lane is set, 0 is not set, + // and all other values are undefined. + // For a valid mask pattern: + // * Each element of size TBase contains 0 or 1 in the lowest bit, and no other bits set. + // * The sequence starts with zero or more 1s and then the rest of the mask is filled with 0s. // Find an unbroken sequence of 1s. for (uint32_t i = 0; i < count; i++) { - // For Arm64 we have count total bits to read, but - // they are sizeof(TBase) bits apart. We set - // the result element to AllBitsSet or Zero depending - // on the corresponding mask bit + const uint64_t lane = (mask >> static_cast(i * sizeof(TBase))); + TBase elem = (TBase)(lane & laneMask); - bool isSet = ((mask >> (i * sizeof(TBase))) & 1) != 0; - if (!isSet) + if (elem == 0) { - finalOne = i; + // Found the first zero + firstZero = i; break; } + else if (elem != 1) + { + // Other bits are set. Invalid sequence + return SveMaskPatternNone; + } + // else just bit 1 in elem was set } // Find an unbroken sequence of 0s. - for (uint32_t i = finalOne; i < count; i++) + for (uint32_t i = firstZero; i < count; i++) { - // For Arm64 we have count total bits to read, but - // they are sizeof(TBase) bits apart. We set - // the result element to AllBitsSet or Zero depending - // on the corresponding mask bit + const uint64_t lane = (mask >> static_cast(i * sizeof(TBase))); + TBase elem = (TBase)(lane & laneMask); - bool isSet = ((mask >> (i * sizeof(TBase))) & 1) != 0; - if (isSet) + if (elem != 0) { - // Invalid sequence + // Either a 1 or other bits are set. Invalid sequence return SveMaskPatternNone; } } - if (finalOne == count) + assert(firstZero <= count); + + if (firstZero == count) { + // No zeros in the pattern return SveMaskPatternAll; } - else if (finalOne >= SveMaskPatternVectorCount1 && finalOne <= SveMaskPatternVectorCount8) + else if (firstZero >= SveMaskPatternVectorCount1 && firstZero <= SveMaskPatternVectorCount8) { - return (SveMaskPattern)finalOne; + return (SveMaskPattern)firstZero; } else { diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs new file mode 100644 index 00000000000000..7934aee80e8285 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs @@ -0,0 +1,38 @@ +// Generated by Fuzzlyn v3.3 on 2026-02-15 17:21:42 +// Run on Arm64 Linux +// Seed: 103488890012433678-vectort,vector64,vector128,armadvsimd,armadvsimdarm64,armaes,armarmbase,armarmbasearm64,armcrc32,armcrc32arm64,armdp,armrdm,armrdmarm64,armsha1,armsha256,armsve,armsve2 +// Reduced from 29.2 KiB to 0.7 KiB in 00:00:16 +// Debug: Outputs -3 +// Release: Outputs -2 + +namespace Runtime_124511; + +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +public unsafe class Runtime_124511 +{ + [ConditionalFact(typeof(Sve), nameof(Sve.IsSupported))] + public static void TestEntryPoint() + { + Assert.True(MainTest() == -3); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static sbyte MainTest() + { + var vr8 = Vector.Create(1); + var vr9 = Vector128.CreateScalar(4701966028735610216UL).AsVector(); + var vr10 = Sve.ShiftLeftLogical(vr8, vr9); + var vr11 = Vector128.CreateScalar(2U).AsVector(); + var vr12 = Sve.Subtract(vr10, vr11); + var vr13 = Vector.Create(1); + var vr14 = Vector128.CreateScalar(0U).AsVector(); + var vr15 = Sve.CreateBreakBeforePropagateMask(vr12, vr13, vr14); + sbyte vr16 = (sbyte)Sve.SaturatingDecrementByActiveElementCount(0, vr15); + return vr16; + } +} diff --git a/src/tests/JIT/Regression/Regression_ro_1.csproj b/src/tests/JIT/Regression/Regression_ro_1.csproj index 7d7788d931a8d6..08ae8ebdc8c460 100644 --- a/src/tests/JIT/Regression/Regression_ro_1.csproj +++ b/src/tests/JIT/Regression/Regression_ro_1.csproj @@ -78,6 +78,7 @@ +