From a0d1e1c8ce52587fbbd7ba80cd3dded05926b251 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 3 Dec 2022 02:48:07 +0100 Subject: [PATCH 1/2] Intrinsify Interlocked.CompareExchange and Interlocked.Exchange for null --- .../src/System/Threading/Interlocked.CoreCLR.cs | 2 ++ src/coreclr/jit/codegenxarch.cpp | 2 +- src/coreclr/jit/emitxarch.cpp | 9 ++++++++- src/coreclr/jit/importercalls.cpp | 14 ++++++++++++-- 4 files changed, 23 insertions(+), 4 deletions(-) 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 6d654f115ff480..56d16fb28cc967 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..a226e9a8ae2023 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().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,12 @@ 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. + } + else if ((retType != TYP_INT) && (retType != TYP_LONG)) { break; } From 401177a69db0bbe5918eccb83b301c93c4ca8ea8 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 3 Dec 2022 10:32:04 +0100 Subject: [PATCH 2/2] Address feedback --- src/coreclr/jit/importercalls.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index a226e9a8ae2023..3504e04d5025a5 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -2967,7 +2967,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, { break; } - if ((retType == TYP_REF) && impStackTop().val->IsIntegralConst(0)) + 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. @@ -3006,6 +3006,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, { // 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)) {