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