From 606fa6b302dcbf6d5131accf14636da107c531b0 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 09:04:16 -0800
Subject: [PATCH 01/13] Adding System.Runtime.CompilerServices.Unsafe.BitCast

---
 .../System/Runtime/CompilerServices/Unsafe.cs | 18 +++++++++
 .../tests/UnsafeTests.cs                      | 38 +++++++++++++++++++
 .../System.Runtime/ref/System.Runtime.cs      |  1 +
 3 files changed, 57 insertions(+)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
index c4c3f669819544..a82d974884aaf8 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
@@ -238,6 +238,24 @@ public static bool AreSame<T>([AllowNull] ref T left, [AllowNull] ref T right)
             // ret
         }
 
+        /// <summary>
+        /// Reinterprets the given reference as a reference to a value of type <typeparamref name="TTo"/>.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The size of <typeparamref name="TFrom" /> and <typeparamref name="TTo" /> are not the same.</exception>
+        [Intrinsic]
+        [NonVersionable]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static TTo BitCast<TFrom, TTo>(TFrom source)
+            where TFrom : struct
+            where TTo : struct
+        {
+            if (sizeof(TFrom) != sizeof(TTo))
+            {
+                ThrowHelper.ThrowNotSupportedException();
+            }
+            return As<TFrom, TTo>(ref source);
+        }
+
         /// <summary>
         /// Copies a value of type T to the given location.
         /// </summary>
diff --git a/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs b/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
index 4780b41b00ae89..c0171353f30963 100644
--- a/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
+++ b/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
+using System.Numerics;
 using System.Runtime.InteropServices;
 using Xunit;
 
@@ -1079,6 +1080,35 @@ public static unsafe void NullRef()
             Assert.Throws<NullReferenceException>(() => Unsafe.NullRef<int>() = 42);
             Assert.Throws<NullReferenceException>(() => Unsafe.NullRef<int>());
         }
+
+        [Fact]
+        public static unsafe void BitCast()
+        {
+            Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<int, long>(5));
+            Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<long, int>(5));
+
+            Assert.Equal(0x8000_0000u, Unsafe.BitCast<float, uint>(-0.0f));
+            Assert.Equal(float.PositiveInfinity, Unsafe.BitCast<uint, float>(0x7F80_0000u));
+
+            Assert.Equal(int.MinValue, Unsafe.BitCast<uint, int>(0x8000_0000u));
+            Assert.Equal(0x8000_0000u, Unsafe.BitCast<int, uint>(int.MinValue));
+
+            Vector4 vector4a = new Vector4(1.0f, 2.0f, 3.0f, 4.0f);
+            Single4 single4a = Unsafe.BitCast<Vector4, Single4>(vector4a);
+
+            Assert.Equal(1.0f, single4a.X);
+            Assert.Equal(2.0f, single4a.Y);
+            Assert.Equal(3.0f, single4a.Z);
+            Assert.Equal(4.0f, single4a.W);
+
+            Single4 single4b = new Single4 { X = -1.0f, Y = -2.0f, Z = -3.0f, W = -4.0f };
+            Vector4 vector4b = Unsafe.BitCast<Single4, Vector4>(single4b);
+
+            Assert.Equal(-1.0f, vector4b.X);
+            Assert.Equal(-2.0f, vector4b.Y);
+            Assert.Equal(-3.0f, vector4b.Z);
+            Assert.Equal(-4.0f, vector4b.W);
+        }
     }
 
     [StructLayout(LayoutKind.Explicit)]
@@ -1155,4 +1185,12 @@ public struct StringInt32
         public string String;
         public int Int32;
     }
+
+    public struct Single4
+    {
+        public float X;
+        public float Y;
+        public float Z;
+        public float W;
+    }
 }
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index 2f0d63ca45cbaa..aea5e9a20a96e9 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -12787,6 +12787,7 @@ public static partial class Unsafe
         [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("o")]
         public static T? As<T>(object? o) where T : class? { throw null; }
         public static ref TTo As<TFrom, TTo>(ref TFrom source) { throw null; }
+        public static TTo BitCast<TFrom, TTo>(TFrom source) where TFrom : struct where TTo : struct { throw null; }
         public static System.IntPtr ByteOffset<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref T origin, [System.Diagnostics.CodeAnalysis.AllowNull] ref T target) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static void CopyBlock(ref byte destination, ref byte source, uint byteCount) { }

From 978898077209794bab8a2c764574fc55ed23e4b4 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 11:08:35 -0800
Subject: [PATCH 02/13] Adding some basic intrinsic recognition for
 Unsafe.BitCast

---
 src/coreclr/jit/fgbasic.cpp          |   1 +
 src/coreclr/jit/importercalls.cpp    | 160 +++++++++++++++++++++++++++
 src/coreclr/jit/namedintrinsiclist.h |   1 +
 3 files changed, 162 insertions(+)

diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp
index 581a5aa620bef8..c008337c71ade1 100644
--- a/src/coreclr/jit/fgbasic.cpp
+++ b/src/coreclr/jit/fgbasic.cpp
@@ -1484,6 +1484,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
 #endif // FEATURE_HW_INTRINSICS
                             case NI_SRCS_UNSAFE_As:
                             case NI_SRCS_UNSAFE_AsRef:
+                            case NI_SRCS_UNSAFE_BitCast:
                             case NI_SRCS_UNSAFE_SkipInit:
                             {
                                 // TODO-CQ: These are no-ops in that they never produce any IR
diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp
index c57ecc3c71952e..f6f9fdcb1f4969 100644
--- a/src/coreclr/jit/importercalls.cpp
+++ b/src/coreclr/jit/importercalls.cpp
@@ -4002,6 +4002,162 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic        intrinsic,
             return impPopStack().val;
         }
 
+        case NI_SRCS_UNSAFE_BitCast:
+        {
+            assert(sig->sigInst.methInstCount == 2);
+
+            CORINFO_CLASS_HANDLE fromTypeHnd = sig->sigInst.methInst[0];
+            CORINFO_CLASS_HANDLE toTypeHnd   = sig->sigInst.methInst[0];
+
+            if (fromTypeHnd == toTypeHnd)
+            {
+                // Handle the easy case of matching type handles, such as `int` to `int`
+                return impPopStack().val;
+            }
+
+            unsigned fromSize = info.compCompHnd->getClassSize(fromTypeHnd);
+            unsigned toSize   = info.compCompHnd->getClassSize(toTypeHnd);
+
+            if (fromSize != toSize)
+            {
+                // Fallback to the software implementation to throw when sizes don't match
+                return nullptr;
+            }
+
+            CorInfoType fromJitType = info.compCompHnd->asCorInfoType(fromTypeHnd);
+            var_types   fromType    = JitType2PreciseVarType(fromJitType);
+
+            CorInfoType toJitType = info.compCompHnd->asCorInfoType(toTypeHnd);
+            var_types   toType    = JitType2PreciseVarType(toJitType);
+
+            bool involvesStructType = false;
+
+#if FEATURE_SIMD
+            if (fromType == TYP_STRUCT)
+            {
+                unsigned simdSize = getSIMDTypeSizeInBytes(toTypeHnd);
+
+                if (simdSize != 0)
+                {
+                    fromType = getSIMDTypeForSize(simdSize);
+                }
+                else
+                {
+                    involvesStructType = true;
+                }
+            }
+
+            if (toType == TYP_STRUCT)
+            {
+                unsigned simdSize = getSIMDTypeSizeInBytes(toTypeHnd);
+
+                if (simdSize != 0)
+                {
+                    toType = getSIMDTypeForSize(simdSize);
+                }
+                else
+                {
+                    involvesStructType = true;
+                }
+            }
+#else
+            involvesStructType = (fromType == TYP_STRUCT) || (toType == TYP_STRUCT);
+#endif // FEATURE_SIMD
+
+            if (involvesStructType)
+            {
+                // Handle the complex case where TFrom or TTo involves a non-special TYP_STRUCT
+                // TODO-CQ: There is quite a bit of specialization we "could" do here. However,
+                // due to ABI differences and other special considerations this isn't always trivial
+                return nullptr;
+            }
+
+            if (varTypeIsSIMD(fromType))
+            {
+                // Handle bitcasting for same sized simd, such as `Vector128<float>` to `Vector128<byte>`
+                assert(varTypeIsSIMD(toType) && (fromType == toType));
+                return impPopStack().val;
+            }
+
+            if (varTypeIsFloating(fromType))
+            {
+                // Handle bitcasting from floating to same sized integral, such as `float` to `int`
+                assert(varTypeIsIntegral(toType));
+
+#if !TARGET_64BIT
+                if ((fromType == TYP_DOUBLE) && !impStackTop().val->IsCnsFltOrDbl())
+                {
+                    // TODO-Cleanup: We should support this on 32-bit but it requires decomposition work
+                    return nullptr;
+                }
+#endif // !TARGET_64BIT
+
+                GenTree* op1 = impPopStack().val;
+
+                if (op1->IsCnsFltOrDbl())
+                {
+                    if (fromType == TYP_DOUBLE)
+                    {
+                        double f64Cns = static_cast<double>(op1->AsDblCon()->DconValue());
+                        return gtNewLconNode(static_cast<int64_t>(BitOperations::DoubleToUInt64Bits(f64Cns)));
+                    }
+                    else
+                    {
+                        assert(fromType == TYP_FLOAT);
+                        float f32Cns = static_cast<float>(op1->AsDblCon()->DconValue());
+                        return gtNewIconNode(static_cast<int32_t>(BitOperations::SingleToUInt32Bits(f32Cns)));
+                    }
+                }
+                else
+                {
+                    toType = varTypeToSigned(toType);
+                    op1    = impImplicitR4orR8Cast(op1, fromType);
+                    return gtNewBitCastNode(toType, op1);
+                }
+                break;
+            }
+
+            if (varTypeIsFloating(toType))
+            {
+                // Handle bitcasting from integral to same sized floating, such as `int` to `float`
+                assert(varTypeIsIntegral(fromType));
+
+#if !TARGET_64BIT
+                if ((toType == TYP_DOUBLE) && !impStackTop().val->IsIntegralConst())
+                {
+                    // TODO-Cleanup: We should support this on 32-bit but it requires decomposition work
+                    return nullptr;
+                }
+#endif // !TARGET_64BIT
+
+                GenTree* op1 = impPopStack().val;
+
+                if (op1->IsIntegralConst())
+                {
+                    if (toType == TYP_DOUBLE)
+                    {
+                        uint64_t u64Cns = static_cast<uint64_t>(op1->AsIntConCommon()->LngValue());
+                        return gtNewDconNode(BitOperations::UInt64BitsToDouble(u64Cns), TYP_DOUBLE);
+                    }
+                    else
+                    {
+                        assert(toType == TYP_FLOAT);
+
+                        uint32_t u32Cns = static_cast<uint32_t>(op1->AsIntConCommon()->IconValue());
+                        return gtNewDconNode(BitOperations::UInt32BitsToSingle(u32Cns), TYP_FLOAT);
+                    }
+                }
+                else
+                {
+                    return gtNewBitCastNode(toType, op1);
+                }
+                break;
+            }
+
+            // Handle bitcasting for same sized integrals, such as `int` to `uint`
+            return impPopStack().val;
+        }
+
         case NI_SRCS_UNSAFE_ByteOffset:
         {
             assert(sig->sigInst.methInstCount == 1);
@@ -8202,6 +8358,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
                         {
                             result = NI_SRCS_UNSAFE_AsRef;
                         }
+                        else if (strcmp(methodName, "BitCast") == 0)
+                        {
+                            result = NI_SRCS_UNSAFE_BitCast;
+                        }
                         else if (strcmp(methodName, "ByteOffset") == 0)
                         {
                             result = NI_SRCS_UNSAFE_ByteOffset;
diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h
index 4f922bcb234fdb..b80a1b3254aef1 100644
--- a/src/coreclr/jit/namedintrinsiclist.h
+++ b/src/coreclr/jit/namedintrinsiclist.h
@@ -179,6 +179,7 @@ enum NamedIntrinsic : unsigned short
     NI_SRCS_UNSAFE_As,
     NI_SRCS_UNSAFE_AsPointer,
     NI_SRCS_UNSAFE_AsRef,
+    NI_SRCS_UNSAFE_BitCast,
     NI_SRCS_UNSAFE_ByteOffset,
     NI_SRCS_UNSAFE_Copy,
     NI_SRCS_UNSAFE_CopyBlock,

From a8bd8a6ce58314bd56874fde7cfc9604c14b7fbe Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 12:54:19 -0800
Subject: [PATCH 03/13] Use ClassLayout::AreCompatible as part of
 Unsafe.BitCast

---
 src/coreclr/jit/importercalls.cpp | 51 ++++++++++---------------------
 1 file changed, 16 insertions(+), 35 deletions(-)

diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp
index f6f9fdcb1f4969..1f82084d7a9e17 100644
--- a/src/coreclr/jit/importercalls.cpp
+++ b/src/coreclr/jit/importercalls.cpp
@@ -4025,60 +4025,41 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic        intrinsic,
             }
 
             CorInfoType fromJitType = info.compCompHnd->asCorInfoType(fromTypeHnd);
-            var_types   fromType    = JitType2PreciseVarType(fromJitType);
+            var_types   fromType    = JITtype2varType(fromJitType);
 
             CorInfoType toJitType = info.compCompHnd->asCorInfoType(toTypeHnd);
-            var_types   toType    = JitType2PreciseVarType(toJitType);
+            var_types   toType    = JITtype2varType(toJitType);
 
             bool involvesStructType = false;
 
-#if FEATURE_SIMD
             if (fromType == TYP_STRUCT)
             {
-                unsigned simdSize = getSIMDTypeSizeInBytes(toTypeHnd);
+                involvesStructType = true;
 
-                if (simdSize != 0)
+                if (toType == TYP_STRUCT)
                 {
-                    fromType = getSIMDTypeForSize(simdSize);
-                }
-                else
-                {
-                    involvesStructType = true;
+                    ClassLayout* fromLayout = typGetObjLayout(fromTypeHnd);
+                    ClassLayout* toLayout   = typGetObjLayout(toTypeHnd);
+
+                    if (ClassLayout::AreCompatible(fromLayout, toLayout))
+                    {
+                        // Handle compatible struct layouts where we can simply return op1
+                        return impPopStack().val;
+                    }
                 }
             }
-
-            if (toType == TYP_STRUCT)
+            else if (toType == TYP_STRUCT)
             {
-                unsigned simdSize = getSIMDTypeSizeInBytes(toTypeHnd);
-
-                if (simdSize != 0)
-                {
-                    toType = getSIMDTypeForSize(simdSize);
-                }
-                else
-                {
-                    involvesStructType = true;
-                }
+                involvesStructType = true;
             }
-#else
-            involvesStructType = (fromType == TYP_STRUCT) || (toType == TYP_STRUCT);
-#endif // FEATURE_SIMD
 
             if (involvesStructType)
             {
-                // Handle the complex case where TFrom or TTo involves a non-special TYP_STRUCT
-                // TODO-CQ: There is quite a bit of specialization we "could" do here. However,
-                // due to ABI differences and other special considerations this isn't always trivial
+                // TODO-CQ: Handle this by getting the address of `op1` and then dereferencing
+                // that as TTo, much as `Unsafe.As<TFrom, TTo>(ref op1)` would work.
                 return nullptr;
             }
 
-            if (varTypeIsSIMD(fromType))
-            {
-                // Handle bitcasting for same sized simd, such as `Vector128<float>` to `Vector128<byte>`
-                assert(varTypeIsSIMD(toType) && (fromType == toType));
-                return impPopStack().val;
-            }
-
             if (varTypeIsFloating(fromType))
             {
                 // Handle bitcasting from floating to same sized integral, such as `float` to `int`

From 38e4b87d2f4796366e0cda6a74491a2bf754da81 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 13:03:07 -0800
Subject: [PATCH 04/13] Fixup BitConverter to use Unsafe.BitCast

---
 .../src/System/BitConverter.cs                   | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs
index f8e965bf4ed825..b9dd9d938b4202 100644
--- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs
@@ -764,7 +764,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <param name="value">The number to convert.</param>
         /// <returns>A 64-bit signed integer whose bits are identical to <paramref name="value"/>.</returns>
         [Intrinsic]
-        public static unsafe long DoubleToInt64Bits(double value) => *((long*)&value);
+        public static unsafe long DoubleToInt64Bits(double value) => Unsafe.BitCast<double, long>(value);
 
         /// <summary>
         /// Converts the specified 64-bit signed integer to a double-precision floating point number.
@@ -772,7 +772,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <param name="value">The number to convert.</param>
         /// <returns>A double-precision floating point number whose bits are identical to <paramref name="value"/>.</returns>
         [Intrinsic]
-        public static unsafe double Int64BitsToDouble(long value) => *((double*)&value);
+        public static unsafe double Int64BitsToDouble(long value) => Unsafe.BitCast<long, double>(value);
 
         /// <summary>
         /// Converts the specified single-precision floating point number to a 32-bit signed integer.
@@ -780,7 +780,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <param name="value">The number to convert.</param>
         /// <returns>A 32-bit signed integer whose bits are identical to <paramref name="value"/>.</returns>
         [Intrinsic]
-        public static unsafe int SingleToInt32Bits(float value) => *((int*)&value);
+        public static unsafe int SingleToInt32Bits(float value) => Unsafe.BitCast<float, int>(value);
 
         /// <summary>
         /// Converts the specified 32-bit signed integer to a single-precision floating point number.
@@ -788,7 +788,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <param name="value">The number to convert.</param>
         /// <returns>A single-precision floating point number whose bits are identical to <paramref name="value"/>.</returns>
         [Intrinsic]
-        public static unsafe float Int32BitsToSingle(int value) => *((float*)&value);
+        public static unsafe float Int32BitsToSingle(int value) => Unsafe.BitCast<int, float>(value);
 
         /// <summary>
         /// Converts the specified half-precision floating point number to a 16-bit signed integer.
@@ -813,7 +813,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <returns>A 64-bit unsigned integer whose bits are identical to <paramref name="value"/>.</returns>
         [CLSCompliant(false)]
         [Intrinsic]
-        public static unsafe ulong DoubleToUInt64Bits(double value) => *((ulong*)&value);
+        public static unsafe ulong DoubleToUInt64Bits(double value) => Unsafe.BitCast<double, ulong>(value);
 
         /// <summary>
         /// Converts the specified 64-bit unsigned integer to a double-precision floating point number.
@@ -822,7 +822,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <returns>A double-precision floating point number whose bits are identical to <paramref name="value"/>.</returns>
         [CLSCompliant(false)]
         [Intrinsic]
-        public static unsafe double UInt64BitsToDouble(ulong value) => *((double*)&value);
+        public static unsafe double UInt64BitsToDouble(ulong value) => Unsafe.BitCast<ulong, double>(value);
 
         /// <summary>
         /// Converts the specified single-precision floating point number to a 32-bit unsigned integer.
@@ -831,7 +831,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <returns>A 32-bit unsigned integer whose bits are identical to <paramref name="value"/>.</returns>
         [CLSCompliant(false)]
         [Intrinsic]
-        public static unsafe uint SingleToUInt32Bits(float value) => *((uint*)&value);
+        public static unsafe uint SingleToUInt32Bits(float value) => Unsafe.BitCast<float, uint>(value);
 
         /// <summary>
         /// Converts the specified 32-bit unsigned integer to a single-precision floating point number.
@@ -840,7 +840,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
         /// <returns>A single-precision floating point number whose bits are identical to <paramref name="value"/>.</returns>
         [CLSCompliant(false)]
         [Intrinsic]
-        public static unsafe float UInt32BitsToSingle(uint value) => *((float*)&value);
+        public static unsafe float UInt32BitsToSingle(uint value) => Unsafe.BitCast<uint, float>(value);
 
         /// <summary>
         /// Converts the specified half-precision floating point number to a 16-bit unsigned integer.

From 5cdf971f655b24b7c94b62eb9ea871bcd3902bf1 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 13:10:37 -0800
Subject: [PATCH 05/13] Fixup Enum to use Unsafe.BitCast

---
 .../System.Private.CoreLib/src/System/Enum.cs | 156 +++++++++---------
 1 file changed, 78 insertions(+), 78 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs
index 534823f28956f7..2fc820c4ee6d16 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs
@@ -46,20 +46,20 @@ public abstract partial class Enum : ValueType, IComparable, ISpanFormattable, I
             RuntimeType rt = (RuntimeType)typeof(TEnum);
             Type underlyingType = typeof(TEnum).GetEnumUnderlyingType();
 
-            if (underlyingType == typeof(sbyte)) return GetNameInlined(GetEnumInfo<sbyte>(rt), *(sbyte*)&value);
-            if (underlyingType == typeof(byte)) return GetNameInlined(GetEnumInfo<byte>(rt), *(byte*)&value);
-            if (underlyingType == typeof(short)) return GetNameInlined(GetEnumInfo<short>(rt), *(short*)&value);
-            if (underlyingType == typeof(ushort)) return GetNameInlined(GetEnumInfo<ushort>(rt), *(ushort*)&value);
-            if (underlyingType == typeof(int)) return GetNameInlined(GetEnumInfo<int>(rt), *(int*)&value);
-            if (underlyingType == typeof(uint)) return GetNameInlined(GetEnumInfo<uint>(rt), *(uint*)&value);
-            if (underlyingType == typeof(long)) return GetNameInlined(GetEnumInfo<long>(rt), *(long*)&value);
-            if (underlyingType == typeof(ulong)) return GetNameInlined(GetEnumInfo<ulong>(rt), *(ulong*)&value);
+            if (underlyingType == typeof(sbyte)) return GetNameInlined(GetEnumInfo<sbyte>(rt), Unsafe.BitCast<TEnum, sbyte>(value));
+            if (underlyingType == typeof(byte)) return GetNameInlined(GetEnumInfo<byte>(rt), Unsafe.BitCast<TEnum, byte>(value));
+            if (underlyingType == typeof(short)) return GetNameInlined(GetEnumInfo<short>(rt), Unsafe.BitCast<TEnum, short>(value));
+            if (underlyingType == typeof(ushort)) return GetNameInlined(GetEnumInfo<ushort>(rt), Unsafe.BitCast<TEnum, ushort>(value));
+            if (underlyingType == typeof(int)) return GetNameInlined(GetEnumInfo<int>(rt), Unsafe.BitCast<TEnum, int>(value));
+            if (underlyingType == typeof(uint)) return GetNameInlined(GetEnumInfo<uint>(rt), Unsafe.BitCast<TEnum, uint>(value));
+            if (underlyingType == typeof(long)) return GetNameInlined(GetEnumInfo<long>(rt), Unsafe.BitCast<TEnum, long>(value));
+            if (underlyingType == typeof(ulong)) return GetNameInlined(GetEnumInfo<ulong>(rt), Unsafe.BitCast<TEnum, ulong>(value));
 #if RARE_ENUMS
-            if (underlyingType == typeof(nint)) return GetNameInlined(GetEnumInfo<nint>(rt), *(nint*)&value);
-            if (underlyingType == typeof(nuint)) return GetNameInlined(GetEnumInfo<nuint>(rt), *(nuint*)&value);
-            if (underlyingType == typeof(float)) return GetNameInlined(GetEnumInfo<float>(rt), *(float*)&value);
-            if (underlyingType == typeof(double)) return GetNameInlined(GetEnumInfo<double>(rt), *(double*)&value);
-            if (underlyingType == typeof(char)) return GetNameInlined(GetEnumInfo<char>(rt), *(char*)&value);
+            if (underlyingType == typeof(nint)) return GetNameInlined(GetEnumInfo<nint>(rt), Unsafe.BitCast<TEnum, nint>(value));
+            if (underlyingType == typeof(nuint)) return GetNameInlined(GetEnumInfo<nuint>(rt), Unsafe.BitCast<TEnum, nuint>(value));
+            if (underlyingType == typeof(float)) return GetNameInlined(GetEnumInfo<float>(rt), Unsafe.BitCast<TEnum, float>(value));
+            if (underlyingType == typeof(double)) return GetNameInlined(GetEnumInfo<double>(rt), Unsafe.BitCast<TEnum, double>(value));
+            if (underlyingType == typeof(char)) return GetNameInlined(GetEnumInfo<char>(rt), Unsafe.BitCast<TEnum, char>(value));
 #endif
             throw CreateUnknownEnumTypeException();
         }
@@ -473,20 +473,20 @@ public static unsafe bool IsDefined<TEnum>(TEnum value) where TEnum : struct, En
             RuntimeType rt = (RuntimeType)typeof(TEnum);
             Type underlyingType = typeof(TEnum).GetEnumUnderlyingType();
 
-            if (underlyingType == typeof(sbyte)) return IsDefinedPrimitive(rt, *(sbyte*)&value);
-            if (underlyingType == typeof(byte)) return IsDefinedPrimitive(rt, *(byte*)&value);
-            if (underlyingType == typeof(short)) return IsDefinedPrimitive(rt, *(short*)&value);
-            if (underlyingType == typeof(ushort)) return IsDefinedPrimitive(rt, *(ushort*)&value);
-            if (underlyingType == typeof(int)) return IsDefinedPrimitive(rt, *(int*)&value);
-            if (underlyingType == typeof(uint)) return IsDefinedPrimitive(rt, *(uint*)&value);
-            if (underlyingType == typeof(long)) return IsDefinedPrimitive(rt, *(long*)&value);
-            if (underlyingType == typeof(ulong)) return IsDefinedPrimitive(rt, *(ulong*)&value);
+            if (underlyingType == typeof(sbyte)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, sbyte>(value));
+            if (underlyingType == typeof(byte)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, byte>(value));
+            if (underlyingType == typeof(short)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, short>(value));
+            if (underlyingType == typeof(ushort)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, ushort>(value));
+            if (underlyingType == typeof(int)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, int>(value));
+            if (underlyingType == typeof(uint)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, uint>(value));
+            if (underlyingType == typeof(long)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, long>(value));
+            if (underlyingType == typeof(ulong)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, ulong>(value));
 #if RARE_ENUMS
-            if (underlyingType == typeof(nint)) return IsDefinedPrimitive(rt, *(nint*)&value);
-            if (underlyingType == typeof(nuint)) return IsDefinedPrimitive(rt, *(nuint*)&value);
-            if (underlyingType == typeof(float)) return IsDefinedPrimitive(rt, *(float*)&value);
-            if (underlyingType == typeof(double)) return IsDefinedPrimitive(rt, *(double*)&value);
-            if (underlyingType == typeof(char)) return IsDefinedPrimitive(rt, *(char*)&value);
+            if (underlyingType == typeof(nint)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, nint>(value));
+            if (underlyingType == typeof(nuint)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, nuint>(value));
+            if (underlyingType == typeof(float)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, float>(value));
+            if (underlyingType == typeof(double)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, double>(value));
+            if (underlyingType == typeof(char)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, char>(value));
 #endif
 
             throw CreateUnknownEnumTypeException();
@@ -1753,38 +1753,38 @@ public static unsafe bool TryFormat<TEnum>(TEnum value, Span<char> destination,
             // be necessary for semantics inside of TryFormatPrimitiveNonDefault, so we can just do it here instead.
             if (format.IsEmpty)
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, *(int*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, *(uint*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, *(long*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, *(ulong*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, *(byte*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, *(sbyte*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, *(short*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, *(ushort*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, *(nint*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, *(nuint*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, *(float*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, *(double*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, *(char*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten);
 #endif
             }
             else
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, *(int*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, *(uint*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, *(long*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, *(ulong*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, *(byte*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, *(sbyte*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, *(short*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, *(ushort*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten, format);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, *(nint*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, *(nuint*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, *(float*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, *(double*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, *(char*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten, format);
 #endif
             }
 
@@ -1812,38 +1812,38 @@ internal static unsafe bool TryFormatUnconstrained<TEnum>(TEnum value, Span<char
             // be necessary for semantics inside of TryFormatPrimitiveNonDefault, so we can just do it here instead.
             if (format.IsEmpty)
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, *(int*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, *(uint*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, *(long*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, *(ulong*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, *(byte*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, *(sbyte*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, *(short*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, *(ushort*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, *(nint*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, *(nuint*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, *(float*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, *(double*)&value, destination, out charsWritten);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, *(char*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten);
 #endif
             }
             else
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, *(int*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, *(uint*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, *(long*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, *(ulong*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, *(byte*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, *(sbyte*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, *(short*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, *(ushort*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten, format);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, *(nint*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, *(nuint*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, *(float*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, *(double*)&value, destination, out charsWritten, format);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, *(char*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten, format);
 #endif
             }
 

From df296f4ea3a6d8792e257464cce216877d9f1b45 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 13:20:35 -0800
Subject: [PATCH 06/13] Ensure BitCast resolves the right generic type for
 toTypeHnd

---
 src/coreclr/jit/importercalls.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp
index 1f82084d7a9e17..3a2273232afbcc 100644
--- a/src/coreclr/jit/importercalls.cpp
+++ b/src/coreclr/jit/importercalls.cpp
@@ -4007,7 +4007,7 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic        intrinsic,
             assert(sig->sigInst.methInstCount == 2);
 
             CORINFO_CLASS_HANDLE fromTypeHnd = sig->sigInst.methInst[0];
-            CORINFO_CLASS_HANDLE toTypeHnd   = sig->sigInst.methInst[0];
+            CORINFO_CLASS_HANDLE toTypeHnd   = sig->sigInst.methInst[1];
 
             if (fromTypeHnd == toTypeHnd)
             {

From aae3cfdf0a08203b5978a2ad43104b71b29443f5 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 13:56:40 -0800
Subject: [PATCH 07/13] Use Unsafe.BitCast in places using the `*(TTo*)&tfrom`
 pattern

---
 .../System/Data/ProviderBase/DbBuffer.cs      |  4 +-
 .../src/System/Data/ProviderBase/DbBuffer.cs  |  4 +-
 .../Parser/ValidateParser.cs                  | 18 +++----
 .../src/System/Decimal.DecCalc.cs             |  4 +-
 .../IndexOfAnyValues/IndexOfAny4Values.cs     | 11 ++---
 .../IndexOfAnyValues/IndexOfAny5Values.cs     | 13 +++--
 .../System.Private.CoreLib/src/System/Span.cs |  2 +-
 .../src/System/SpanHelpers.Packed.cs          |  2 +-
 .../src/System/SpanHelpers.T.cs               | 18 +++----
 .../src/System/Threading/Volatile.cs          |  4 +-
 .../src/System/Xml/XmlConverter.cs            |  6 +--
 .../Internal/Utilities/BlobUtilities.cs       |  4 +-
 .../Converters/Value/EnumConverter.cs         | 48 +++++++++----------
 13 files changed, 64 insertions(+), 74 deletions(-)

diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs
index 4c9bf45e2d9bd5..9ef1e0f7b90990 100644
--- a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs
+++ b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs
@@ -365,7 +365,7 @@ internal IntPtr ReadIntPtr(int offset)
         internal unsafe float ReadSingle(int offset)
         {
             int value = ReadInt32(offset);
-            return *(float*)&value;
+            return BitConverter.Int32BitsToSingle(value);
         }
 
         protected override bool ReleaseHandle()
@@ -636,7 +636,7 @@ internal void WriteIntPtr(int offset, IntPtr value)
 
         internal unsafe void WriteSingle(int offset, float value)
         {
-            WriteInt32(offset, *(int*)&value);
+            WriteInt32(offset, BitConverter.SingleToInt32Bits(value));
         }
 
         internal void ZeroMemory()
diff --git a/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbBuffer.cs b/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbBuffer.cs
index dac3f186abc154..ef399eff362088 100644
--- a/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbBuffer.cs
+++ b/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbBuffer.cs
@@ -344,7 +344,7 @@ internal IntPtr ReadIntPtr(int offset)
         internal unsafe float ReadSingle(int offset)
         {
             int value = ReadInt32(offset);
-            return *(float*)&value;
+            return BitConverter.Int32BitsToSingle(value);
         }
 
         protected override bool ReleaseHandle()
@@ -615,7 +615,7 @@ internal void WriteIntPtr(int offset, IntPtr value)
 
         internal unsafe void WriteSingle(int offset, float value)
         {
-            WriteInt32(offset, *(int*)&value);
+            WriteInt32(offset, BitConverter.SingleToInt32Bits(value));
         }
 
         internal Guid ReadGuid(int offset)
diff --git a/src/libraries/System.Memory/tests/ParsersAndFormatters/Parser/ValidateParser.cs b/src/libraries/System.Memory/tests/ParsersAndFormatters/Parser/ValidateParser.cs
index 6ecd116b05e04e..aae401f07b7118 100644
--- a/src/libraries/System.Memory/tests/ParsersAndFormatters/Parser/ValidateParser.cs
+++ b/src/libraries/System.Memory/tests/ParsersAndFormatters/Parser/ValidateParser.cs
@@ -106,13 +106,10 @@ private static bool IsParsedValueEqual<T>(T expected, T actual)
                 double expectedDouble = (double)(object)expected;
                 double actualDouble = (double)(object)actual;
 
-                unsafe
-                {
-                    if (*((ulong*)&expectedDouble) != *((ulong*)&actualDouble))
-                        return false;
+                if (BitConverter.DoubleToUInt64Bits(expectedDouble) != BitConverter.DoubleToUInt64Bits(actualDouble))
+                    return false;
 
-                    return true;
-                }
+                return true;
             }
 
             // Parsed floating points are constructed, not computed. Thus, we can do the exact compare.
@@ -121,13 +118,10 @@ private static bool IsParsedValueEqual<T>(T expected, T actual)
                 float expectedSingle = (float)(object)expected;
                 float actualSingle = (float)(object)actual;
 
-                unsafe
-                {
-                    if (*((uint*)&expectedSingle) != *((uint*)&actualSingle))
-                        return false;
+                if (BitConverter.SingleToUInt32Bits(expectedSingle) != BitConverter.SingleToUInt32Bits(actualSingle))
+                    return false;
 
-                    return true;
-                }
+                return true;
             }
 
             return expected.Equals(actual);
diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs
index 03d4943b493c4d..bd9a70b6edf415 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs
@@ -160,7 +160,7 @@ private static unsafe uint GetExponent(float f)
                 //    ULONG sign:1;
                 // } SNGSTRUCT;
 
-                return (byte)(*(uint*)&f >> 23);
+                return (byte)(BitConverter.SingleToUInt32Bits(f) >> 23);
             }
 
             private static unsafe uint GetExponent(double d)
@@ -171,7 +171,7 @@ private static unsafe uint GetExponent(double d)
                 //   DWORDLONG signexp:12;
                 // } DBLSTRUCT;
 
-                return (uint)(*(ulong*)&d >> 52) & 0x7FFu;
+                return (uint)(BitConverter.DoubleToUInt64Bits(d) >> 52) & 0x7FFu;
             }
 
             private static ulong UInt32x32To64(uint a, uint b)
diff --git a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs
index c23839310933cf..0746c401ea3ebe 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs
@@ -25,16 +25,15 @@ public IndexOfAny4Values(ReadOnlySpan<TImpl> values)
 
         internal override unsafe T[] GetValues()
         {
-            TImpl e0 = _e0, e1 = _e1, e2 = _e2, e3 = _e3;
-            return new[] { *(T*)&e0, *(T*)&e1, *(T*)&e2, *(T*)&e3 };
+            return new[] { Unsafe.BitCast<TImpl, T>(_e0), Unsafe.BitCast<TImpl, T>(_e1), Unsafe.BitCast<TImpl, T>(_e2), Unsafe.BitCast<TImpl, T>(_e3) };
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override unsafe bool ContainsCore(T value) =>
-            *(TImpl*)&value == _e0 ||
-            *(TImpl*)&value == _e1 ||
-            *(TImpl*)&value == _e2 ||
-            *(TImpl*)&value == _e3;
+            Unsafe.BitCast<T, TImpl>(value) == _e0 ||
+            Unsafe.BitCast<T, TImpl>(value) == _e1 ||
+            Unsafe.BitCast<T, TImpl>(value) == _e2 ||
+            Unsafe.BitCast<T, TImpl>(value) == _e3;
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override int IndexOfAny(ReadOnlySpan<T> span) =>
diff --git a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs
index 55660a22b99f12..75d182a6806c7a 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs
@@ -25,17 +25,16 @@ public IndexOfAny5Values(ReadOnlySpan<TImpl> values)
 
         internal override unsafe T[] GetValues()
         {
-            TImpl e0 = _e0, e1 = _e1, e2 = _e2, e3 = _e3, e4 = _e4;
-            return new[] { *(T*)&e0, *(T*)&e1, *(T*)&e2, *(T*)&e3, *(T*)&e4 };
+            return new[] { Unsafe.BitCast<TImpl, T>(_e0), Unsafe.BitCast<TImpl, T>(_e1), Unsafe.BitCast<TImpl, T>(_e2), Unsafe.BitCast<TImpl, T>(_e3), Unsafe.BitCast<TImpl, T>(_e4) };
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override unsafe bool ContainsCore(T value) =>
-            *(TImpl*)&value == _e0 ||
-            *(TImpl*)&value == _e1 ||
-            *(TImpl*)&value == _e2 ||
-            *(TImpl*)&value == _e3 ||
-            *(TImpl*)&value == _e4;
+            Unsafe.BitCast<T, TImpl>(value) == _e0 ||
+            Unsafe.BitCast<T, TImpl>(value) == _e1 ||
+            Unsafe.BitCast<T, TImpl>(value) == _e2 ||
+            Unsafe.BitCast<T, TImpl>(value) == _e3 ||
+            Unsafe.BitCast<T, TImpl>(value) == _e4;
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override int IndexOfAny(ReadOnlySpan<T> span) =>
diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs
index 26e32ffb4cfd08..74d2407ff3003e 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Span.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs
@@ -305,7 +305,7 @@ public unsafe void Fill(T value)
                 // The runtime eventually calls memset, which can efficiently support large buffers.
                 // We don't need to check IsReferenceOrContainsReferences because no references
                 // can ever be stored in types this small.
-                Unsafe.InitBlockUnaligned(ref Unsafe.As<T, byte>(ref _reference), *(byte*)&value, (uint)_length);
+                Unsafe.InitBlockUnaligned(ref Unsafe.As<T, byte>(ref _reference), Unsafe.BitCast<T, byte>(value), (uint)_length);
             }
             else
             {
diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs
index 9e8272671dd692..44f9778a9a3ee8 100644
--- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs
@@ -30,7 +30,7 @@ public static unsafe bool CanUsePackedIndexOf<T>(T value)
             Debug.Assert(RuntimeHelpers.IsBitwiseEquatable<T>());
             Debug.Assert(sizeof(T) == sizeof(ushort));
 
-            return *(ushort*)&value - 1u < 254u;
+            return Unsafe.BitCast<T, ushort>(value) - 1u < 254u;
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs
index 11c79ef0b76af6..7b78bde92f3fb5 100644
--- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs
@@ -1309,7 +1309,7 @@ internal static unsafe bool ContainsValueType<T>(ref T searchSpace, T value, int
         {
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(T) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value))
             {
-                return PackedSpanHelpers.Contains(ref Unsafe.As<T, short>(ref searchSpace), *(short*)&value, length);
+                return PackedSpanHelpers.Contains(ref Unsafe.As<T, short>(ref searchSpace), Unsafe.BitCast<T, short>(value), length);
             }
 
             return NonPackedContainsValueType(ref searchSpace, value, length);
@@ -1456,8 +1456,8 @@ private static unsafe int IndexOfValueType<TValue, TNegator>(ref TValue searchSp
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value))
             {
                 return typeof(TNegator) == typeof(DontNegate<short>)
-                    ? PackedSpanHelpers.IndexOf(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value, length)
-                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value, length);
+                    ? PackedSpanHelpers.IndexOf(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value), length)
+                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value), length);
             }
 
             return NonPackedIndexOfValueType<TValue, TNegator>(ref searchSpace, value, length);
@@ -1613,8 +1613,8 @@ private static unsafe int IndexOfAnyValueType<TValue, TNegator>(ref TValue searc
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1))
             {
                 return typeof(TNegator) == typeof(DontNegate<short>)
-                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, length)
-                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, length);
+                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), length)
+                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), length);
             }
 
             return NonPackedIndexOfAnyValueType<TValue, TNegator>(ref searchSpace, value0, value1, length);
@@ -1790,8 +1790,8 @@ private static unsafe int IndexOfAnyValueType<TValue, TNegator>(ref TValue searc
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1) && PackedSpanHelpers.CanUsePackedIndexOf(value2))
             {
                 return typeof(TNegator) == typeof(DontNegate<short>)
-                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, *(char*)&value2, length)
-                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, *(char*)&value2, length);
+                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), Unsafe.BitCast<TValue, char>(value2), length)
+                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), Unsafe.BitCast<TValue, char>(value2), length);
             }
 
             return NonPackedIndexOfAnyValueType<TValue, TNegator>(ref searchSpace, value0, value1, value2, length);
@@ -3093,8 +3093,8 @@ private static unsafe int IndexOfAnyInRangeUnsignedNumber<T, TNegator>(ref T sea
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(T) == typeof(ushort) && PackedSpanHelpers.CanUsePackedIndexOf(lowInclusive) && PackedSpanHelpers.CanUsePackedIndexOf(highInclusive) && highInclusive >= lowInclusive)
             {
                 ref char charSearchSpace = ref Unsafe.As<T, char>(ref searchSpace);
-                char charLowInclusive = *(char*)&lowInclusive;
-                char charRange = (char)(*(char*)&highInclusive - charLowInclusive);
+                char charLowInclusive = Unsafe.BitCast<T, char>(lowInclusive);
+                char charRange = (char)(Unsafe.BitCast<T, char>(highInclusive) - charLowInclusive);
 
                 return typeof(TNegator) == typeof(DontNegate<ushort>)
                     ? PackedSpanHelpers.IndexOfAnyInRange(ref charSearchSpace, charLowInclusive, charRange, length)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Volatile.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Volatile.cs
index 80b2a21932e487..aeba3db6279a9c 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/Volatile.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Volatile.cs
@@ -47,13 +47,13 @@ public static void Write(ref byte location, byte value) =>
         public static double Read(ref double location)
         {
             long result = Read(ref Unsafe.As<double, long>(ref location));
-            return *(double*)&result;
+            return BitConverter.Int64BitsToDouble(result);
         }
 
         [Intrinsic]
         [NonVersionable]
         public static void Write(ref double location, double value) =>
-            Write(ref Unsafe.As<double, long>(ref location), *(long*)&value);
+            Write(ref Unsafe.As<double, long>(ref location), BitConverter.DoubleToInt64Bits(value));
         #endregion
 
         #region Int16
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs
index 71867bf458deac..3420846d339a26 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs
@@ -710,15 +710,13 @@ public static int ToCharsR(long value, byte[] chars, int offset)
         private static unsafe bool IsNegativeZero(float value)
         {
             // Simple equals function will report that -0 is equal to +0, so compare bits instead
-            float negativeZero = -0e0F;
-            return (*(int*)&value == *(int*)&negativeZero);
+            return BitConverter.SingleToUInt32Bits(value) == 0x8000_0000U;
         }
 
         private static unsafe bool IsNegativeZero(double value)
         {
             // Simple equals function will report that -0 is equal to +0, so compare bits instead
-            double negativeZero = -0e0;
-            return (*(long*)&value == *(long*)&negativeZero);
+            return BitConverter.DoubleToUInt64Bits(value) == 0x8000_0000_0000_0000UL;
         }
 
         private static int ToInfinity(bool isNegative, byte[] buffer, int offset)
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
index 8f3a1321c284c6..b29f5819cdcc49 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
@@ -20,12 +20,12 @@ public static void WriteBytes(this byte[] buffer, int start, byte value, int byt
 
         public static void WriteDouble(this byte[] buffer, int start, double value)
         {
-            WriteUInt64(buffer, start, *(ulong*)&value);
+            WriteUInt64(buffer, start, BitConverter.DoubleToUInt64Bits(value));
         }
 
         public static void WriteSingle(this byte[] buffer, int start, float value)
         {
-            WriteUInt32(buffer, start, *(uint*)&value);
+            WriteUInt32(buffer, start, BitConverter.SingleToUInt32Bits(value));
         }
 
         public static void WriteByte(this byte[] buffer, int start, byte value)
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
index fe4779f87190f0..a38c2dbee1e19c 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
@@ -136,49 +136,49 @@ public override unsafe T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso
                 case TypeCode.Int32:
                     if (reader.TryGetInt32(out int int32))
                     {
-                        return *(T*)&int32;
+                        return Unsafe.BitCast<int, T>(int32);
                     }
                     break;
                 case TypeCode.UInt32:
                     if (reader.TryGetUInt32(out uint uint32))
                     {
-                        return *(T*)&uint32;
+                        return Unsafe.BitCast<uint, T>(uint32);
                     }
                     break;
                 case TypeCode.UInt64:
                     if (reader.TryGetUInt64(out ulong uint64))
                     {
-                        return *(T*)&uint64;
+                        return Unsafe.BitCast<ulong, T>(uint64)
                     }
                     break;
                 case TypeCode.Int64:
                     if (reader.TryGetInt64(out long int64))
                     {
-                        return *(T*)&int64;
+                        return Unsafe.BitCast<long, T>(int64);
                     }
                     break;
                 case TypeCode.SByte:
                     if (reader.TryGetSByte(out sbyte byte8))
                     {
-                        return *(T*)&byte8;
+                        return Unsafe.BitCast<sbyte, T>(byte8);
                     }
                     break;
                 case TypeCode.Byte:
                     if (reader.TryGetByte(out byte ubyte8))
                     {
-                        return *(T*)&ubyte8;
+                        return Unsafe.BitCast<byte, T>(ubyte8);
                     }
                     break;
                 case TypeCode.Int16:
                     if (reader.TryGetInt16(out short int16))
                     {
-                        return *(T*)&int16;
+                        return Unsafe.BitCast<short, T>(int16);
                     }
                     break;
                 case TypeCode.UInt16:
                     if (reader.TryGetUInt16(out ushort uint16))
                     {
-                        return *(T*)&uint16;
+                        return Unsafe.BitCast<ushort, T>(uint16);
                     }
                     break;
             }
@@ -235,28 +235,28 @@ public override unsafe void Write(Utf8JsonWriter writer, T value, JsonSerializer
             switch (s_enumTypeCode)
             {
                 case TypeCode.Int32:
-                    writer.WriteNumberValue(*(int*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, int>(value));
                     break;
                 case TypeCode.UInt32:
-                    writer.WriteNumberValue(*(uint*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, uint>(value));
                     break;
                 case TypeCode.UInt64:
-                    writer.WriteNumberValue(*(ulong*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, ulong>(value));
                     break;
                 case TypeCode.Int64:
-                    writer.WriteNumberValue(*(long*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, long>(value));
                     break;
                 case TypeCode.Int16:
-                    writer.WriteNumberValue(*(short*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, short>(value));
                     break;
                 case TypeCode.UInt16:
-                    writer.WriteNumberValue(*(ushort*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, ushort>(value));
                     break;
                 case TypeCode.Byte:
-                    writer.WriteNumberValue(*(byte*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, byte>(value));
                     break;
                 case TypeCode.SByte:
-                    writer.WriteNumberValue(*(sbyte*)&value);
+                    writer.WriteNumberValue(Unsafe.BitCast<T, sbyte>(value));
                     break;
                 default:
                     ThrowHelper.ThrowJsonException();
@@ -324,28 +324,28 @@ internal override unsafe void WriteAsPropertyNameCore(Utf8JsonWriter writer, T v
             switch (s_enumTypeCode)
             {
                 case TypeCode.Int32:
-                    writer.WritePropertyName(*(int*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, int>(value));
                     break;
                 case TypeCode.UInt32:
-                    writer.WritePropertyName(*(uint*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, uint>(value));
                     break;
                 case TypeCode.UInt64:
-                    writer.WritePropertyName(*(ulong*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, ulong>(value));
                     break;
                 case TypeCode.Int64:
-                    writer.WritePropertyName(*(long*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, long>(value));
                     break;
                 case TypeCode.Int16:
-                    writer.WritePropertyName(*(short*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, short>(value));
                     break;
                 case TypeCode.UInt16:
-                    writer.WritePropertyName(*(ushort*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, ushort>(value));
                     break;
                 case TypeCode.Byte:
-                    writer.WritePropertyName(*(byte*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, byte>(value));
                     break;
                 case TypeCode.SByte:
-                    writer.WritePropertyName(*(sbyte*)&value);
+                    writer.WritePropertyName(Unsafe.BitCast<T, sbyte>(value));
                     break;
                 default:
                     ThrowHelper.ThrowJsonException();

From e7cd1470d56d642881acff866d8f97f70738aedf Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 14:07:20 -0800
Subject: [PATCH 08/13] Don't use BitCast in places the generic constraints
 disallows it

---
 .../System.Private.CoreLib/src/System/Enum.cs | 52 +++++++++----------
 .../System.Private.CoreLib/src/System/Span.cs |  2 +-
 .../src/System/SpanHelpers.Packed.cs          |  2 +-
 3 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs
index 2fc820c4ee6d16..b5cc1fadfb8d0d 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs
@@ -1812,38 +1812,38 @@ internal static unsafe bool TryFormatUnconstrained<TEnum>(TEnum value, Span<char
             // be necessary for semantics inside of TryFormatPrimitiveNonDefault, so we can just do it here instead.
             if (format.IsEmpty)
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, *(int*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, *(uint*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, *(long*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, *(ulong*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, *(byte*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, *(sbyte*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, *(short*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, *(ushort*)&value, destination, out charsWritten);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, *(nint*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, *(nuint*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, *(float*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, *(double*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, *(char*)&value, destination, out charsWritten);
 #endif
             }
             else
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, *(int*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, *(uint*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, *(long*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, *(ulong*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, *(byte*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, *(sbyte*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, *(short*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, *(ushort*)&value, destination, out charsWritten, format);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, *(nint*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, *(nuint*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, *(float*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, *(double*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, *(char*)&value, destination, out charsWritten, format);
 #endif
             }
 
diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs
index 74d2407ff3003e..26e32ffb4cfd08 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Span.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs
@@ -305,7 +305,7 @@ public unsafe void Fill(T value)
                 // The runtime eventually calls memset, which can efficiently support large buffers.
                 // We don't need to check IsReferenceOrContainsReferences because no references
                 // can ever be stored in types this small.
-                Unsafe.InitBlockUnaligned(ref Unsafe.As<T, byte>(ref _reference), Unsafe.BitCast<T, byte>(value), (uint)_length);
+                Unsafe.InitBlockUnaligned(ref Unsafe.As<T, byte>(ref _reference), *(byte*)&value, (uint)_length);
             }
             else
             {
diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs
index 44f9778a9a3ee8..9e8272671dd692 100644
--- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs
@@ -30,7 +30,7 @@ public static unsafe bool CanUsePackedIndexOf<T>(T value)
             Debug.Assert(RuntimeHelpers.IsBitwiseEquatable<T>());
             Debug.Assert(sizeof(T) == sizeof(ushort));
 
-            return Unsafe.BitCast<T, ushort>(value) - 1u < 254u;
+            return *(ushort*)&value - 1u < 254u;
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]

From e2875ddd3e1f1cf0f8131d626aaf8c5dcb8a1386 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Thu, 2 Mar 2023 14:13:44 -0800
Subject: [PATCH 09/13] Missing semicolon

---
 .../Text/Json/Serialization/Converters/Value/EnumConverter.cs   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
index a38c2dbee1e19c..46001c627826f6 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
@@ -148,7 +148,7 @@ public override unsafe T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso
                 case TypeCode.UInt64:
                     if (reader.TryGetUInt64(out ulong uint64))
                     {
-                        return Unsafe.BitCast<ulong, T>(uint64)
+                        return Unsafe.BitCast<ulong, T>(uint64);
                     }
                     break;
                 case TypeCode.Int64:

From b34275665cb052eb3d629ebc3c3ceb4442461a8c Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Fri, 3 Mar 2023 08:06:40 -0800
Subject: [PATCH 10/13] Don't use Unsafe.BitCast where it introduces additional
 generic instantiations

---
 .../System.Private.CoreLib/src/System/Enum.cs | 104 +++++++++---------
 .../IndexOfAnyValues/IndexOfAny4Values.cs     |  11 +-
 .../IndexOfAnyValues/IndexOfAny5Values.cs     |  13 ++-
 .../src/System/SpanHelpers.T.cs               |  18 +--
 .../Converters/Value/EnumConverter.cs         |  48 ++++----
 5 files changed, 98 insertions(+), 96 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs
index b5cc1fadfb8d0d..534823f28956f7 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs
@@ -46,20 +46,20 @@ public abstract partial class Enum : ValueType, IComparable, ISpanFormattable, I
             RuntimeType rt = (RuntimeType)typeof(TEnum);
             Type underlyingType = typeof(TEnum).GetEnumUnderlyingType();
 
-            if (underlyingType == typeof(sbyte)) return GetNameInlined(GetEnumInfo<sbyte>(rt), Unsafe.BitCast<TEnum, sbyte>(value));
-            if (underlyingType == typeof(byte)) return GetNameInlined(GetEnumInfo<byte>(rt), Unsafe.BitCast<TEnum, byte>(value));
-            if (underlyingType == typeof(short)) return GetNameInlined(GetEnumInfo<short>(rt), Unsafe.BitCast<TEnum, short>(value));
-            if (underlyingType == typeof(ushort)) return GetNameInlined(GetEnumInfo<ushort>(rt), Unsafe.BitCast<TEnum, ushort>(value));
-            if (underlyingType == typeof(int)) return GetNameInlined(GetEnumInfo<int>(rt), Unsafe.BitCast<TEnum, int>(value));
-            if (underlyingType == typeof(uint)) return GetNameInlined(GetEnumInfo<uint>(rt), Unsafe.BitCast<TEnum, uint>(value));
-            if (underlyingType == typeof(long)) return GetNameInlined(GetEnumInfo<long>(rt), Unsafe.BitCast<TEnum, long>(value));
-            if (underlyingType == typeof(ulong)) return GetNameInlined(GetEnumInfo<ulong>(rt), Unsafe.BitCast<TEnum, ulong>(value));
+            if (underlyingType == typeof(sbyte)) return GetNameInlined(GetEnumInfo<sbyte>(rt), *(sbyte*)&value);
+            if (underlyingType == typeof(byte)) return GetNameInlined(GetEnumInfo<byte>(rt), *(byte*)&value);
+            if (underlyingType == typeof(short)) return GetNameInlined(GetEnumInfo<short>(rt), *(short*)&value);
+            if (underlyingType == typeof(ushort)) return GetNameInlined(GetEnumInfo<ushort>(rt), *(ushort*)&value);
+            if (underlyingType == typeof(int)) return GetNameInlined(GetEnumInfo<int>(rt), *(int*)&value);
+            if (underlyingType == typeof(uint)) return GetNameInlined(GetEnumInfo<uint>(rt), *(uint*)&value);
+            if (underlyingType == typeof(long)) return GetNameInlined(GetEnumInfo<long>(rt), *(long*)&value);
+            if (underlyingType == typeof(ulong)) return GetNameInlined(GetEnumInfo<ulong>(rt), *(ulong*)&value);
 #if RARE_ENUMS
-            if (underlyingType == typeof(nint)) return GetNameInlined(GetEnumInfo<nint>(rt), Unsafe.BitCast<TEnum, nint>(value));
-            if (underlyingType == typeof(nuint)) return GetNameInlined(GetEnumInfo<nuint>(rt), Unsafe.BitCast<TEnum, nuint>(value));
-            if (underlyingType == typeof(float)) return GetNameInlined(GetEnumInfo<float>(rt), Unsafe.BitCast<TEnum, float>(value));
-            if (underlyingType == typeof(double)) return GetNameInlined(GetEnumInfo<double>(rt), Unsafe.BitCast<TEnum, double>(value));
-            if (underlyingType == typeof(char)) return GetNameInlined(GetEnumInfo<char>(rt), Unsafe.BitCast<TEnum, char>(value));
+            if (underlyingType == typeof(nint)) return GetNameInlined(GetEnumInfo<nint>(rt), *(nint*)&value);
+            if (underlyingType == typeof(nuint)) return GetNameInlined(GetEnumInfo<nuint>(rt), *(nuint*)&value);
+            if (underlyingType == typeof(float)) return GetNameInlined(GetEnumInfo<float>(rt), *(float*)&value);
+            if (underlyingType == typeof(double)) return GetNameInlined(GetEnumInfo<double>(rt), *(double*)&value);
+            if (underlyingType == typeof(char)) return GetNameInlined(GetEnumInfo<char>(rt), *(char*)&value);
 #endif
             throw CreateUnknownEnumTypeException();
         }
@@ -473,20 +473,20 @@ public static unsafe bool IsDefined<TEnum>(TEnum value) where TEnum : struct, En
             RuntimeType rt = (RuntimeType)typeof(TEnum);
             Type underlyingType = typeof(TEnum).GetEnumUnderlyingType();
 
-            if (underlyingType == typeof(sbyte)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, sbyte>(value));
-            if (underlyingType == typeof(byte)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, byte>(value));
-            if (underlyingType == typeof(short)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, short>(value));
-            if (underlyingType == typeof(ushort)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, ushort>(value));
-            if (underlyingType == typeof(int)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, int>(value));
-            if (underlyingType == typeof(uint)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, uint>(value));
-            if (underlyingType == typeof(long)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, long>(value));
-            if (underlyingType == typeof(ulong)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, ulong>(value));
+            if (underlyingType == typeof(sbyte)) return IsDefinedPrimitive(rt, *(sbyte*)&value);
+            if (underlyingType == typeof(byte)) return IsDefinedPrimitive(rt, *(byte*)&value);
+            if (underlyingType == typeof(short)) return IsDefinedPrimitive(rt, *(short*)&value);
+            if (underlyingType == typeof(ushort)) return IsDefinedPrimitive(rt, *(ushort*)&value);
+            if (underlyingType == typeof(int)) return IsDefinedPrimitive(rt, *(int*)&value);
+            if (underlyingType == typeof(uint)) return IsDefinedPrimitive(rt, *(uint*)&value);
+            if (underlyingType == typeof(long)) return IsDefinedPrimitive(rt, *(long*)&value);
+            if (underlyingType == typeof(ulong)) return IsDefinedPrimitive(rt, *(ulong*)&value);
 #if RARE_ENUMS
-            if (underlyingType == typeof(nint)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, nint>(value));
-            if (underlyingType == typeof(nuint)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, nuint>(value));
-            if (underlyingType == typeof(float)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, float>(value));
-            if (underlyingType == typeof(double)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, double>(value));
-            if (underlyingType == typeof(char)) return IsDefinedPrimitive(rt, Unsafe.BitCast<TEnum, char>(value));
+            if (underlyingType == typeof(nint)) return IsDefinedPrimitive(rt, *(nint*)&value);
+            if (underlyingType == typeof(nuint)) return IsDefinedPrimitive(rt, *(nuint*)&value);
+            if (underlyingType == typeof(float)) return IsDefinedPrimitive(rt, *(float*)&value);
+            if (underlyingType == typeof(double)) return IsDefinedPrimitive(rt, *(double*)&value);
+            if (underlyingType == typeof(char)) return IsDefinedPrimitive(rt, *(char*)&value);
 #endif
 
             throw CreateUnknownEnumTypeException();
@@ -1753,38 +1753,38 @@ public static unsafe bool TryFormat<TEnum>(TEnum value, Span<char> destination,
             // be necessary for semantics inside of TryFormatPrimitiveNonDefault, so we can just do it here instead.
             if (format.IsEmpty)
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, *(int*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, *(uint*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, *(long*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, *(ulong*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, *(byte*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, *(sbyte*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, *(short*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, *(ushort*)&value, destination, out charsWritten);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, *(nint*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, *(nuint*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, *(float*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, *(double*)&value, destination, out charsWritten);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, *(char*)&value, destination, out charsWritten);
 #endif
             }
             else
             {
-                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, int>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, uint>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, long>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ulong>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, byte>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, sbyte>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, short>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, ushort>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, *(int*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, *(uint*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, *(long*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, *(ulong*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, *(byte*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, *(sbyte*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, *(short*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, *(ushort*)&value, destination, out charsWritten, format);
 #if RARE_ENUMS
-                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nint>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, nuint>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, float>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, double>(value), destination, out charsWritten, format);
-                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, Unsafe.BitCast<TEnum, char>(value), destination, out charsWritten, format);
+                if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, *(nint*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, *(nuint*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, *(float*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, *(double*)&value, destination, out charsWritten, format);
+                if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, *(char*)&value, destination, out charsWritten, format);
 #endif
             }
 
diff --git a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs
index 0746c401ea3ebe..c23839310933cf 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny4Values.cs
@@ -25,15 +25,16 @@ public IndexOfAny4Values(ReadOnlySpan<TImpl> values)
 
         internal override unsafe T[] GetValues()
         {
-            return new[] { Unsafe.BitCast<TImpl, T>(_e0), Unsafe.BitCast<TImpl, T>(_e1), Unsafe.BitCast<TImpl, T>(_e2), Unsafe.BitCast<TImpl, T>(_e3) };
+            TImpl e0 = _e0, e1 = _e1, e2 = _e2, e3 = _e3;
+            return new[] { *(T*)&e0, *(T*)&e1, *(T*)&e2, *(T*)&e3 };
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override unsafe bool ContainsCore(T value) =>
-            Unsafe.BitCast<T, TImpl>(value) == _e0 ||
-            Unsafe.BitCast<T, TImpl>(value) == _e1 ||
-            Unsafe.BitCast<T, TImpl>(value) == _e2 ||
-            Unsafe.BitCast<T, TImpl>(value) == _e3;
+            *(TImpl*)&value == _e0 ||
+            *(TImpl*)&value == _e1 ||
+            *(TImpl*)&value == _e2 ||
+            *(TImpl*)&value == _e3;
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override int IndexOfAny(ReadOnlySpan<T> span) =>
diff --git a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs
index 75d182a6806c7a..55660a22b99f12 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IndexOfAnyValues/IndexOfAny5Values.cs
@@ -25,16 +25,17 @@ public IndexOfAny5Values(ReadOnlySpan<TImpl> values)
 
         internal override unsafe T[] GetValues()
         {
-            return new[] { Unsafe.BitCast<TImpl, T>(_e0), Unsafe.BitCast<TImpl, T>(_e1), Unsafe.BitCast<TImpl, T>(_e2), Unsafe.BitCast<TImpl, T>(_e3), Unsafe.BitCast<TImpl, T>(_e4) };
+            TImpl e0 = _e0, e1 = _e1, e2 = _e2, e3 = _e3, e4 = _e4;
+            return new[] { *(T*)&e0, *(T*)&e1, *(T*)&e2, *(T*)&e3, *(T*)&e4 };
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override unsafe bool ContainsCore(T value) =>
-            Unsafe.BitCast<T, TImpl>(value) == _e0 ||
-            Unsafe.BitCast<T, TImpl>(value) == _e1 ||
-            Unsafe.BitCast<T, TImpl>(value) == _e2 ||
-            Unsafe.BitCast<T, TImpl>(value) == _e3 ||
-            Unsafe.BitCast<T, TImpl>(value) == _e4;
+            *(TImpl*)&value == _e0 ||
+            *(TImpl*)&value == _e1 ||
+            *(TImpl*)&value == _e2 ||
+            *(TImpl*)&value == _e3 ||
+            *(TImpl*)&value == _e4;
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal override int IndexOfAny(ReadOnlySpan<T> span) =>
diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs
index 7b78bde92f3fb5..11c79ef0b76af6 100644
--- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs
@@ -1309,7 +1309,7 @@ internal static unsafe bool ContainsValueType<T>(ref T searchSpace, T value, int
         {
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(T) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value))
             {
-                return PackedSpanHelpers.Contains(ref Unsafe.As<T, short>(ref searchSpace), Unsafe.BitCast<T, short>(value), length);
+                return PackedSpanHelpers.Contains(ref Unsafe.As<T, short>(ref searchSpace), *(short*)&value, length);
             }
 
             return NonPackedContainsValueType(ref searchSpace, value, length);
@@ -1456,8 +1456,8 @@ private static unsafe int IndexOfValueType<TValue, TNegator>(ref TValue searchSp
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value))
             {
                 return typeof(TNegator) == typeof(DontNegate<short>)
-                    ? PackedSpanHelpers.IndexOf(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value), length)
-                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value), length);
+                    ? PackedSpanHelpers.IndexOf(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value, length)
+                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value, length);
             }
 
             return NonPackedIndexOfValueType<TValue, TNegator>(ref searchSpace, value, length);
@@ -1613,8 +1613,8 @@ private static unsafe int IndexOfAnyValueType<TValue, TNegator>(ref TValue searc
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1))
             {
                 return typeof(TNegator) == typeof(DontNegate<short>)
-                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), length)
-                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), length);
+                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, length)
+                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, length);
             }
 
             return NonPackedIndexOfAnyValueType<TValue, TNegator>(ref searchSpace, value0, value1, length);
@@ -1790,8 +1790,8 @@ private static unsafe int IndexOfAnyValueType<TValue, TNegator>(ref TValue searc
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1) && PackedSpanHelpers.CanUsePackedIndexOf(value2))
             {
                 return typeof(TNegator) == typeof(DontNegate<short>)
-                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), Unsafe.BitCast<TValue, char>(value2), length)
-                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), Unsafe.BitCast<TValue, char>(value0), Unsafe.BitCast<TValue, char>(value1), Unsafe.BitCast<TValue, char>(value2), length);
+                    ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, *(char*)&value2, length)
+                    : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As<TValue, char>(ref searchSpace), *(char*)&value0, *(char*)&value1, *(char*)&value2, length);
             }
 
             return NonPackedIndexOfAnyValueType<TValue, TNegator>(ref searchSpace, value0, value1, value2, length);
@@ -3093,8 +3093,8 @@ private static unsafe int IndexOfAnyInRangeUnsignedNumber<T, TNegator>(ref T sea
             if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(T) == typeof(ushort) && PackedSpanHelpers.CanUsePackedIndexOf(lowInclusive) && PackedSpanHelpers.CanUsePackedIndexOf(highInclusive) && highInclusive >= lowInclusive)
             {
                 ref char charSearchSpace = ref Unsafe.As<T, char>(ref searchSpace);
-                char charLowInclusive = Unsafe.BitCast<T, char>(lowInclusive);
-                char charRange = (char)(Unsafe.BitCast<T, char>(highInclusive) - charLowInclusive);
+                char charLowInclusive = *(char*)&lowInclusive;
+                char charRange = (char)(*(char*)&highInclusive - charLowInclusive);
 
                 return typeof(TNegator) == typeof(DontNegate<ushort>)
                     ? PackedSpanHelpers.IndexOfAnyInRange(ref charSearchSpace, charLowInclusive, charRange, length)
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
index 46001c627826f6..fe4779f87190f0 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs
@@ -136,49 +136,49 @@ public override unsafe T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso
                 case TypeCode.Int32:
                     if (reader.TryGetInt32(out int int32))
                     {
-                        return Unsafe.BitCast<int, T>(int32);
+                        return *(T*)&int32;
                     }
                     break;
                 case TypeCode.UInt32:
                     if (reader.TryGetUInt32(out uint uint32))
                     {
-                        return Unsafe.BitCast<uint, T>(uint32);
+                        return *(T*)&uint32;
                     }
                     break;
                 case TypeCode.UInt64:
                     if (reader.TryGetUInt64(out ulong uint64))
                     {
-                        return Unsafe.BitCast<ulong, T>(uint64);
+                        return *(T*)&uint64;
                     }
                     break;
                 case TypeCode.Int64:
                     if (reader.TryGetInt64(out long int64))
                     {
-                        return Unsafe.BitCast<long, T>(int64);
+                        return *(T*)&int64;
                     }
                     break;
                 case TypeCode.SByte:
                     if (reader.TryGetSByte(out sbyte byte8))
                     {
-                        return Unsafe.BitCast<sbyte, T>(byte8);
+                        return *(T*)&byte8;
                     }
                     break;
                 case TypeCode.Byte:
                     if (reader.TryGetByte(out byte ubyte8))
                     {
-                        return Unsafe.BitCast<byte, T>(ubyte8);
+                        return *(T*)&ubyte8;
                     }
                     break;
                 case TypeCode.Int16:
                     if (reader.TryGetInt16(out short int16))
                     {
-                        return Unsafe.BitCast<short, T>(int16);
+                        return *(T*)&int16;
                     }
                     break;
                 case TypeCode.UInt16:
                     if (reader.TryGetUInt16(out ushort uint16))
                     {
-                        return Unsafe.BitCast<ushort, T>(uint16);
+                        return *(T*)&uint16;
                     }
                     break;
             }
@@ -235,28 +235,28 @@ public override unsafe void Write(Utf8JsonWriter writer, T value, JsonSerializer
             switch (s_enumTypeCode)
             {
                 case TypeCode.Int32:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, int>(value));
+                    writer.WriteNumberValue(*(int*)&value);
                     break;
                 case TypeCode.UInt32:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, uint>(value));
+                    writer.WriteNumberValue(*(uint*)&value);
                     break;
                 case TypeCode.UInt64:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, ulong>(value));
+                    writer.WriteNumberValue(*(ulong*)&value);
                     break;
                 case TypeCode.Int64:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, long>(value));
+                    writer.WriteNumberValue(*(long*)&value);
                     break;
                 case TypeCode.Int16:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, short>(value));
+                    writer.WriteNumberValue(*(short*)&value);
                     break;
                 case TypeCode.UInt16:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, ushort>(value));
+                    writer.WriteNumberValue(*(ushort*)&value);
                     break;
                 case TypeCode.Byte:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, byte>(value));
+                    writer.WriteNumberValue(*(byte*)&value);
                     break;
                 case TypeCode.SByte:
-                    writer.WriteNumberValue(Unsafe.BitCast<T, sbyte>(value));
+                    writer.WriteNumberValue(*(sbyte*)&value);
                     break;
                 default:
                     ThrowHelper.ThrowJsonException();
@@ -324,28 +324,28 @@ internal override unsafe void WriteAsPropertyNameCore(Utf8JsonWriter writer, T v
             switch (s_enumTypeCode)
             {
                 case TypeCode.Int32:
-                    writer.WritePropertyName(Unsafe.BitCast<T, int>(value));
+                    writer.WritePropertyName(*(int*)&value);
                     break;
                 case TypeCode.UInt32:
-                    writer.WritePropertyName(Unsafe.BitCast<T, uint>(value));
+                    writer.WritePropertyName(*(uint*)&value);
                     break;
                 case TypeCode.UInt64:
-                    writer.WritePropertyName(Unsafe.BitCast<T, ulong>(value));
+                    writer.WritePropertyName(*(ulong*)&value);
                     break;
                 case TypeCode.Int64:
-                    writer.WritePropertyName(Unsafe.BitCast<T, long>(value));
+                    writer.WritePropertyName(*(long*)&value);
                     break;
                 case TypeCode.Int16:
-                    writer.WritePropertyName(Unsafe.BitCast<T, short>(value));
+                    writer.WritePropertyName(*(short*)&value);
                     break;
                 case TypeCode.UInt16:
-                    writer.WritePropertyName(Unsafe.BitCast<T, ushort>(value));
+                    writer.WritePropertyName(*(ushort*)&value);
                     break;
                 case TypeCode.Byte:
-                    writer.WritePropertyName(Unsafe.BitCast<T, byte>(value));
+                    writer.WritePropertyName(*(byte*)&value);
                     break;
                 case TypeCode.SByte:
-                    writer.WritePropertyName(Unsafe.BitCast<T, sbyte>(value));
+                    writer.WritePropertyName(*(sbyte*)&value);
                     break;
                 default:
                     ThrowHelper.ThrowJsonException();

From bc80205e5f9dd23f93329e25524a210dc1d40446 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Fri, 3 Mar 2023 09:46:50 -0800
Subject: [PATCH 11/13] Don't regress the files that are used for both
 netstandard and netcoreapp

---
 .../System/Reflection/Internal/Utilities/BlobUtilities.cs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
index b29f5819cdcc49..843e95e616d34b 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
@@ -20,12 +20,20 @@ public static void WriteBytes(this byte[] buffer, int start, byte value, int byt
 
         public static void WriteDouble(this byte[] buffer, int start, double value)
         {
+#if NETCOREAPP
             WriteUInt64(buffer, start, BitConverter.DoubleToUInt64Bits(value));
+#else
+            WriteUInt64(buffer, start, *(ulong*)&value);
+#endif
         }
 
         public static void WriteSingle(this byte[] buffer, int start, float value)
         {
+#if NETCOREAPP
             WriteUInt32(buffer, start, BitConverter.SingleToUInt32Bits(value));
+#else
+            WriteUInt32(buffer, start, *(uint*)&value);
+#endif
         }
 
         public static void WriteByte(this byte[] buffer, int start, byte value)

From 29afa956672fc640fc60c9554ee0e5377e4cfa49 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Wed, 8 Mar 2023 06:03:56 -0800
Subject: [PATCH 12/13] Responding to PR feedback

---
 src/coreclr/jit/importercalls.cpp             |  4 ++-
 .../System/Runtime/CompilerServices/Unsafe.cs |  2 +-
 .../tests/UnsafeTests.cs                      | 33 +++++++++++++++++++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp
index 3a2273232afbcc..7b437bbc52af40 100644
--- a/src/coreclr/jit/importercalls.cpp
+++ b/src/coreclr/jit/importercalls.cpp
@@ -4018,6 +4018,9 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic        intrinsic,
             unsigned fromSize = info.compCompHnd->getClassSize(fromTypeHnd);
             unsigned toSize   = info.compCompHnd->getClassSize(toTypeHnd);
 
+            // Runtime requires all types to be at least 1-byte
+            assert((fromSize != 0) && (toSize != 0));
+
             if (fromSize != toSize)
             {
                 // Fallback to the software implementation to throw when sizes don't match
@@ -4132,7 +4135,6 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic        intrinsic,
                 {
                     return gtNewBitCastNode(toType, op1);
                 }
-                break;
             }
 
             // Handle bitcasting for same sized integrals, such as `int` to `uint`
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
index a82d974884aaf8..ef7a6fc4e84fd3 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
@@ -239,7 +239,7 @@ public static bool AreSame<T>([AllowNull] ref T left, [AllowNull] ref T right)
         }
 
         /// <summary>
-        /// Reinterprets the given reference as a reference to a value of type <typeparamref name="TTo"/>.
+        /// Reinterprets the given value of type <typeparamref name="TFrom" /> as a value of type <typeparamref name="TTo" />.
         /// </summary>
         /// <exception cref="NotSupportedException">The size of <typeparamref name="TFrom" /> and <typeparamref name="TTo" /> are not the same.</exception>
         [Intrinsic]
diff --git a/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs b/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
index c0171353f30963..ebc87cb26cc4c1 100644
--- a/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
+++ b/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
@@ -1084,15 +1084,23 @@ public static unsafe void NullRef()
         [Fact]
         public static unsafe void BitCast()
         {
+            // Conversion between differently sized types should fail
+
             Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<int, long>(5));
             Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<long, int>(5));
 
+            // Conversion between floating-point and same sized integral should succeed
+
             Assert.Equal(0x8000_0000u, Unsafe.BitCast<float, uint>(-0.0f));
             Assert.Equal(float.PositiveInfinity, Unsafe.BitCast<uint, float>(0x7F80_0000u));
 
+            // Conversion between same sized integers should succeed
+
             Assert.Equal(int.MinValue, Unsafe.BitCast<uint, int>(0x8000_0000u));
             Assert.Equal(0x8000_0000u, Unsafe.BitCast<int, uint>(int.MinValue));
 
+            // Conversion from runtime SIMD type to a custom struct should succeed
+
             Vector4 vector4a = new Vector4(1.0f, 2.0f, 3.0f, 4.0f);
             Single4 single4a = Unsafe.BitCast<Vector4, Single4>(vector4a);
 
@@ -1101,6 +1109,8 @@ public static unsafe void BitCast()
             Assert.Equal(3.0f, single4a.Z);
             Assert.Equal(4.0f, single4a.W);
 
+            // Conversion from custom struct to a runtime SIMD type should succeed
+
             Single4 single4b = new Single4 { X = -1.0f, Y = -2.0f, Z = -3.0f, W = -4.0f };
             Vector4 vector4b = Unsafe.BitCast<Single4, Vector4>(single4b);
 
@@ -1108,6 +1118,21 @@ public static unsafe void BitCast()
             Assert.Equal(-2.0f, vector4b.Y);
             Assert.Equal(-3.0f, vector4b.Z);
             Assert.Equal(-4.0f, vector4b.W);
+
+            // Runtime requires that all types be at least 1-byte, so empty to empty should succeed
+
+            EmptyA empty1 = new EmptyA();
+            EmptyB empty2 = Unsafe.BitCast<EmptyA, EmptyB>(empty1);
+
+            // ..., likewise, empty to/from byte should succeed
+
+            byte empty3 = Unsafe.BitCast<EmptyA, byte>(empty1);
+            EmptyA empty4 = Unsafe.BitCast<byte, EmptyA>(1);
+
+            // ..., however, empty to/from a larger type should fail
+
+            Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<int, EmptyA>(5));
+            Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<EmptyA, int>(emptyA));
         }
     }
 
@@ -1193,4 +1218,12 @@ public struct Single4
         public float Z;
         public float W;
     }
+
+    public struct EmptyA
+    {
+    }
+
+    public struct EmptyB
+    {
+    }
 }

From 22012d8ef04c6f93176747d7a503008ce302a8a7 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Wed, 8 Mar 2023 06:27:26 -0800
Subject: [PATCH 13/13] Fix a typo in the bitcast tests

---
 .../System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs b/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
index ebc87cb26cc4c1..8d596482766a40 100644
--- a/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
+++ b/src/libraries/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
@@ -1132,7 +1132,7 @@ public static unsafe void BitCast()
             // ..., however, empty to/from a larger type should fail
 
             Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<int, EmptyA>(5));
-            Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<EmptyA, int>(emptyA));
+            Assert.Throws<NotSupportedException>(() => Unsafe.BitCast<EmptyA, int>(empty1));
         }
     }