From 670fd943d0afa6b26bede7301f87aa034fe580ad Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Fri, 23 Jan 2026 10:51:46 +0000 Subject: [PATCH 1/3] arm64: Remove widening casts before truncating --- src/coreclr/jit/morph.cpp | 13 + .../CoreCLRTestLibrary.csproj | 1 + src/tests/Common/CoreCLRTestLibrary/Expect.cs | 41 ++ .../JIT/opt/InstructionCombining/Casts.cs | 540 ++++++++++++++++++ .../JIT/opt/InstructionCombining/Casts.csproj | 18 + 5 files changed, 613 insertions(+) create mode 100644 src/tests/Common/CoreCLRTestLibrary/Expect.cs create mode 100644 src/tests/JIT/opt/InstructionCombining/Casts.cs create mode 100644 src/tests/JIT/opt/InstructionCombining/Casts.csproj diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 49d5435162f191..8ee60770a8199b 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8640,6 +8640,19 @@ GenTree* Compiler::fgOptimizeCast(GenTreeCast* cast) var_types castToType = cast->CastToType(); + // For small-int casts fed by a widening int->long, remove the widening so we truncate directly + // from the original int value. + if (varTypeIsSmall(castToType) && src->OperIs(GT_CAST) && !src->gtOverflow()) + { + GenTreeCast* widening = src->AsCast(); + if (varTypeIsLong(widening->CastToType()) && (genActualType(widening->CastFromType()) == TYP_INT)) + { + cast->CastOp() = widening->CastOp(); + DEBUG_DESTROY_NODE(widening); + src = cast->CastOp(); + } + } + // For indir-like nodes, we may be able to change their type to satisfy (and discard) the cast. if (varTypeIsSmall(castToType) && (genTypeSize(castToType) == genTypeSize(src)) && src->OperIs(GT_IND, GT_LCL_FLD)) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj b/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj index 6bbebee74d7177..915e6b1ff1c632 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj +++ b/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/Common/CoreCLRTestLibrary/Expect.cs b/src/tests/Common/CoreCLRTestLibrary/Expect.cs new file mode 100644 index 00000000000000..1fed85cb6b51a1 --- /dev/null +++ b/src/tests/Common/CoreCLRTestLibrary/Expect.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Linq.Expressions; +using Xunit; + +namespace TestLibrary; + +public static class Expect +{ + public static void ExpectEqual(Expression> expr, T expected, ref bool fail) + { + var compiled = expr.Compile(); + T actual = compiled(); + + // Get just the expression body text + string exprText = expr.Body.ToString(); + + if (!Equals(actual, expected)) + { + Console.WriteLine($"{exprText} = {actual}, expected {expected}"); + fail = true; + } + } + + public static void ExpectTrue(Expression> expr, ref bool fail) + { + var compiled = expr.Compile(); + bool actual = compiled(); + + // Get just the expression body text + string exprText = expr.Body.ToString(); + + if (!actual) + { + Console.WriteLine($"{exprText} = {actual}, expected True"); + fail = true; + } + } +} diff --git a/src/tests/JIT/opt/InstructionCombining/Casts.cs b/src/tests/JIT/opt/InstructionCombining/Casts.cs new file mode 100644 index 00000000000000..4212ac4d57f49b --- /dev/null +++ b/src/tests/JIT/opt/InstructionCombining/Casts.cs @@ -0,0 +1,540 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using static TestLibrary.Expect; +using Xunit; + +namespace TestMultipleCasts +{ + public class Program + { + [MethodImpl(MethodImplOptions.NoInlining)] + [Fact] + public static int CheckMultipleCasts() + { + bool fail = false; + + // Cast int -> x + ExpectEqual(() => CastIntSbyte(0x11223344), 0x44, ref fail); + ExpectEqual(() => CastIntShort(-0x11223344), -0x3344, ref fail); + ExpectEqual(() => CastIntLong(0x11223344), 0x11223344, ref fail); + + // Cast long -> x + ExpectEqual(() => CastLongSbyte(0xFFEEDDCCBBAAL), -0x56, ref fail); + ExpectEqual(() => CastLongShort(0xFFEEDDCCBBAAL), -0x4456, ref fail); + ExpectEqual(() => CastLongInt(0xFFEEDDCCBBAAL), -0x22334456, ref fail); + + // Cast uint -> x + ExpectEqual(() => CastUIntByte(0x11223344u), 0x44, ref fail); + ExpectEqual(() => CastUIntUShort(0x11223344u), 0x3344, ref fail); + ExpectEqual(() => CastUIntULong(0x11223344u), 0x11223344ul, ref fail); + + // Cast ulong -> x + ExpectEqual(() => CastULongByte(0xFFEEDDCCBBAAul), 0xAA, ref fail); + ExpectEqual(() => CastULongUShort(0xFFEEDDCCBBAAul), 0xBBAA, ref fail); + ExpectEqual(() => CastULongUInt(0xFFEEDDCCBBAAul), 0xDDCCBBAAu, ref fail); + + // Cast int -> x -> int + ExpectEqual(() => CastIntSbyteInt(0xF0), -0x10, ref fail); + ExpectEqual(() => CastIntShortInt(0xFF8001), -0x7FFF, ref fail); + ExpectEqual(() => CastIntLongInt(0x11223344), 0x11223344, ref fail); + + // Cast int -> x -> long + ExpectEqual(() => CastIntSbyteLong(0x12345678), 0x78, ref fail); + ExpectEqual(() => CastIntShortLong(0x12345678), 0x5678, ref fail); + + // Cast long -> x -> int + ExpectEqual(() => CastLongSbyteInt(0xA7L), -0x59, ref fail); + ExpectEqual(() => CastLongShortInt(0xFFFFFFFF8003L), -0x7FFD, ref fail); + + // Cast long -> x -> long + ExpectEqual(() => CastLongSbyteLong(0xFEL), -0x2L, ref fail); + ExpectEqual(() => CastLongShortLong(0xDEADL), -0x2153L, ref fail); + ExpectEqual(() => CastLongIntLong(0x1ABCDEF00L), -0x54321100L, ref fail); + + // Cast uint -> x -> uint + ExpectEqual(() => CastUIntByteUInt(0xF0u), 0xF0u, ref fail); + ExpectEqual(() => CastUIntUShortUInt(0xFF8001u), 0x8001u, ref fail); + + // Cast uint -> x -> ulong + ExpectEqual(() => CastUIntByteULong(0x12345678u), 0x78ul, ref fail); + ExpectEqual(() => CastUIntUShortULong(0x12345678u), 0x5678ul, ref fail); + ExpectEqual(() => CastUIntULongUInt(0x11223344u), 0x11223344u, ref fail); + + // Cast ulong -> x -> uint + ExpectEqual(() => CastULongByteUInt(0xA7ul), 0xA7u, ref fail); + ExpectEqual(() => CastULongUShortUInt(0xFFFFFFFF8003ul), 0x8003u, ref fail); + + // Cast ulong -> x -> ulong + ExpectEqual(() => CastULongByteULong(0xFEul), 0xFEul, ref fail); + ExpectEqual(() => CastULongUShortULong(0xDEADul), 0xDEADul, ref fail); + ExpectEqual(() => CastULongUIntULong(0x1ABCDEF00ul), 0xABCDEF00ul, ref fail); + + // Cast int -> long -> x + ExpectEqual(() => CastIntLongSbyte(0x11223344), 0x44, ref fail); + ExpectEqual(() => CastIntLongShort(0x11223344), 0x3344, ref fail); + + // Cast uint -> ulong -> x + ExpectEqual(() => CastUIntULongByte(0x11223344u), 0x44, ref fail); + ExpectEqual(() => CastUIntULongUShort(0x11223344u), 0x3344, ref fail); + + // Cast long -> int -> short -> sbyte + ExpectEqual(() => CastLongIntShortSByte(0x11223344), 0x44, ref fail); + + // Cast ulong -> uint -> ushort -> byte + ExpectEqual(() => CastULongUIntUShortByte(0x11223344u), 0x44, ref fail); + + // Cast sbyte -> short -> int -> long + ExpectEqual(() => CastSByteShortIntLong(-0x59), -0x59L, ref fail); + + // Cast byte -> ushort -> uint -> ulong + ExpectEqual(() => CastByteUShortUIntULong(0xA7), 0xA7ul, ref fail); + + // Cast int -> long -> int -> long + ExpectEqual(() => CastIntSByteIntSByte(-0x15263748), -0x48, ref fail); + ExpectEqual(() => CastIntShortIntShort(-0x15263748), -0x3748, ref fail); + ExpectEqual(() => CastIntLongIntLong(-0x15263748), -0x15263748l, ref fail); + + // Cast uint -> x -> uint -> x + ExpectEqual(() => CastUIntByteUIntByte(0xF0u), 0xF0, ref fail); + ExpectEqual(() => CastUIntUShortUIntUShort(0xFF8001u), 0x8001, ref fail); + ExpectEqual(() => CastUIntULongUIntULong(0x11223344u), 0x11223344ul, ref fail); + + // Cast long -> x -> long -> x + ExpectEqual(() => CastLongSByteLongSByte(0xA7L), -0x59, ref fail); + ExpectEqual(() => CastLongShortLongShort(0xFFFFFFFF8003L), -0x7FFD, ref fail); + ExpectEqual(() => CastLongIntLongInt(0x1ABCDEF00L), -0x54321100, ref fail); + + // Cast ulong -> x -> ulong -> x + ExpectEqual(() => CastULongByteULongByte(0xA7ul), 0xA7, ref fail); + ExpectEqual(() => CastULongUShortULongUShort(0xFFFFFFFF8003ul), 0x8003, ref fail); + ExpectEqual(() => CastULongUIntULongUInt(0x1ABCDEF00ul), 0xABCDEF00u, ref fail); + + if (fail) + { + return 101; + } + return 100; + } + + // Cast int -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static sbyte CastIntSbyte(int x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short CastIntShort(int x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + return (short)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastIntLong(int x) + { + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (long)x; + } + + // Cast long -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static sbyte CastLongSbyte(long x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short CastLongShort(long x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + return (short)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int CastLongInt(long x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (int)x; + } + + // Cast uint -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static byte CastUIntByte(uint x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ushort CastUIntUShort(uint x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastUIntULong(uint x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (ulong)x; + } + + // Cast ulong -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static byte CastULongByte(ulong x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ushort CastULongUShort(ulong x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint CastULongUInt(ulong x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (uint)x; + } + + // Cast int -> x -> int + + [MethodImpl(MethodImplOptions.NoInlining)] + static int CastIntSbyteInt(int x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int CastIntShortInt(int x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + return (short)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int CastIntLongInt(int x) + { + //ARM64-NOT: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (int)(long)x; + } + + // Cast int -> x -> long + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastIntSbyteLong(int x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastIntShortLong(int x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (short)x; + } + + // Cast long -> x -> int + + [MethodImpl(MethodImplOptions.NoInlining)] + static int CastLongSbyteInt(long x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int CastLongShortInt(long x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + return (short)x; + } + + // Cast long -> x -> long + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastLongSbyteLong(long x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastLongShortLong(long x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (short)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastLongIntLong(long x) + { + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (int)x; + } + + // Cast uint -> x -> uint + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint CastUIntByteUInt(uint x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint CastUIntUShortUInt(uint x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)x; + } + + // Cast uint -> x -> ulong + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastUIntByteULong(uint x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastUIntUShortULong(uint x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint CastUIntULongUInt(uint x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (uint)(ulong)x; + } + + // Cast ulong -> x -> uint + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint CastULongByteUInt(ulong x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint CastULongUShortUInt(ulong x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)x; + } + + // Cast ulong -> x -> ulong + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastULongByteULong(ulong x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastULongUShortULong(ulong x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastULongUIntULong(ulong x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (uint)x; + } + + // Cast int -> long -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static sbyte CastIntLongSbyte(int x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)(long)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short CastIntLongShort(int x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + return (short)(long)x; + } + + // Cast uint -> ulong -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static byte CastUIntULongByte(uint x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)(ulong)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ushort CastUIntULongUShort(uint x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)(ulong)x; + } + + // Cast long -> int -> short -> sbyte + + [MethodImpl(MethodImplOptions.NoInlining)] + static sbyte CastLongIntShortSByte(long x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)(short)(int)x; + } + + // Cast ulong -> uint -> ushort -> byte + + [MethodImpl(MethodImplOptions.NoInlining)] + static byte CastULongUIntUShortByte(ulong x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)(ushort)(uint)x; + } + + // Cast sbyte -> short -> int -> long + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastSByteShortIntLong(sbyte x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (long)(int)(short)x; + } + + // Cast byte -> ushort -> uint -> ulong + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastByteUShortUIntULong(byte x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (ulong)(uint)(ushort)x; + } + + // Cast int -> x -> int -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static sbyte CastIntSByteIntSByte(int x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)(int)(sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short CastIntShortIntShort(int x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + return (short)(int)(short)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static long CastIntLongIntLong(int x) + { + //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} + return (long)(int)(long)x; + } + + // Cast uint -> x -> uint -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static byte CastUIntByteUIntByte(uint x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)(uint)(byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ushort CastUIntUShortUIntUShort(uint x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)(uint)(ushort)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong CastUIntULongUIntULong(uint x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (ulong)(uint)(ulong)x; + } + + // Cast long -> x -> long -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static sbyte CastLongSByteLongSByte(long x) + { + //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} + return (sbyte)(long)(sbyte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short CastLongShortLongShort(long x) + { + //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} + return (short)(long)(short)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int CastLongIntLongInt(long x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (int)(long)(int)x; + } + + // Cast ulong -> x -> ulong -> x + + [MethodImpl(MethodImplOptions.NoInlining)] + static byte CastULongByteULongByte(ulong x) + { + //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} + return (byte)(ulong)(byte)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ushort CastULongUShortULongUShort(ulong x) + { + //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} + return (ushort)(ulong)(ushort)x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint CastULongUIntULongUInt(ulong x) + { + //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} + return (uint)(ulong)(uint)x; + } + } +} diff --git a/src/tests/JIT/opt/InstructionCombining/Casts.csproj b/src/tests/JIT/opt/InstructionCombining/Casts.csproj new file mode 100644 index 00000000000000..c66d8762492f5c --- /dev/null +++ b/src/tests/JIT/opt/InstructionCombining/Casts.csproj @@ -0,0 +1,18 @@ + + + + true + + + None + True + + + + true + + + + + + From a6692e81b566e895833caccb89cd84b0c4c07e95 Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Tue, 27 Jan 2026 12:57:25 +0000 Subject: [PATCH 2/3] Change Casts.cs to use Xunit helpers - Remove Expect.cs --- .../CoreCLRTestLibrary.csproj | 1 - src/tests/Common/CoreCLRTestLibrary/Expect.cs | 41 -- .../JIT/opt/InstructionCombining/Casts.cs | 475 ++++++++++-------- .../JIT/opt/InstructionCombining/Casts.csproj | 1 - 4 files changed, 260 insertions(+), 258 deletions(-) delete mode 100644 src/tests/Common/CoreCLRTestLibrary/Expect.cs diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj b/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj index 915e6b1ff1c632..6bbebee74d7177 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj +++ b/src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj @@ -7,7 +7,6 @@ - diff --git a/src/tests/Common/CoreCLRTestLibrary/Expect.cs b/src/tests/Common/CoreCLRTestLibrary/Expect.cs deleted file mode 100644 index 1fed85cb6b51a1..00000000000000 --- a/src/tests/Common/CoreCLRTestLibrary/Expect.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Linq.Expressions; -using Xunit; - -namespace TestLibrary; - -public static class Expect -{ - public static void ExpectEqual(Expression> expr, T expected, ref bool fail) - { - var compiled = expr.Compile(); - T actual = compiled(); - - // Get just the expression body text - string exprText = expr.Body.ToString(); - - if (!Equals(actual, expected)) - { - Console.WriteLine($"{exprText} = {actual}, expected {expected}"); - fail = true; - } - } - - public static void ExpectTrue(Expression> expr, ref bool fail) - { - var compiled = expr.Compile(); - bool actual = compiled(); - - // Get just the expression body text - string exprText = expr.Body.ToString(); - - if (!actual) - { - Console.WriteLine($"{exprText} = {actual}, expected True"); - fail = true; - } - } -} diff --git a/src/tests/JIT/opt/InstructionCombining/Casts.cs b/src/tests/JIT/opt/InstructionCombining/Casts.cs index 4212ac4d57f49b..634ebae77d3e82 100644 --- a/src/tests/JIT/opt/InstructionCombining/Casts.cs +++ b/src/tests/JIT/opt/InstructionCombining/Casts.cs @@ -1,540 +1,585 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.CompilerServices; -using static TestLibrary.Expect; using Xunit; namespace TestMultipleCasts { public class Program { - [MethodImpl(MethodImplOptions.NoInlining)] - [Fact] - public static int CheckMultipleCasts() - { - bool fail = false; - - // Cast int -> x - ExpectEqual(() => CastIntSbyte(0x11223344), 0x44, ref fail); - ExpectEqual(() => CastIntShort(-0x11223344), -0x3344, ref fail); - ExpectEqual(() => CastIntLong(0x11223344), 0x11223344, ref fail); - - // Cast long -> x - ExpectEqual(() => CastLongSbyte(0xFFEEDDCCBBAAL), -0x56, ref fail); - ExpectEqual(() => CastLongShort(0xFFEEDDCCBBAAL), -0x4456, ref fail); - ExpectEqual(() => CastLongInt(0xFFEEDDCCBBAAL), -0x22334456, ref fail); - - // Cast uint -> x - ExpectEqual(() => CastUIntByte(0x11223344u), 0x44, ref fail); - ExpectEqual(() => CastUIntUShort(0x11223344u), 0x3344, ref fail); - ExpectEqual(() => CastUIntULong(0x11223344u), 0x11223344ul, ref fail); - - // Cast ulong -> x - ExpectEqual(() => CastULongByte(0xFFEEDDCCBBAAul), 0xAA, ref fail); - ExpectEqual(() => CastULongUShort(0xFFEEDDCCBBAAul), 0xBBAA, ref fail); - ExpectEqual(() => CastULongUInt(0xFFEEDDCCBBAAul), 0xDDCCBBAAu, ref fail); - - // Cast int -> x -> int - ExpectEqual(() => CastIntSbyteInt(0xF0), -0x10, ref fail); - ExpectEqual(() => CastIntShortInt(0xFF8001), -0x7FFF, ref fail); - ExpectEqual(() => CastIntLongInt(0x11223344), 0x11223344, ref fail); - - // Cast int -> x -> long - ExpectEqual(() => CastIntSbyteLong(0x12345678), 0x78, ref fail); - ExpectEqual(() => CastIntShortLong(0x12345678), 0x5678, ref fail); - - // Cast long -> x -> int - ExpectEqual(() => CastLongSbyteInt(0xA7L), -0x59, ref fail); - ExpectEqual(() => CastLongShortInt(0xFFFFFFFF8003L), -0x7FFD, ref fail); - - // Cast long -> x -> long - ExpectEqual(() => CastLongSbyteLong(0xFEL), -0x2L, ref fail); - ExpectEqual(() => CastLongShortLong(0xDEADL), -0x2153L, ref fail); - ExpectEqual(() => CastLongIntLong(0x1ABCDEF00L), -0x54321100L, ref fail); - - // Cast uint -> x -> uint - ExpectEqual(() => CastUIntByteUInt(0xF0u), 0xF0u, ref fail); - ExpectEqual(() => CastUIntUShortUInt(0xFF8001u), 0x8001u, ref fail); - - // Cast uint -> x -> ulong - ExpectEqual(() => CastUIntByteULong(0x12345678u), 0x78ul, ref fail); - ExpectEqual(() => CastUIntUShortULong(0x12345678u), 0x5678ul, ref fail); - ExpectEqual(() => CastUIntULongUInt(0x11223344u), 0x11223344u, ref fail); - - // Cast ulong -> x -> uint - ExpectEqual(() => CastULongByteUInt(0xA7ul), 0xA7u, ref fail); - ExpectEqual(() => CastULongUShortUInt(0xFFFFFFFF8003ul), 0x8003u, ref fail); - - // Cast ulong -> x -> ulong - ExpectEqual(() => CastULongByteULong(0xFEul), 0xFEul, ref fail); - ExpectEqual(() => CastULongUShortULong(0xDEADul), 0xDEADul, ref fail); - ExpectEqual(() => CastULongUIntULong(0x1ABCDEF00ul), 0xABCDEF00ul, ref fail); - - // Cast int -> long -> x - ExpectEqual(() => CastIntLongSbyte(0x11223344), 0x44, ref fail); - ExpectEqual(() => CastIntLongShort(0x11223344), 0x3344, ref fail); - - // Cast uint -> ulong -> x - ExpectEqual(() => CastUIntULongByte(0x11223344u), 0x44, ref fail); - ExpectEqual(() => CastUIntULongUShort(0x11223344u), 0x3344, ref fail); - - // Cast long -> int -> short -> sbyte - ExpectEqual(() => CastLongIntShortSByte(0x11223344), 0x44, ref fail); - - // Cast ulong -> uint -> ushort -> byte - ExpectEqual(() => CastULongUIntUShortByte(0x11223344u), 0x44, ref fail); - - // Cast sbyte -> short -> int -> long - ExpectEqual(() => CastSByteShortIntLong(-0x59), -0x59L, ref fail); - - // Cast byte -> ushort -> uint -> ulong - ExpectEqual(() => CastByteUShortUIntULong(0xA7), 0xA7ul, ref fail); - - // Cast int -> long -> int -> long - ExpectEqual(() => CastIntSByteIntSByte(-0x15263748), -0x48, ref fail); - ExpectEqual(() => CastIntShortIntShort(-0x15263748), -0x3748, ref fail); - ExpectEqual(() => CastIntLongIntLong(-0x15263748), -0x15263748l, ref fail); - - // Cast uint -> x -> uint -> x - ExpectEqual(() => CastUIntByteUIntByte(0xF0u), 0xF0, ref fail); - ExpectEqual(() => CastUIntUShortUIntUShort(0xFF8001u), 0x8001, ref fail); - ExpectEqual(() => CastUIntULongUIntULong(0x11223344u), 0x11223344ul, ref fail); - - // Cast long -> x -> long -> x - ExpectEqual(() => CastLongSByteLongSByte(0xA7L), -0x59, ref fail); - ExpectEqual(() => CastLongShortLongShort(0xFFFFFFFF8003L), -0x7FFD, ref fail); - ExpectEqual(() => CastLongIntLongInt(0x1ABCDEF00L), -0x54321100, ref fail); - - // Cast ulong -> x -> ulong -> x - ExpectEqual(() => CastULongByteULongByte(0xA7ul), 0xA7, ref fail); - ExpectEqual(() => CastULongUShortULongUShort(0xFFFFFFFF8003ul), 0x8003, ref fail); - ExpectEqual(() => CastULongUIntULongUInt(0x1ABCDEF00ul), 0xABCDEF00u, ref fail); - - if (fail) - { - return 101; - } - return 100; - } - // Cast int -> x + [Theory] + [InlineData(0x11223344, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - static sbyte CastIntSbyte(int x) + public static void CastIntSbyte(int x, sbyte expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)x; + sbyte result = (sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(-0x11223344, -0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - static short CastIntShort(int x) + public static void CastIntShort(int x, short expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - return (short)x; + short result = (short)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344, 0x11223344)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastIntLong(int x) + public static void CastIntLong(int x, long expected) { //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (long)x; + long result = (long)x; + Assert.Equal(expected, result); } // Cast long -> x + [Theory] + [InlineData(0xFFEEDDCCBBAAL, -0x56)] [MethodImpl(MethodImplOptions.NoInlining)] - static sbyte CastLongSbyte(long x) + public static void CastLongSbyte(long x, sbyte expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)x; + sbyte result = (sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFEEDDCCBBAAL, -0x4456)] [MethodImpl(MethodImplOptions.NoInlining)] - static short CastLongShort(long x) + public static void CastLongShort(long x, short expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - return (short)x; + short result = (short)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFEEDDCCBBAAL, -0x22334456)] [MethodImpl(MethodImplOptions.NoInlining)] - static int CastLongInt(long x) + public static void CastLongInt(long x, int expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (int)x; + int result = (int)x; + Assert.Equal(expected, result); } // Cast uint -> x + [Theory] + [InlineData(0x11223344u, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - static byte CastUIntByte(uint x) + public static void CastUIntByte(uint x, byte expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)x; + byte result = (byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344u, 0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - static ushort CastUIntUShort(uint x) + public static void CastUIntUShort(uint x, ushort expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)x; + ushort result = (ushort)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344u, 0x11223344ul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastUIntULong(uint x) + public static void CastUIntULong(uint x, ulong expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (ulong)x; + ulong result = (ulong)x; + Assert.Equal(expected, result); } // Cast ulong -> x + [Theory] + [InlineData(0xFFEEDDCCBBAAul, 0xAA)] [MethodImpl(MethodImplOptions.NoInlining)] - static byte CastULongByte(ulong x) + public static void CastULongByte(ulong x, byte expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)x; + byte result = (byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFEEDDCCBBAAul, 0xBBAA)] [MethodImpl(MethodImplOptions.NoInlining)] - static ushort CastULongUShort(ulong x) + public static void CastULongUShort(ulong x, ushort expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)x; + ushort result = (ushort)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFEEDDCCBBAAul, 0xDDCCBBAAu)] [MethodImpl(MethodImplOptions.NoInlining)] - static uint CastULongUInt(ulong x) + public static void CastULongUInt(ulong x, uint expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (uint)x; + uint result = (uint)x; + Assert.Equal(expected, result); } // Cast int -> x -> int + [Theory] + [InlineData(0xF0, -0x10)] [MethodImpl(MethodImplOptions.NoInlining)] - static int CastIntSbyteInt(int x) + public static void CastIntSbyteInt(int x, int expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)x; + int result = (sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFF8001, -0x7FFF)] [MethodImpl(MethodImplOptions.NoInlining)] - static int CastIntShortInt(int x) + public static void CastIntShortInt(int x, int expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - return (short)x; + int result = (short)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344, 0x11223344)] [MethodImpl(MethodImplOptions.NoInlining)] - static int CastIntLongInt(int x) + public static void CastIntLongInt(int x, int expected) { //ARM64-NOT: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (int)(long)x; + int result = (int)(long)x; + Assert.Equal(expected, result); } // Cast int -> x -> long + [Theory] + [InlineData(0x12345678, 0x78)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastIntSbyteLong(int x) + public static void CastIntSbyteLong(int x, long expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (sbyte)x; + long result = (sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x12345678, 0x5678)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastIntShortLong(int x) + public static void CastIntShortLong(int x, long expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (short)x; + long result = (short)x; + Assert.Equal(expected, result); } // Cast long -> x -> int + [Theory] + [InlineData(0xA7L, -0x59)] [MethodImpl(MethodImplOptions.NoInlining)] - static int CastLongSbyteInt(long x) + public static void CastLongSbyteInt(long x, int expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)x; + int result = (sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFFFFFFF8003L, -0x7FFD)] [MethodImpl(MethodImplOptions.NoInlining)] - static int CastLongShortInt(long x) + public static void CastLongShortInt(long x, int expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - return (short)x; + int result = (short)x; + Assert.Equal(expected, result); } // Cast long -> x -> long + [Theory] + [InlineData(0xFEL, -0x2L)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastLongSbyteLong(long x) + public static void CastLongSbyteLong(long x, long expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (sbyte)x; + long result = (sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xDEADL, -0x2153L)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastLongShortLong(long x) + public static void CastLongShortLong(long x, long expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (short)x; + long result = (short)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x1ABCDEF00L, -0x54321100L)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastLongIntLong(long x) + public static void CastLongIntLong(long x, long expected) { //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (int)x; + long result = (int)x; + Assert.Equal(expected, result); } // Cast uint -> x -> uint + [Theory] + [InlineData(0xF0u, 0xF0u)] [MethodImpl(MethodImplOptions.NoInlining)] - static uint CastUIntByteUInt(uint x) + public static void CastUIntByteUInt(uint x, uint expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)x; + uint result = (byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFF8001u, 0x8001u)] [MethodImpl(MethodImplOptions.NoInlining)] - static uint CastUIntUShortUInt(uint x) + public static void CastUIntUShortUInt(uint x, uint expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)x; + uint result = (ushort)x; + Assert.Equal(expected, result); } // Cast uint -> x -> ulong + [Theory] + [InlineData(0x12345678u, 0x78ul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastUIntByteULong(uint x) + public static void CastUIntByteULong(uint x, ulong expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (byte)x; + ulong result = (byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x12345678u, 0x5678ul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastUIntUShortULong(uint x) + public static void CastUIntUShortULong(uint x, ulong expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)x; + ulong result = (ushort)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344u, 0x11223344u)] [MethodImpl(MethodImplOptions.NoInlining)] - static uint CastUIntULongUInt(uint x) + public static void CastUIntULongUInt(uint x, uint expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (uint)(ulong)x; + uint result = (uint)(ulong)x; + Assert.Equal(expected, result); } // Cast ulong -> x -> uint + [Theory] + [InlineData(0xA7ul, 0xA7u)] [MethodImpl(MethodImplOptions.NoInlining)] - static uint CastULongByteUInt(ulong x) + public static void CastULongByteUInt(ulong x, uint expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)x; + uint result = (byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFFFFFFF8003ul, 0x8003u)] [MethodImpl(MethodImplOptions.NoInlining)] - static uint CastULongUShortUInt(ulong x) + public static void CastULongUShortUInt(ulong x, uint expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)x; + uint result = (ushort)x; + Assert.Equal(expected, result); } // Cast ulong -> x -> ulong + [Theory] + [InlineData(0xFEul, 0xFEul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastULongByteULong(ulong x) + public static void CastULongByteULong(ulong x, ulong expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (byte)x; + ulong result = (byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xDEADul, 0xDEADul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastULongUShortULong(ulong x) + public static void CastULongUShortULong(ulong x, ulong expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)x; + ulong result = (ushort)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x1ABCDEF00ul, 0xABCDEF00ul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastULongUIntULong(ulong x) + public static void CastULongUIntULong(ulong x, ulong expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (uint)x; + ulong result = (uint)x; + Assert.Equal(expected, result); } // Cast int -> long -> x + [Theory] + [InlineData(0x11223344, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - static sbyte CastIntLongSbyte(int x) + public static void CastIntLongSbyte(int x, sbyte expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)(long)x; + sbyte result = (sbyte)(long)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344, 0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - static short CastIntLongShort(int x) + public static void CastIntLongShort(int x, short expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - return (short)(long)x; + short result = (short)(long)x; + Assert.Equal(expected, result); } // Cast uint -> ulong -> x + [Theory] + [InlineData(0x11223344u, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - static byte CastUIntULongByte(uint x) + public static void CastUIntULongByte(uint x, byte expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)(ulong)x; + byte result = (byte)(ulong)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344u, 0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - static ushort CastUIntULongUShort(uint x) + public static void CastUIntULongUShort(uint x, ushort expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)(ulong)x; + ushort result = (ushort)(ulong)x; + Assert.Equal(expected, result); } // Cast long -> int -> short -> sbyte + [Theory] + [InlineData(0x11223344L, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - static sbyte CastLongIntShortSByte(long x) + public static void CastLongIntShortSByte(long x, sbyte expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)(short)(int)x; + sbyte result = (sbyte)(short)(int)x; + Assert.Equal(expected, result); } // Cast ulong -> uint -> ushort -> byte + [Theory] + [InlineData(0x11223344ul, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - static byte CastULongUIntUShortByte(ulong x) + public static void CastULongUIntUShortByte(ulong x, byte expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)(ushort)(uint)x; + byte result = (byte)(ushort)(uint)x; + Assert.Equal(expected, result); } // Cast sbyte -> short -> int -> long + [Theory] + [InlineData(-0x59, -0x59L)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastSByteShortIntLong(sbyte x) + public static void CastSByteShortIntLong(sbyte x, long expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (long)(int)(short)x; + long result = (long)(int)(short)x; + Assert.Equal(expected, result); } // Cast byte -> ushort -> uint -> ulong + [Theory] + [InlineData(0xA7, 0xA7ul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastByteUShortUIntULong(byte x) + public static void CastByteUShortUIntULong(byte x, ulong expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (ulong)(uint)(ushort)x; + ulong result = (ulong)(uint)(ushort)x; + Assert.Equal(expected, result); } // Cast int -> x -> int -> x + [Theory] + [InlineData(-0x15263748, -0x48)] [MethodImpl(MethodImplOptions.NoInlining)] - static sbyte CastIntSByteIntSByte(int x) + public static void CastIntSByteIntSByte(int x, sbyte expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)(int)(sbyte)x; + sbyte result = (sbyte)(int)(sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(-0x15263748, -0x3748)] [MethodImpl(MethodImplOptions.NoInlining)] - static short CastIntShortIntShort(int x) + public static void CastIntShortIntShort(int x, short expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - return (short)(int)(short)x; + short result = (short)(int)(short)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(-0x15263748, -0x15263748L)] [MethodImpl(MethodImplOptions.NoInlining)] - static long CastIntLongIntLong(int x) + public static void CastIntLongIntLong(int x, long expected) { //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - return (long)(int)(long)x; + long result = (long)(int)(long)x; + Assert.Equal(expected, result); } // Cast uint -> x -> uint -> x + [Theory] + [InlineData(0xF0u, 0xF0)] [MethodImpl(MethodImplOptions.NoInlining)] - static byte CastUIntByteUIntByte(uint x) + public static void CastUIntByteUIntByte(uint x, byte expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)(uint)(byte)x; + byte result = (byte)(uint)(byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFF8001u, 0x8001)] [MethodImpl(MethodImplOptions.NoInlining)] - static ushort CastUIntUShortUIntUShort(uint x) + public static void CastUIntUShortUIntUShort(uint x, ushort expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)(uint)(ushort)x; + ushort result = (ushort)(uint)(ushort)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x11223344u, 0x11223344ul)] [MethodImpl(MethodImplOptions.NoInlining)] - static ulong CastUIntULongUIntULong(uint x) + public static void CastUIntULongUIntULong(uint x, ulong expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (ulong)(uint)(ulong)x; + ulong result = (ulong)(uint)(ulong)x; + Assert.Equal(expected, result); } // Cast long -> x -> long -> x + [Theory] + [InlineData(0xA7L, -0x59)] [MethodImpl(MethodImplOptions.NoInlining)] - static sbyte CastLongSByteLongSByte(long x) + public static void CastLongSByteLongSByte(long x, sbyte expected) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - return (sbyte)(long)(sbyte)x; + sbyte result = (sbyte)(long)(sbyte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFFFFFFF8003L, -0x7FFD)] [MethodImpl(MethodImplOptions.NoInlining)] - static short CastLongShortLongShort(long x) + public static void CastLongShortLongShort(long x, short expected) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - return (short)(long)(short)x; + short result = (short)(long)(short)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x1ABCDEF00L, -0x54321100)] [MethodImpl(MethodImplOptions.NoInlining)] - static int CastLongIntLongInt(long x) + public static void CastLongIntLongInt(long x, int expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (int)(long)(int)x; + int result = (int)(long)(int)x; + Assert.Equal(expected, result); } // Cast ulong -> x -> ulong -> x + [Theory] + [InlineData(0xA7ul, 0xA7)] [MethodImpl(MethodImplOptions.NoInlining)] - static byte CastULongByteULongByte(ulong x) + public static void CastULongByteULongByte(ulong x, byte expected) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - return (byte)(ulong)(byte)x; + byte result = (byte)(ulong)(byte)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0xFFFFFFFF8003ul, 0x8003)] [MethodImpl(MethodImplOptions.NoInlining)] - static ushort CastULongUShortULongUShort(ulong x) + public static void CastULongUShortULongUShort(ulong x, ushort expected) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - return (ushort)(ulong)(ushort)x; + ushort result = (ushort)(ulong)(ushort)x; + Assert.Equal(expected, result); } + [Theory] + [InlineData(0x1ABCDEF00ul, 0xABCDEF00u)] [MethodImpl(MethodImplOptions.NoInlining)] - static uint CastULongUIntULongUInt(ulong x) + public static void CastULongUIntULongUInt(ulong x, uint expected) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - return (uint)(ulong)(uint)x; + uint result = (uint)(ulong)(uint)x; + Assert.Equal(expected, result); } } } diff --git a/src/tests/JIT/opt/InstructionCombining/Casts.csproj b/src/tests/JIT/opt/InstructionCombining/Casts.csproj index c66d8762492f5c..b3cc1eeece28c6 100644 --- a/src/tests/JIT/opt/InstructionCombining/Casts.csproj +++ b/src/tests/JIT/opt/InstructionCombining/Casts.csproj @@ -13,6 +13,5 @@ - From 6d952611c747cff0478ab08d08625a95b3f5a19b Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Thu, 29 Jan 2026 09:42:30 +0000 Subject: [PATCH 3/3] Revert Casts.cs to single test function --- .../JIT/opt/InstructionCombining/Casts.cs | 629 ++++++++++-------- 1 file changed, 369 insertions(+), 260 deletions(-) diff --git a/src/tests/JIT/opt/InstructionCombining/Casts.cs b/src/tests/JIT/opt/InstructionCombining/Casts.cs index 634ebae77d3e82..438b4869b3ccf5 100644 --- a/src/tests/JIT/opt/InstructionCombining/Casts.cs +++ b/src/tests/JIT/opt/InstructionCombining/Casts.cs @@ -8,578 +8,687 @@ namespace TestMultipleCasts { public class Program { + [MethodImpl(MethodImplOptions.NoInlining)] + [Fact] + public static int CheckMultipleCasts() + { + bool fail = false; + + // Cast int -> x + if (CastIntSbyte(0x11223344) != 0x44) + { + fail = true; + } + if (CastIntShort(-0x11223344) != -0x3344) + { + fail = true; + } + if (CastIntLong(0x11223344) != 0x11223344) + { + fail = true; + } + + // Cast long -> x + if (CastLongSbyte(0xFFEEDDCCBBAAL) != -0x56) + { + fail = true; + } + if (CastLongShort(0xFFEEDDCCBBAAL) != -0x4456) + { + fail = true; + } + if (CastLongInt(0xFFEEDDCCBBAAL) != -0x22334456) + { + fail = true; + } + + // Cast uint -> x + if (CastUIntByte(0x11223344u) != 0x44) + { + fail = true; + } + if (CastUIntUShort(0x11223344u) != 0x3344) + { + fail = true; + } + if (CastUIntULong(0x11223344u) != 0x11223344ul) + { + fail = true; + } + + // Cast ulong -> x + if (CastULongByte(0xFFEEDDCCBBAAul) != 0xAA) + { + fail = true; + } + if (CastULongUShort(0xFFEEDDCCBBAAul) != 0xBBAA) + { + fail = true; + } + if (CastULongUInt(0xFFEEDDCCBBAAul) != 0xDDCCBBAAu) + { + fail = true; + } + + // Cast int -> x -> int + if (CastIntSbyteInt(0xF0) != -0x10) + { + fail = true; + } + if (CastIntShortInt(0xFF8001) != -0x7FFF) + { + fail = true; + } + if (CastIntLongInt(0x11223344) != 0x11223344) + { + fail = true; + } + + // Cast int -> x -> long + if (CastIntSbyteLong(0x12345678) != 0x78) + { + fail = true; + } + if (CastIntShortLong(0x12345678) != 0x5678) + { + fail = true; + } + + // Cast long -> x -> int + if (CastLongSbyteInt(0xA7L) != -0x59) + { + fail = true; + } + if (CastLongShortInt(0xFFFFFFFF8003L) != -0x7FFD) + { + fail = true; + } + + // Cast long -> x -> long + if (CastLongSbyteLong(0xFEL) != -0x2L) + { + fail = true; + } + if (CastLongShortLong(0xDEADL) != -0x2153L) + { + fail = true; + } + if (CastLongIntLong(0x1ABCDEF00L) != -0x54321100L) + { + fail = true; + } + + // Cast uint -> x -> uint + if (CastUIntByteUInt(0xF0u) != 0xF0u) + { + fail = true; + } + if (CastUIntUShortUInt(0xFF8001u) != 0x8001u) + { + fail = true; + } + + // Cast uint -> x -> ulong + if (CastUIntByteULong(0x12345678u) != 0x78ul) + { + fail = true; + } + if (CastUIntUShortULong(0x12345678u) != 0x5678ul) + { + fail = true; + } + if (CastUIntULongUInt(0x11223344u) != 0x11223344u) + { + fail = true; + } + + // Cast ulong -> x -> uint + if (CastULongByteUInt(0xA7ul) != 0xA7u) + { + fail = true; + } + if (CastULongUShortUInt(0xFFFFFFFF8003ul) != 0x8003u) + { + fail = true; + } + + // Cast ulong -> x -> ulong + if (CastULongByteULong(0xFEul) != 0xFEul) + { + fail = true; + } + if (CastULongUShortULong(0xDEADul) != 0xDEADul) + { + fail = true; + } + if (CastULongUIntULong(0x1ABCDEF00ul) != 0xABCDEF00ul) + { + fail = true; + } + + // Cast int -> long -> x + if (CastIntLongSbyte(0x11223344) != 0x44) + { + fail = true; + } + if (CastIntLongShort(0x11223344) != 0x3344) + { + fail = true; + } + + // Cast uint -> ulong -> x + if (CastUIntULongByte(0x11223344u) != 0x44) + { + fail = true; + } + if (CastUIntULongUShort(0x11223344u) != 0x3344) + { + fail = true; + } + + // Cast long -> int -> short -> sbyte + if (CastLongIntShortSByte(0x11223344) != 0x44) + { + fail = true; + } + + // Cast ulong -> uint -> ushort -> byte + if (CastULongUIntUShortByte(0x11223344u) != 0x44) + { + fail = true; + } + + // Cast sbyte -> short -> int -> long + if (CastSByteShortIntLong(-0x59) != -0x59L) + { + fail = true; + } + + // Cast byte -> ushort -> uint -> ulong + if (CastByteUShortUIntULong(0xA7) != 0xA7ul) + { + fail = true; + } + + // Cast int -> long -> int -> long + if (CastIntSByteIntSByte(-0x15263748) != -0x48) + { + fail = true; + } + if (CastIntShortIntShort(-0x15263748) != -0x3748) + { + fail = true; + } + if (CastIntLongIntLong(-0x15263748) != -0x15263748l) + { + fail = true; + } + + // Cast uint -> x -> uint -> x + if (CastUIntByteUIntByte(0xF0u) != 0xF0) + { + fail = true; + } + if (CastUIntUShortUIntUShort(0xFF8001u) != 0x8001) + { + fail = true; + } + if (CastUIntULongUIntULong(0x11223344u) != 0x11223344ul) + { + fail = true; + } + + // Cast long -> x -> long -> x + if (CastLongSByteLongSByte(0xA7L) != -0x59) + { + fail = true; + } + if (CastLongShortLongShort(0xFFFFFFFF8003L) != -0x7FFD) + { + fail = true; + } + if (CastLongIntLongInt(0x1ABCDEF00L) != -0x54321100) + { + fail = true; + } + + // Cast ulong -> x -> ulong -> x + if (CastULongByteULongByte(0xA7ul) != 0xA7) + { + fail = true; + } + if (CastULongUShortULongUShort(0xFFFFFFFF8003ul) != 0x8003) + { + fail = true; + } + if (CastULongUIntULongUInt(0x1ABCDEF00ul) != 0xABCDEF00u) + { + fail = true; + } + + if (fail) + { + return 101; + } + return 100; + } + // Cast int -> x - [Theory] - [InlineData(0x11223344, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntSbyte(int x, sbyte expected) + static sbyte CastIntSbyte(int x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - sbyte result = (sbyte)x; - Assert.Equal(expected, result); + return (sbyte)x; } - [Theory] - [InlineData(-0x11223344, -0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntShort(int x, short expected) + static short CastIntShort(int x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - short result = (short)x; - Assert.Equal(expected, result); + return (short)x; } - [Theory] - [InlineData(0x11223344, 0x11223344)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntLong(int x, long expected) + static long CastIntLong(int x) { //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (long)x; - Assert.Equal(expected, result); + return (long)x; } // Cast long -> x - [Theory] - [InlineData(0xFFEEDDCCBBAAL, -0x56)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongSbyte(long x, sbyte expected) + static sbyte CastLongSbyte(long x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - sbyte result = (sbyte)x; - Assert.Equal(expected, result); + return (sbyte)x; } - [Theory] - [InlineData(0xFFEEDDCCBBAAL, -0x4456)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongShort(long x, short expected) + static short CastLongShort(long x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - short result = (short)x; - Assert.Equal(expected, result); + return (short)x; } - [Theory] - [InlineData(0xFFEEDDCCBBAAL, -0x22334456)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongInt(long x, int expected) + static int CastLongInt(long x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - int result = (int)x; - Assert.Equal(expected, result); + return (int)x; } // Cast uint -> x - [Theory] - [InlineData(0x11223344u, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntByte(uint x, byte expected) + static byte CastUIntByte(uint x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - byte result = (byte)x; - Assert.Equal(expected, result); + return (byte)x; } - [Theory] - [InlineData(0x11223344u, 0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntUShort(uint x, ushort expected) + static ushort CastUIntUShort(uint x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - ushort result = (ushort)x; - Assert.Equal(expected, result); + return (ushort)x; } - [Theory] - [InlineData(0x11223344u, 0x11223344ul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntULong(uint x, ulong expected) + static ulong CastUIntULong(uint x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (ulong)x; - Assert.Equal(expected, result); + return (ulong)x; } // Cast ulong -> x - [Theory] - [InlineData(0xFFEEDDCCBBAAul, 0xAA)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongByte(ulong x, byte expected) + static byte CastULongByte(ulong x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - byte result = (byte)x; - Assert.Equal(expected, result); + return (byte)x; } - [Theory] - [InlineData(0xFFEEDDCCBBAAul, 0xBBAA)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUShort(ulong x, ushort expected) + static ushort CastULongUShort(ulong x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - ushort result = (ushort)x; - Assert.Equal(expected, result); + return (ushort)x; } - [Theory] - [InlineData(0xFFEEDDCCBBAAul, 0xDDCCBBAAu)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUInt(ulong x, uint expected) + static uint CastULongUInt(ulong x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - uint result = (uint)x; - Assert.Equal(expected, result); + return (uint)x; } // Cast int -> x -> int - [Theory] - [InlineData(0xF0, -0x10)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntSbyteInt(int x, int expected) + static int CastIntSbyteInt(int x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - int result = (sbyte)x; - Assert.Equal(expected, result); + return (sbyte)x; } - [Theory] - [InlineData(0xFF8001, -0x7FFF)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntShortInt(int x, int expected) + static int CastIntShortInt(int x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - int result = (short)x; - Assert.Equal(expected, result); + return (short)x; } - [Theory] - [InlineData(0x11223344, 0x11223344)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntLongInt(int x, int expected) + static int CastIntLongInt(int x) { //ARM64-NOT: sxtw {{x[0-9]+}}, {{w[0-9]+}} - int result = (int)(long)x; - Assert.Equal(expected, result); + return (int)(long)x; } // Cast int -> x -> long - [Theory] - [InlineData(0x12345678, 0x78)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntSbyteLong(int x, long expected) + static long CastIntSbyteLong(int x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (sbyte)x; - Assert.Equal(expected, result); + return (sbyte)x; } - [Theory] - [InlineData(0x12345678, 0x5678)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntShortLong(int x, long expected) + static long CastIntShortLong(int x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (short)x; - Assert.Equal(expected, result); + return (short)x; } // Cast long -> x -> int - [Theory] - [InlineData(0xA7L, -0x59)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongSbyteInt(long x, int expected) + static int CastLongSbyteInt(long x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - int result = (sbyte)x; - Assert.Equal(expected, result); + return (sbyte)x; } - [Theory] - [InlineData(0xFFFFFFFF8003L, -0x7FFD)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongShortInt(long x, int expected) + static int CastLongShortInt(long x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - int result = (short)x; - Assert.Equal(expected, result); + return (short)x; } // Cast long -> x -> long - [Theory] - [InlineData(0xFEL, -0x2L)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongSbyteLong(long x, long expected) + static long CastLongSbyteLong(long x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (sbyte)x; - Assert.Equal(expected, result); + return (sbyte)x; } - [Theory] - [InlineData(0xDEADL, -0x2153L)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongShortLong(long x, long expected) + static long CastLongShortLong(long x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (short)x; - Assert.Equal(expected, result); + return (short)x; } - [Theory] - [InlineData(0x1ABCDEF00L, -0x54321100L)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongIntLong(long x, long expected) + static long CastLongIntLong(long x) { //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (int)x; - Assert.Equal(expected, result); + return (int)x; } // Cast uint -> x -> uint - [Theory] - [InlineData(0xF0u, 0xF0u)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntByteUInt(uint x, uint expected) + static uint CastUIntByteUInt(uint x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - uint result = (byte)x; - Assert.Equal(expected, result); + return (byte)x; } - [Theory] - [InlineData(0xFF8001u, 0x8001u)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntUShortUInt(uint x, uint expected) + static uint CastUIntUShortUInt(uint x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - uint result = (ushort)x; - Assert.Equal(expected, result); + return (ushort)x; } // Cast uint -> x -> ulong - [Theory] - [InlineData(0x12345678u, 0x78ul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntByteULong(uint x, ulong expected) + static ulong CastUIntByteULong(uint x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (byte)x; - Assert.Equal(expected, result); + return (byte)x; } - [Theory] - [InlineData(0x12345678u, 0x5678ul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntUShortULong(uint x, ulong expected) + static ulong CastUIntUShortULong(uint x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (ushort)x; - Assert.Equal(expected, result); + return (ushort)x; } - [Theory] - [InlineData(0x11223344u, 0x11223344u)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntULongUInt(uint x, uint expected) + static uint CastUIntULongUInt(uint x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - uint result = (uint)(ulong)x; - Assert.Equal(expected, result); + return (uint)(ulong)x; } // Cast ulong -> x -> uint - [Theory] - [InlineData(0xA7ul, 0xA7u)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongByteUInt(ulong x, uint expected) + static uint CastULongByteUInt(ulong x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - uint result = (byte)x; - Assert.Equal(expected, result); + return (byte)x; } - [Theory] - [InlineData(0xFFFFFFFF8003ul, 0x8003u)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUShortUInt(ulong x, uint expected) + static uint CastULongUShortUInt(ulong x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - uint result = (ushort)x; - Assert.Equal(expected, result); + return (ushort)x; } // Cast ulong -> x -> ulong - [Theory] - [InlineData(0xFEul, 0xFEul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongByteULong(ulong x, ulong expected) + static ulong CastULongByteULong(ulong x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (byte)x; - Assert.Equal(expected, result); + return (byte)x; } - [Theory] - [InlineData(0xDEADul, 0xDEADul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUShortULong(ulong x, ulong expected) + static ulong CastULongUShortULong(ulong x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (ushort)x; - Assert.Equal(expected, result); + return (ushort)x; } - [Theory] - [InlineData(0x1ABCDEF00ul, 0xABCDEF00ul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUIntULong(ulong x, ulong expected) + static ulong CastULongUIntULong(ulong x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (uint)x; - Assert.Equal(expected, result); + return (uint)x; } // Cast int -> long -> x - [Theory] - [InlineData(0x11223344, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntLongSbyte(int x, sbyte expected) + static sbyte CastIntLongSbyte(int x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - sbyte result = (sbyte)(long)x; - Assert.Equal(expected, result); + return (sbyte)(long)x; } - [Theory] - [InlineData(0x11223344, 0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntLongShort(int x, short expected) + static short CastIntLongShort(int x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - short result = (short)(long)x; - Assert.Equal(expected, result); + return (short)(long)x; } // Cast uint -> ulong -> x - [Theory] - [InlineData(0x11223344u, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntULongByte(uint x, byte expected) + static byte CastUIntULongByte(uint x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - byte result = (byte)(ulong)x; - Assert.Equal(expected, result); + return (byte)(ulong)x; } - [Theory] - [InlineData(0x11223344u, 0x3344)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntULongUShort(uint x, ushort expected) + static ushort CastUIntULongUShort(uint x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - ushort result = (ushort)(ulong)x; - Assert.Equal(expected, result); + return (ushort)(ulong)x; } // Cast long -> int -> short -> sbyte - [Theory] - [InlineData(0x11223344L, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongIntShortSByte(long x, sbyte expected) + static sbyte CastLongIntShortSByte(long x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - sbyte result = (sbyte)(short)(int)x; - Assert.Equal(expected, result); + return (sbyte)(short)(int)x; } // Cast ulong -> uint -> ushort -> byte - [Theory] - [InlineData(0x11223344ul, 0x44)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUIntUShortByte(ulong x, byte expected) + static byte CastULongUIntUShortByte(ulong x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - byte result = (byte)(ushort)(uint)x; - Assert.Equal(expected, result); + return (byte)(ushort)(uint)x; } // Cast sbyte -> short -> int -> long - [Theory] - [InlineData(-0x59, -0x59L)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastSByteShortIntLong(sbyte x, long expected) + static long CastSByteShortIntLong(sbyte x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (long)(int)(short)x; - Assert.Equal(expected, result); + return (long)(int)(short)x; } // Cast byte -> ushort -> uint -> ulong - [Theory] - [InlineData(0xA7, 0xA7ul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastByteUShortUIntULong(byte x, ulong expected) + static ulong CastByteUShortUIntULong(byte x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (ulong)(uint)(ushort)x; - Assert.Equal(expected, result); + return (ulong)(uint)(ushort)x; } // Cast int -> x -> int -> x - [Theory] - [InlineData(-0x15263748, -0x48)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntSByteIntSByte(int x, sbyte expected) + static sbyte CastIntSByteIntSByte(int x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - sbyte result = (sbyte)(int)(sbyte)x; - Assert.Equal(expected, result); + return (sbyte)(int)(sbyte)x; } - [Theory] - [InlineData(-0x15263748, -0x3748)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntShortIntShort(int x, short expected) + static short CastIntShortIntShort(int x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - short result = (short)(int)(short)x; - Assert.Equal(expected, result); + return (short)(int)(short)x; } - [Theory] - [InlineData(-0x15263748, -0x15263748L)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastIntLongIntLong(int x, long expected) + static long CastIntLongIntLong(int x) { //ARM64-FULL-LINE: sxtw {{x[0-9]+}}, {{w[0-9]+}} - long result = (long)(int)(long)x; - Assert.Equal(expected, result); + return (long)(int)(long)x; } // Cast uint -> x -> uint -> x - [Theory] - [InlineData(0xF0u, 0xF0)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntByteUIntByte(uint x, byte expected) + static byte CastUIntByteUIntByte(uint x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - byte result = (byte)(uint)(byte)x; - Assert.Equal(expected, result); + return (byte)(uint)(byte)x; } - [Theory] - [InlineData(0xFF8001u, 0x8001)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntUShortUIntUShort(uint x, ushort expected) + static ushort CastUIntUShortUIntUShort(uint x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - ushort result = (ushort)(uint)(ushort)x; - Assert.Equal(expected, result); + return (ushort)(uint)(ushort)x; } - [Theory] - [InlineData(0x11223344u, 0x11223344ul)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastUIntULongUIntULong(uint x, ulong expected) + static ulong CastUIntULongUIntULong(uint x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - ulong result = (ulong)(uint)(ulong)x; - Assert.Equal(expected, result); + return (ulong)(uint)(ulong)x; } // Cast long -> x -> long -> x - [Theory] - [InlineData(0xA7L, -0x59)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongSByteLongSByte(long x, sbyte expected) + static sbyte CastLongSByteLongSByte(long x) { //ARM64-FULL-LINE: sxtb {{w[0-9]+}}, {{w[0-9]+}} - sbyte result = (sbyte)(long)(sbyte)x; - Assert.Equal(expected, result); + return (sbyte)(long)(sbyte)x; } - [Theory] - [InlineData(0xFFFFFFFF8003L, -0x7FFD)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongShortLongShort(long x, short expected) + static short CastLongShortLongShort(long x) { //ARM64-FULL-LINE: sxth {{w[0-9]+}}, {{w[0-9]+}} - short result = (short)(long)(short)x; - Assert.Equal(expected, result); + return (short)(long)(short)x; } - [Theory] - [InlineData(0x1ABCDEF00L, -0x54321100)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastLongIntLongInt(long x, int expected) + static int CastLongIntLongInt(long x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - int result = (int)(long)(int)x; - Assert.Equal(expected, result); + return (int)(long)(int)x; } // Cast ulong -> x -> ulong -> x - [Theory] - [InlineData(0xA7ul, 0xA7)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongByteULongByte(ulong x, byte expected) + static byte CastULongByteULongByte(ulong x) { //ARM64-FULL-LINE: uxtb {{w[0-9]+}}, {{w[0-9]+}} - byte result = (byte)(ulong)(byte)x; - Assert.Equal(expected, result); + return (byte)(ulong)(byte)x; } - [Theory] - [InlineData(0xFFFFFFFF8003ul, 0x8003)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUShortULongUShort(ulong x, ushort expected) + static ushort CastULongUShortULongUShort(ulong x) { //ARM64-FULL-LINE: uxth {{w[0-9]+}}, {{w[0-9]+}} - ushort result = (ushort)(ulong)(ushort)x; - Assert.Equal(expected, result); + return (ushort)(ulong)(ushort)x; } - [Theory] - [InlineData(0x1ABCDEF00ul, 0xABCDEF00u)] [MethodImpl(MethodImplOptions.NoInlining)] - public static void CastULongUIntULongUInt(ulong x, uint expected) + static uint CastULongUIntULongUInt(ulong x) { //ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}} - uint result = (uint)(ulong)(uint)x; - Assert.Equal(expected, result); + return (uint)(ulong)(uint)x; } } }