diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
index df8cc0111a7f25..107705fa5e5729 100644
--- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
+++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
@@ -1425,7 +1425,6 @@ void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node)
}
else
{
- assert(op1->TypeGet() == op2->TypeGet());
assert((targetType == TYP_INT) || (targetType == TYP_LONG));
genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(targetType), targetReg, op2);
}
diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h
index 46e1accf726cb3..b8b5686133efc2 100644
--- a/src/coreclr/jit/lower.h
+++ b/src/coreclr/jit/lower.h
@@ -377,17 +377,36 @@ class Lowering final : public Phase
// Otherwise, it returns the underlying operation that was being casted
GenTree* TryRemoveCastIfPresent(var_types expectedType, GenTree* op)
{
- if (!op->OperIs(GT_CAST))
+ if (!op->OperIs(GT_CAST) || !comp->opts.OptimizationEnabled())
{
return op;
}
- GenTree* castOp = op->AsCast()->CastOp();
+ GenTreeCast* cast = op->AsCast();
- if (genTypeSize(castOp->gtType) >= genTypeSize(expectedType))
+ // FP <-> INT casts should be kept
+ if (varTypeIsFloating(cast->CastFromType()) ^ varTypeIsFloating(expectedType))
{
+ return op;
+ }
+
+ // Keep casts which can overflow
+ if (cast->gtOverflow())
+ {
+ return op;
+ }
+
+ if (genTypeSize(cast->CastToType()) >= genTypeSize(expectedType))
+ {
+#ifndef TARGET_64BIT
+ // Don't expose TYP_LONG on 32bit
+ if (varTypeIsLong(cast->CastFromType()))
+ {
+ return op;
+ }
+#endif
BlockRange().Remove(op);
- return castOp;
+ return cast->CastOp();
}
return op;
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692.cs b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692.cs
new file mode 100644
index 00000000000000..aec577db661866
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+using System;
+using System.Runtime.Intrinsics.X86;
+
+public unsafe class Runtime_62692
+{
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static uint Problem1(byte* pSrc, uint data) => Sse42.Crc32(*pSrc, data);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static uint Problem2(uint crc, ulong data) => Sse42.Crc32(crc, (uint)(data >> 16));
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static uint Problem3(uint crc, uint data) => Sse42.Crc32(crc, (uint)(byte)data);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static uint Problem4(uint crc, ulong data) => Sse42.Crc32(crc, (uint)(data >> 16));
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static uint Problem5(uint crc, double data) => Sse42.Crc32(crc, (uint)data);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static uint Problem6(uint crc, float data) => Sse42.Crc32(crc, (uint)data);
+
+ static int Main()
+ {
+ if (Sse42.IsSupported)
+ {
+ long a = long.MaxValue;
+ AssertEqual(Problem1((byte*)&a, 111), 3150215170);
+ a = 333;
+ AssertEqual(Problem1((byte*)&a, 44), 2714165716);
+ AssertEqual(Problem2(uint.MaxValue, 42), 3080238136);
+ AssertEqual(Problem2(1111, 0xFFFF_FFFF_0000_0001), 3414328792);
+ AssertEqual(Problem3(1, 0xFFFF_0001), 0);
+ AssertEqual(Problem4(1111, 0xFFFF_FFFF_0000_0001), 3414328792);
+ AssertEqual(Problem5(1111, double.MaxValue), 3307008522);
+ AssertEqual(Problem6(1111, float.MaxValue), 3307008522);
+ AssertEqual(Problem5(1111, double.MinValue), 3307008522);
+ AssertEqual(Problem6(1111, float.MinValue), 3307008522);
+ AssertEqual(Problem5(1111, -0.0), 3307008522);
+ AssertEqual(Problem6(1111, -0.0f), 3307008522);
+ }
+
+ Console.WriteLine(retCode);
+ return retCode;
+ }
+
+ static int retCode = 100;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void AssertEqual(uint a, uint b, [CallerLineNumber] int line = 0)
+ {
+ if (a != b)
+ {
+ Console.WriteLine($"{a} != {b}, Line:{line}");
+ retCode++;
+ }
+ }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_r.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_r.csproj
new file mode 100644
index 00000000000000..cff31f0439e03e
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_r.csproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ False
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_ro.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_ro.csproj
new file mode 100644
index 00000000000000..83ea5c091b8795
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_ro.csproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ True
+ True
+
+
+
+
+
\ No newline at end of file