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 a4ab35444ae703..2e683dcf73c8ac 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
@@ -81,6 +81,7 @@ public static long Decrement(ref long location) =>
/// The value to which the parameter is set.
/// The original value of .
/// The address of location1 is a null pointer.
+ [Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: NotNullIfNotNull(nameof(location1))]
public static extern object? Exchange([NotNullIfNotNull(nameof(value))] ref object? location1, object? value);
@@ -145,6 +146,7 @@ public static T Exchange([NotNullIfNotNull(nameof(value))] ref T location1, T
/// The object that is compared by reference to the object at .
/// The original value in .
/// The address of is a null pointer.
+ [Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: NotNullIfNotNull(nameof(location1))]
public static extern object? CompareExchange(ref object? location1, object? value, object? comparand);
diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp
index 3adde7d491ac42..ec92685974929c 100644
--- a/src/coreclr/jit/codegenxarch.cpp
+++ b/src/coreclr/jit/codegenxarch.cpp
@@ -4064,7 +4064,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* node)
assert(addr->isUsedFromReg());
assert(data->isUsedFromReg());
- assert((size == EA_4BYTE) || (size == EA_PTRSIZE));
+ assert((size == EA_4BYTE) || (size == EA_PTRSIZE) || (size == EA_GCREF));
genConsumeOperands(node);
diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp
index a0008218ecf6b7..1c3c3bffd90af4 100644
--- a/src/coreclr/jit/emitxarch.cpp
+++ b/src/coreclr/jit/emitxarch.cpp
@@ -12193,7 +12193,14 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)
case IF_ARW_RRD:
case IF_ARW_CNS:
- assert(id->idGCref() == GCT_BYREF && (ins == INS_add || ins == INS_sub || ins == INS_sub_hide));
+ if (id->idGCref() == GCT_BYREF)
+ {
+ assert(ins == INS_add || ins == INS_sub || ins == INS_sub_hide);
+ }
+ else
+ {
+ assert((id->idGCref() == GCT_GCREF) && (ins == INS_cmpxchg || ins == INS_xchg));
+ }
break;
default:
diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp
index 90163e6f842f07..3504e04d5025a5 100644
--- a/src/coreclr/jit/importercalls.cpp
+++ b/src/coreclr/jit/importercalls.cpp
@@ -2967,7 +2967,12 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
{
break;
}
- if ((retType != TYP_INT) && (retType != TYP_LONG))
+ if ((retType == TYP_REF) && impStackTop(1).val->IsIntegralConst(0))
+ {
+ // Intrinsify "object" overload in case of null assignment
+ // since we don't need the write barrier.
+ }
+ else if ((retType != TYP_INT) && (retType != TYP_LONG))
{
break;
}
@@ -2997,7 +3002,13 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
{
break;
}
- if ((retType != TYP_INT) && (retType != TYP_LONG))
+ if ((retType == TYP_REF) && impStackTop().val->IsIntegralConst(0))
+ {
+ // 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))
{
break;
}