diff --git a/src/coreclr/jit/rangecheck.h b/src/coreclr/jit/rangecheck.h index 9a56b80703154e..92886073a2c7bf 100644 --- a/src/coreclr/jit/rangecheck.h +++ b/src/coreclr/jit/rangecheck.h @@ -356,15 +356,28 @@ struct RangeOps static Range Multiply(const Range& r1, const Range& r2) { - return ApplyRangeOp(r1, r2, [](const Limit& a, const Limit& b) { - // For Mul we require both operands to be constant to produce a constant result. - if (b.IsConstant() && a.IsConstant() && - !CheckedOps::MulOverflows(a.GetConstant(), b.GetConstant(), CheckedOps::Signed)) - { - return Limit(Limit::keConstant, a.GetConstant() * b.GetConstant()); - } + if (!r1.IsConstantRange() || !r2.IsConstantRange()) + { return Limit(Limit::keUnknown); - }); + } + + int r1lo = r1.LowerLimit().GetConstant(); + int r1hi = r1.UpperLimit().GetConstant(); + int r2lo = r2.LowerLimit().GetConstant(); + int r2hi = r2.UpperLimit().GetConstant(); + + if (CheckedOps::MulOverflows(r1lo, r2lo, CheckedOps::Signed) || + CheckedOps::MulOverflows(r1lo, r2hi, CheckedOps::Signed) || + CheckedOps::MulOverflows(r1hi, r2lo, CheckedOps::Signed) || + CheckedOps::MulOverflows(r1hi, r2hi, CheckedOps::Signed)) + { + return Limit(Limit::keUnknown); + } + + int lo = min(min(r1lo * r2lo, r1lo * r2hi), min(r1hi * r2lo, r1hi * r2hi)); + int hi = max(max(r1lo * r2lo, r1lo * r2hi), max(r1hi * r2lo, r1hi * r2hi)); + assert(hi >= lo); + return Range(Limit(Limit::keConstant, lo), Limit(Limit::keConstant, hi)); } static Range ShiftRight(const Range& r1, const Range& r2, bool logical) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_124082/Runtime_124082.cs b/src/tests/JIT/Regression/JitBlue/Runtime_124082/Runtime_124082.cs new file mode 100644 index 00000000000000..b27fd8588c7461 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_124082/Runtime_124082.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v3.3 on 2026-02-05 22:00:13 +// Run on X64 Windows +// Seed: 3325744140221827777-vectort,vector128,vector256,x86aes,x86avx,x86avx2,x86avx512bw,x86avx512bwvl,x86avx512cd,x86avx512cdvl,x86avx512dq,x86avx512dqvl,x86avx512f,x86avx512fvl,x86avx512fx64,x86bmi1,x86bmi1x64,x86bmi2,x86bmi2x64,x86fma,x86lzcnt,x86lzcntx64,x86pclmulqdq,x86popcnt,x86popcntx64,x86sse,x86ssex64,x86sse2,x86sse2x64,x86sse3,x86sse41,x86sse41x64,x86sse42,x86sse42x64,x86ssse3,x86x86base +// Reduced from 64.4 KiB to 0.3 KiB in 00:01:42 +// Debug: Outputs -1 +// Release: Outputs 4294967295 + +using System; +using Xunit; + +public class Runtime_124082 +{ + public static sbyte s_4 = 1; + public static byte[][] s_12 = new byte[][] + { + new byte[] + { + 1 + } + }; + + [Fact] + public static void TestEntryPoint() + { + byte[] vr9 = s_12[0]; + long vr10 = (ushort)s_4 * (sbyte)(-s_4); + Assert.Equal(-1L, vr10); + } +}