diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp
index 656b58ee84fbf7..c0558f14da54b2 100644
--- a/src/coreclr/jit/lower.cpp
+++ b/src/coreclr/jit/lower.cpp
@@ -4599,7 +4599,30 @@ GenTree* Lowering::OptimizeConstCompare(GenTree* cmp)
BlockRange().Remove(op2);
GenCondition cmpCondition = GenCondition::FromRelop(cmp);
- GenTreeCC* setcc = m_compiler->gtNewCC(GT_SETCC, cmp->TypeGet(), cmpCondition);
+
+ // For unsigned compares against zero that rely on flags-as-compare-to-zero,
+ // we cannot use UGT/UGE/ULT/ULE directly because op1 may set only NZ flags
+ // (e.g. ANDS on ARM64 clears C/V). UGT/ULT depend on carry, which would be wrong.
+ // Rewrite the condition to use Z/N where possible, or bail out.
+ if (cmp->IsUnsigned() && op2->IsIntegralConst(0) && cmp->OperIs(GT_GT, GT_GE, GT_LT, GT_LE))
+ {
+ if (cmp->OperIs(GT_GT))
+ {
+ // x > 0U <=> x != 0
+ cmpCondition = GenCondition::NE;
+ }
+ else if (cmp->OperIs(GT_LE))
+ {
+ // x <= 0U <=> x == 0
+ cmpCondition = GenCondition::EQ;
+ }
+ else
+ {
+ // x >= 0U is always true and x < 0U is always false; keep the compare for correctness.
+ return cmp;
+ }
+ }
+ GenTreeCC* setcc = m_compiler->gtNewCC(GT_SETCC, cmp->TypeGet(), cmpCondition);
BlockRange().InsertAfter(op1, setcc);
use.ReplaceWith(setcc);
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_124510/Runtime_124510.cs b/src/tests/JIT/Regression/JitBlue/Runtime_124510/Runtime_124510.cs
new file mode 100644
index 00000000000000..0986417aafb80b
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_124510/Runtime_124510.cs
@@ -0,0 +1,51 @@
+// Generated by Fuzzlyn v3.3 on 2026-02-15 16:52:57
+// Run on Arm64 Linux
+// Seed: 14599529654677333173-vectort,vector64,vector128,armadvsimd,armadvsimdarm64,armaes,armarmbase,armarmbasearm64,armcrc32,armcrc32arm64,armdp,armrdm,armrdmarm64,armsha1,armsha256,armsve,armsve2
+// Reduced from 73.3 KiB to 0.7 KiB in 00:00:52
+// Debug: Outputs 0
+// Release: Outputs 1
+public class C0
+{
+ public ulong F3;
+ public C0(ulong f3)
+ {
+ F3 = f3;
+ }
+}
+
+public class C1
+{
+ public byte F8;
+}
+
+public class C2
+{
+ public C0 F1;
+ public C1 F2;
+ public C2(C0 f1, C1 f2)
+ {
+ F1 = f1;
+ F2 = f2;
+ }
+}
+
+public struct S0
+{
+ public byte F0;
+}
+
+public class Program
+{
+ public static S0 s_1;
+ public static C2 s_2 = new C2(new C0(8013948595597981922UL), new C1());
+ public static void Main()
+ {
+ var vr1 = s_2.F1.F3;
+ if (((uint)(vr1 & 3080599622U) <= (ushort)(s_2.F2.F8 % 1)))
+ {
+ byte vr3 = s_1.F0++;
+ }
+
+ System.Console.WriteLine(s_1.F0);
+ }
+}
diff --git a/src/tests/JIT/Regression/Regression_ro_1.csproj b/src/tests/JIT/Regression/Regression_ro_1.csproj
index 7d7788d931a8d6..62bf725b3642ad 100644
--- a/src/tests/JIT/Regression/Regression_ro_1.csproj
+++ b/src/tests/JIT/Regression/Regression_ro_1.csproj
@@ -78,6 +78,7 @@
+
diff --git a/src/tests/JIT/opt/InstructionCombining/And.cs b/src/tests/JIT/opt/InstructionCombining/And.cs
index f794bc20624a92..e4f2742d7fc88e 100644
--- a/src/tests/JIT/opt/InstructionCombining/And.cs
+++ b/src/tests/JIT/opt/InstructionCombining/And.cs
@@ -125,6 +125,16 @@ public static int CheckAnd()
fail = true;
}
+ if (AndsUnsignedStaticBranchLe() != 0)
+ {
+ fail = true;
+ }
+
+ if (AndsUnsignedStaticBranchGt() == 0)
+ {
+ fail = true;
+ }
+
if (fail)
{
return 101;
@@ -288,29 +298,62 @@ static bool AndsBinOpSingleLine(uint a, uint b, uint c, uint d)
[MethodImpl(MethodImplOptions.NoInlining)]
static bool AndsGreaterThan(int a, int b)
{
- //ARM64-FULL-LINE: ands w0, {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: ands {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return (a & b) > 0;
}
[MethodImpl(MethodImplOptions.NoInlining)]
static bool AndsGreaterThanEq(int a, int b)
{
- //ARM64-FULL-LINE: ands w0, {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: ands {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return (a & b) >= 0;
}
[MethodImpl(MethodImplOptions.NoInlining)]
static bool AndsLessThan(int a, int b)
{
- //ARM64-FULL-LINE: ands w0, {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: ands {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return (a & b) < 0;
}
[MethodImpl(MethodImplOptions.NoInlining)]
static bool AndsLessThanEq(int a, int b)
{
- //ARM64-FULL-LINE: ands w0, {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: ands {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return (a & b) <= 0;
}
+
+ static ulong s_a = 8013948595597981922UL;
+ static byte s_b = 0;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int AndsUnsignedStaticBranchLe()
+ {
+ //ARM64-FULL-LINE: ands {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: cset {{x[0-9]+}}, eq
+ uint left = (uint)(s_a & 0xB79E3846u);
+ uint right = (ushort)(s_b % 1);
+
+ if (left <= right)
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int AndsUnsignedStaticBranchGt()
+ {
+ //ARM64-FULL-LINE: tst {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: cset {{x[0-9]+}}, ne
+ uint left = (uint)(s_a & 0xB79E3846u);
+ uint right = (ushort)(s_b % 1);
+
+ if (left > right)
+ {
+ return 1;
+ }
+ return 0;
+ }
}
}
diff --git a/src/tests/JIT/opt/InstructionCombining/Bic.cs b/src/tests/JIT/opt/InstructionCombining/Bic.cs
index 419981104094aa..4e817c73652e73 100644
--- a/src/tests/JIT/opt/InstructionCombining/Bic.cs
+++ b/src/tests/JIT/opt/InstructionCombining/Bic.cs
@@ -115,6 +115,16 @@ public static int CheckBic()
fail = true;
}
+ if (BicsUnsignedStaticBranchLe() != 0)
+ {
+ fail = true;
+ }
+
+ if (BicsUnsignedStaticBranchGt() == 0)
+ {
+ fail = true;
+ }
+
if (fail)
{
return 101;
@@ -316,5 +326,38 @@ static bool BicsLessThanEq(int a, int b)
//ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return (a & ~b) <= 0;
}
+
+ static uint s_a = 0xFFFFFFFFu;
+ static uint s_b = 0x12345678u;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int BicsUnsignedStaticBranchLe()
+ {
+ //ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: cset {{x[0-9]+}}, eq
+ uint left = s_a & ~s_b;
+ uint right = (ushort)(s_b % 1);
+
+ if (left <= right)
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int BicsUnsignedStaticBranchGt()
+ {
+ //ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
+ //ARM64-FULL-LINE: cset {{x[0-9]+}}, ne
+ uint left = s_a & ~s_b;
+ uint right = (ushort)(s_b % 1);
+
+ if (left > right)
+ {
+ return 1;
+ }
+ return 0;
+ }
}
}