From 9c120d8662b196bbfc03d538a167a2f7c2c842a2 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 5 Sep 2023 22:16:40 +0100 Subject: [PATCH 1/7] Reduce IL size for `BitConverter.GetBytes` --- .../src/System/BitConverter.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index 18b6ab4b0b5346..49add21107485c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -59,7 +59,7 @@ public static bool TryWriteBytes(Span destination, bool value) public static byte[] GetBytes(char value) { byte[] bytes = new byte[sizeof(char)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -86,7 +86,7 @@ public static bool TryWriteBytes(Span destination, char value) public static byte[] GetBytes(short value) { byte[] bytes = new byte[sizeof(short)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -113,7 +113,7 @@ public static bool TryWriteBytes(Span destination, short value) public static byte[] GetBytes(int value) { byte[] bytes = new byte[sizeof(int)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -140,7 +140,7 @@ public static bool TryWriteBytes(Span destination, int value) public static byte[] GetBytes(long value) { byte[] bytes = new byte[sizeof(long)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -168,7 +168,7 @@ public static bool TryWriteBytes(Span destination, long value) public static byte[] GetBytes(ushort value) { byte[] bytes = new byte[sizeof(ushort)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -197,7 +197,7 @@ public static bool TryWriteBytes(Span destination, ushort value) public static byte[] GetBytes(uint value) { byte[] bytes = new byte[sizeof(uint)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -226,7 +226,7 @@ public static bool TryWriteBytes(Span destination, uint value) public static byte[] GetBytes(ulong value) { byte[] bytes = new byte[sizeof(ulong)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -254,7 +254,7 @@ public static bool TryWriteBytes(Span destination, ulong value) public static unsafe byte[] GetBytes(Half value) { byte[] bytes = new byte[sizeof(Half)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -281,7 +281,7 @@ public static unsafe bool TryWriteBytes(Span destination, Half value) public static byte[] GetBytes(float value) { byte[] bytes = new byte[sizeof(float)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } @@ -308,7 +308,7 @@ public static bool TryWriteBytes(Span destination, float value) public static byte[] GetBytes(double value) { byte[] bytes = new byte[sizeof(double)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } From 5241e2bee4425aee6e05eb719c959c2f67c84e19 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Wed, 6 Sep 2023 23:08:33 +0100 Subject: [PATCH 2/7] Avoid spilling floating point argument --- .../src/System/BitConverter.cs | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index 49add21107485c..7a5c98d626fbdf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -251,12 +251,7 @@ public static bool TryWriteBytes(Span destination, ulong value) /// /// The number to convert. /// An array of bytes with length 2. - public static unsafe byte[] GetBytes(Half value) - { - byte[] bytes = new byte[sizeof(Half)]; - Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); - return bytes; - } + public static unsafe byte[] GetBytes(Half value) => GetBytes(HalfToInt16Bits(value)); /// /// Converts a half-precision floating-point value into a span of bytes. @@ -278,12 +273,7 @@ public static unsafe bool TryWriteBytes(Span destination, Half value) /// /// The number to convert. /// An array of bytes with length 4. - public static byte[] GetBytes(float value) - { - byte[] bytes = new byte[sizeof(float)]; - Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); - return bytes; - } + public static byte[] GetBytes(float value) => GetBytes(SingleToInt32Bits(value)); /// /// Converts a single-precision floating-point value into a span of bytes. @@ -305,12 +295,7 @@ public static bool TryWriteBytes(Span destination, float value) /// /// The number to convert. /// An array of bytes with length 8. - public static byte[] GetBytes(double value) - { - byte[] bytes = new byte[sizeof(double)]; - Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); - return bytes; - } + public static byte[] GetBytes(double value) => GetBytes(DoubleToInt64Bits(value)); /// /// Converts a double-precision floating-point value into a span of bytes. From cbe9a08c3ae17c38a34c1763f6c86e0875a33230 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Thu, 7 Sep 2023 02:08:34 +0100 Subject: [PATCH 3/7] Use unsigned casts --- .../System.Private.CoreLib/src/System/BitConverter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index 7a5c98d626fbdf..1d608db2db5a68 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -251,7 +251,7 @@ public static bool TryWriteBytes(Span destination, ulong value) /// /// The number to convert. /// An array of bytes with length 2. - public static unsafe byte[] GetBytes(Half value) => GetBytes(HalfToInt16Bits(value)); + public static unsafe byte[] GetBytes(Half value) => GetBytes(HalfToUInt16Bits(value)); /// /// Converts a half-precision floating-point value into a span of bytes. @@ -273,7 +273,7 @@ public static unsafe bool TryWriteBytes(Span destination, Half value) /// /// The number to convert. /// An array of bytes with length 4. - public static byte[] GetBytes(float value) => GetBytes(SingleToInt32Bits(value)); + public static byte[] GetBytes(float value) => GetBytes(SingleToUInt32Bits(value)); /// /// Converts a single-precision floating-point value into a span of bytes. @@ -295,7 +295,7 @@ public static bool TryWriteBytes(Span destination, float value) /// /// The number to convert. /// An array of bytes with length 8. - public static byte[] GetBytes(double value) => GetBytes(DoubleToInt64Bits(value)); + public static byte[] GetBytes(double value) => GetBytes(DoubleToUInt64Bits(value)); /// /// Converts a double-precision floating-point value into a span of bytes. From 039c509a96ef6cd76d5c823bb239f702105eb104 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Thu, 7 Sep 2023 02:11:09 +0100 Subject: [PATCH 4/7] Use `AggressiveInlining` --- .../System.Private.CoreLib/src/System/BitConverter.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index 1d608db2db5a68..45aded788444b4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -56,6 +56,7 @@ public static bool TryWriteBytes(Span destination, bool value) /// /// A Char value. /// An array of bytes with length 2. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(char value) { byte[] bytes = new byte[sizeof(char)]; @@ -83,6 +84,7 @@ public static bool TryWriteBytes(Span destination, char value) /// /// The number to convert. /// An array of bytes with length 2. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(short value) { byte[] bytes = new byte[sizeof(short)]; @@ -110,6 +112,7 @@ public static bool TryWriteBytes(Span destination, short value) /// /// The number to convert. /// An array of bytes with length 4. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(int value) { byte[] bytes = new byte[sizeof(int)]; @@ -137,6 +140,7 @@ public static bool TryWriteBytes(Span destination, int value) /// /// The number to convert. /// An array of bytes with length 8. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(long value) { byte[] bytes = new byte[sizeof(long)]; @@ -165,6 +169,7 @@ public static bool TryWriteBytes(Span destination, long value) /// The number to convert. /// An array of bytes with length 2. [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(ushort value) { byte[] bytes = new byte[sizeof(ushort)]; @@ -194,6 +199,7 @@ public static bool TryWriteBytes(Span destination, ushort value) /// The number to convert. /// An array of bytes with length 4. [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(uint value) { byte[] bytes = new byte[sizeof(uint)]; @@ -223,6 +229,7 @@ public static bool TryWriteBytes(Span destination, uint value) /// The number to convert. /// An array of bytes with length 8. [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(ulong value) { byte[] bytes = new byte[sizeof(ulong)]; From f83695980c00cbfeb3a38285b22d0dc14e3892f1 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 10 Sep 2023 19:47:03 +0100 Subject: [PATCH 5/7] Revert to 9c120d8 and add `AggressiveInlining` --- .../src/System/BitConverter.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index 45aded788444b4..a2712e8118c0ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -258,7 +258,13 @@ public static bool TryWriteBytes(Span destination, ulong value) /// /// The number to convert. /// An array of bytes with length 2. - public static unsafe byte[] GetBytes(Half value) => GetBytes(HalfToUInt16Bits(value)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe byte[] GetBytes(Half value) + { + byte[] bytes = new byte[sizeof(Half)]; + Unsafe.As(ref bytes[0]) = value; + return bytes; + } /// /// Converts a half-precision floating-point value into a span of bytes. @@ -280,7 +286,13 @@ public static unsafe bool TryWriteBytes(Span destination, Half value) /// /// The number to convert. /// An array of bytes with length 4. - public static byte[] GetBytes(float value) => GetBytes(SingleToUInt32Bits(value)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] GetBytes(float value) + { + byte[] bytes = new byte[sizeof(float)]; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); + return bytes; + } /// /// Converts a single-precision floating-point value into a span of bytes. @@ -302,7 +314,13 @@ public static bool TryWriteBytes(Span destination, float value) /// /// The number to convert. /// An array of bytes with length 8. - public static byte[] GetBytes(double value) => GetBytes(DoubleToUInt64Bits(value)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] GetBytes(double value) + { + byte[] bytes = new byte[sizeof(double)]; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); + return bytes; + } /// /// Converts a double-precision floating-point value into a span of bytes. From 377f9a0ea573e4c9217b784c233fc1b600293390 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 10 Sep 2023 19:48:05 +0100 Subject: [PATCH 6/7] fixup! --- src/libraries/System.Private.CoreLib/src/System/BitConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index a2712e8118c0ab..b0c6fb5a041fa0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -262,7 +262,7 @@ public static bool TryWriteBytes(Span destination, ulong value) public static unsafe byte[] GetBytes(Half value) { byte[] bytes = new byte[sizeof(Half)]; - Unsafe.As(ref bytes[0]) = value; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(bytes), value); return bytes; } From e7cd0dd20f29200fe9dca740d48f01af06f1037b Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 12 Sep 2023 14:26:05 +0100 Subject: [PATCH 7/7] Add `AggressiveInlining` to `GetBytes(bool)` --- src/libraries/System.Private.CoreLib/src/System/BitConverter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index b0c6fb5a041fa0..8b2ebcc6db1376 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -29,6 +29,7 @@ public static class BitConverter /// /// A Boolean value. /// A byte array with length 1. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] GetBytes(bool value) { byte[] r = new byte[1];