diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs index f4551e01beada..1bce1b45748c9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs @@ -79,8 +79,9 @@ public static partial class Interlocked /// The original value of . /// The address of location1 is a null pointer. /// The type to be used for and . This type must be a reference type. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [return: NotNullIfNotNull(nameof(location1))] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Exchange([NotNullIfNotNull(nameof(value))] ref T location1, T value) where T : class? => Unsafe.As(Exchange(ref Unsafe.As(ref location1), value)); #endregion @@ -134,8 +135,9 @@ public static partial class Interlocked /// The original value in . /// The address of is a null pointer. /// The type to be used for , , and . This type must be a reference type. - [return: NotNullIfNotNull(nameof(location1))] [Intrinsic] + [return: NotNullIfNotNull(nameof(location1))] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T CompareExchange(ref T location1, T value, T comparand) where T : class? => Unsafe.As(CompareExchange(ref Unsafe.As(ref location1), value, comparand)); #endregion diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 6006a48a86f2a..2107c7fe69bef 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3253,16 +3253,18 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, case NI_System_Threading_Interlocked_CompareExchange: { var_types retType = JITtype2varType(sig->retType); - if ((retType == TYP_LONG) && (TARGET_POINTER_SIZE == 4)) + if (genTypeSize(retType) > TARGET_POINTER_SIZE) { break; } - if ((retType == TYP_REF) && impStackTop(1).val->IsIntegralConst(0)) + + if ((retType == TYP_REF) && + (impStackTop(1).val->IsIntegralConst(0) || impStackTop(1).val->IsIconHandle(GTF_ICON_OBJ_HDL))) { // Intrinsify "object" overload in case of null assignment // since we don't need the write barrier. } - else if ((retType != TYP_INT) && (retType != TYP_LONG)) + else if (!varTypeIsIntegral(retType)) { break; } @@ -3273,7 +3275,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, GenTree* op3 = impPopStack().val; // comparand GenTree* op2 = impPopStack().val; // value GenTree* op1 = impPopStack().val; // location - retNode = gtNewAtomicNode(GT_CMPXCHG, genActualType(callType), op1, op2, op3); + retNode = gtNewAtomicNode(GT_CMPXCHG, callType, op1, op2, op3); break; } @@ -3284,17 +3286,19 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, assert(sig->numArgs == 2); var_types retType = JITtype2varType(sig->retType); - if ((retType == TYP_LONG) && (TARGET_POINTER_SIZE == 4)) + if (genTypeSize(retType) > TARGET_POINTER_SIZE) { break; } - if ((retType == TYP_REF) && impStackTop().val->IsIntegralConst(0)) + + if ((retType == TYP_REF) && + (impStackTop().val->IsIntegralConst(0) || impStackTop().val->IsIconHandle(GTF_ICON_OBJ_HDL))) { // Intrinsify "object" overload in case of null assignment // since we don't need the write barrier. assert(ni == NI_System_Threading_Interlocked_Exchange); } - else if ((retType != TYP_INT) && (retType != TYP_LONG)) + else if (!varTypeIsIntegral(retType)) { break; } @@ -3308,7 +3312,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, // field_addr (for example) // retNode = gtNewAtomicNode(ni == NI_System_Threading_Interlocked_ExchangeAdd ? GT_XADD : GT_XCHG, - genActualType(callType), op1, op2); + callType, op1, op2); break; } #endif // defined(TARGET_XARCH) || defined(TARGET_ARM64) || defined(TARGET_RISCV64) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs index f8a5e61ecbb65..a81051a58ba17 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -24,8 +24,8 @@ public static long CompareExchange(ref long location1, long value, long comparan } [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NotNullIfNotNull(nameof(location1))] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T CompareExchange(ref T location1, T value, T comparand) where T : class? { return Unsafe.As(RuntimeImports.InterlockedCompareExchange(ref Unsafe.As(ref location1), value, comparand)); @@ -69,8 +69,8 @@ public static long Exchange(ref long location1, long value) } [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NotNullIfNotNull(nameof(location1))] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Exchange([NotNullIfNotNull(nameof(value))] ref T location1, T value) where T : class? { return Unsafe.As(RuntimeImports.InterlockedExchange(ref Unsafe.As(ref location1), value)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs index 465d7d70a35d1..c125443f2a97e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -54,6 +54,7 @@ public static partial class Interlocked /// The value to which the parameter is set. /// The original value of . /// The address of location1 is a null pointer. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static uint Exchange(ref uint location1, uint value) => @@ -64,6 +65,7 @@ public static partial class Interlocked /// The value to which the parameter is set. /// The original value of . /// The address of location1 is a null pointer. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static ulong Exchange(ref ulong location1, ulong value) => @@ -92,6 +94,7 @@ public static double Exchange(ref double location1, double value) /// The value to which the parameter is set. /// The original value of . /// The address of location1 is a null pointer. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr Exchange(ref IntPtr location1, IntPtr value) { @@ -109,6 +112,7 @@ public static IntPtr Exchange(ref IntPtr location1, IntPtr value) /// The value to which the parameter is set. /// The original value of . /// The address of location1 is a null pointer. + [Intrinsic] [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static UIntPtr Exchange(ref UIntPtr location1, UIntPtr value) @@ -128,6 +132,7 @@ public static UIntPtr Exchange(ref UIntPtr location1, UIntPtr value) /// The value that is compared to the value at . /// The original value in . /// The address of is a null pointer. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static uint CompareExchange(ref uint location1, uint value, uint comparand) => @@ -139,6 +144,7 @@ public static UIntPtr Exchange(ref UIntPtr location1, UIntPtr value) /// The value that is compared to the value at . /// The original value in . /// The address of is a null pointer. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static ulong CompareExchange(ref ulong location1, ulong value, ulong comparand) => @@ -170,6 +176,7 @@ public static double CompareExchange(ref double location1, double value, double /// The that is compared to the value at . /// The original value in . /// The address of is a null pointer. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand) { @@ -188,6 +195,7 @@ public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr /// The that is compared to the value at . /// The original value in . /// The address of is a null pointer. + [Intrinsic] [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static UIntPtr CompareExchange(ref UIntPtr location1, UIntPtr value, UIntPtr comparand)