From 99cf54df5a011a1dad9367c2d31525d0d2525d59 Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Thu, 19 Feb 2026 13:32:11 +0000 Subject: [PATCH 1/7] Less optimistic checks for const vector to pattern checks Fixes #124511 When checking a element of TBase size, ensure that no other bits other than the first bit are set --- src/coreclr/jit/simd.h | 50 +++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h index bc15e74f956cf7..3270fa4af666ec 100644 --- a/src/coreclr/jit/simd.h +++ b/src/coreclr/jit/simd.h @@ -1976,49 +1976,55 @@ 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. + uint64_t allTBaseBits = ((uint64_t)1 << sizeof(TBase)) - (uint64_t)1; + + // 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 - - bool isSet = ((mask >> (i * sizeof(TBase))) & 1) != 0; - if (!isSet) + TBase elem = ((mask >> (i * sizeof(TBase))) & allTBaseBits); + 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 - - bool isSet = ((mask >> (i * sizeof(TBase))) & 1) != 0; - if (isSet) + TBase elem = ((mask >> (i * sizeof(TBase))) & allTBaseBits); + 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 { From 99725a798892abc7997d6dbe32a0546d7f1da976 Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Thu, 19 Feb 2026 14:57:40 +0000 Subject: [PATCH 2/7] Add test --- .../JitBlue/Runtime_124511/Runtime_124511.cs | 38 +++++++++++++++++++ .../Runtime_124511/Runtime_124511.csproj | 12 ++++++ 2 files changed, 50 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj 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..c5d5e15cba665c --- /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_105944 +{ + [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/JitBlue/Runtime_124511/Runtime_124511.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj new file mode 100644 index 00000000000000..5d107ffa5e2f80 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj @@ -0,0 +1,12 @@ + + + True + + true + + + + + + + From 88f741cc821a7d449f573aaded4b0e728bd10200 Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Thu, 19 Feb 2026 15:30:04 +0000 Subject: [PATCH 3/7] Remove RequiresProcessIsolation --- .../JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj index 5d107ffa5e2f80..8db03c90e9421b 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj @@ -1,8 +1,6 @@ True - - true From a353a5bdc70b3452d00cc2cc27f84d548394877f Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Thu, 19 Feb 2026 16:22:56 +0000 Subject: [PATCH 4/7] Remove csproj file --- .../JitBlue/Runtime_124511/Runtime_124511.cs | 2 +- .../JitBlue/Runtime_124511/Runtime_124511.csproj | 10 ---------- src/tests/JIT/Regression/Regression_ro_1.csproj | 1 + 3 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs index c5d5e15cba665c..7934aee80e8285 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.cs @@ -13,7 +13,7 @@ namespace Runtime_124511; using System.Runtime.Intrinsics.Arm; using Xunit; -public unsafe class Runtime_105944 +public unsafe class Runtime_124511 { [ConditionalFact(typeof(Sve), nameof(Sve.IsSupported))] public static void TestEntryPoint() diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj deleted file mode 100644 index 8db03c90e9421b..00000000000000 --- a/src/tests/JIT/Regression/JitBlue/Runtime_124511/Runtime_124511.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - True - - - - - - - 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 @@ + From 97b47ceafdbaa6332be7590e14149ea78785c7df Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Thu, 19 Feb 2026 17:06:32 +0000 Subject: [PATCH 5/7] Add cast --- src/coreclr/jit/simd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h index 3270fa4af666ec..50fa15da14f2a6 100644 --- a/src/coreclr/jit/simd.h +++ b/src/coreclr/jit/simd.h @@ -1989,7 +1989,7 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) // Find an unbroken sequence of 1s. for (uint32_t i = 0; i < count; i++) { - TBase elem = ((mask >> (i * sizeof(TBase))) & allTBaseBits); + TBase elem = (TBase)((mask >> (i * sizeof(TBase))) & allTBaseBits); if (elem == 0) { // Found the first zero @@ -2007,7 +2007,7 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) // Find an unbroken sequence of 0s. for (uint32_t i = firstZero; i < count; i++) { - TBase elem = ((mask >> (i * sizeof(TBase))) & allTBaseBits); + TBase elem = (TBase)((mask >> (i * sizeof(TBase))) & allTBaseBits); if (elem != 0) { // Either a 1 or other bits are set. Invalid sequence From be9df5fe5d8d10a642a07477ef84e95c52f34002 Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Thu, 19 Feb 2026 17:54:14 +0000 Subject: [PATCH 6/7] Explicit casting for windows --- src/coreclr/jit/simd.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h index 50fa15da14f2a6..f325e986503acb 100644 --- a/src/coreclr/jit/simd.h +++ b/src/coreclr/jit/simd.h @@ -1978,7 +1978,7 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) memcpy(&mask, &arg0.u8[0], sizeof(uint64_t)); uint32_t firstZero = count; - uint64_t allTBaseBits = ((uint64_t)1 << sizeof(TBase)) - (uint64_t)1; + 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. @@ -1989,7 +1989,9 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) // Find an unbroken sequence of 1s. for (uint32_t i = 0; i < count; i++) { - TBase elem = (TBase)((mask >> (i * sizeof(TBase))) & allTBaseBits); + const uint64_t lane = (mask >> static_cast(i * sizeof(TBase))); + TBase elem = (TBase)(lane & laneMask); + if (elem == 0) { // Found the first zero @@ -2007,7 +2009,9 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) // Find an unbroken sequence of 0s. for (uint32_t i = firstZero; i < count; i++) { - TBase elem = (TBase)((mask >> (i * sizeof(TBase))) & allTBaseBits); + const uint64_t lane = (mask >> static_cast(i * sizeof(TBase))); + TBase elem = (TBase)(lane & laneMask); + if (elem != 0) { // Either a 1 or other bits are set. Invalid sequence From b7654b1d59e0b9be901daf0cdbc3877c6bdb79ca Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Fri, 20 Feb 2026 09:55:54 +0000 Subject: [PATCH 7/7] formatting --- src/coreclr/jit/simd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h index f325e986503acb..73a327742b5438 100644 --- a/src/coreclr/jit/simd.h +++ b/src/coreclr/jit/simd.h @@ -1990,7 +1990,7 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) for (uint32_t i = 0; i < count; i++) { const uint64_t lane = (mask >> static_cast(i * sizeof(TBase))); - TBase elem = (TBase)(lane & laneMask); + TBase elem = (TBase)(lane & laneMask); if (elem == 0) { @@ -2010,7 +2010,7 @@ SveMaskPattern EvaluateSimdMaskToPattern(simdmask_t arg0) for (uint32_t i = firstZero; i < count; i++) { const uint64_t lane = (mask >> static_cast(i * sizeof(TBase))); - TBase elem = (TBase)(lane & laneMask); + TBase elem = (TBase)(lane & laneMask); if (elem != 0) {