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)