Skip to content

Commit b4c165d

Browse files
MichalPetrykaliveans
authored andcommitted
Interlocked intrinsic improvements (dotnet#93821)
* Interlocked intrinsic improvements * Format
1 parent de69e83 commit b4c165d

File tree

4 files changed

+26
-12
lines changed

4 files changed

+26
-12
lines changed

src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ public static long Decrement(ref long location) =>
7979
/// <returns>The original value of <paramref name="location1"/>.</returns>
8080
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
8181
/// <typeparam name="T">The type to be used for <paramref name="location1"/> and <paramref name="value"/>. This type must be a reference type.</typeparam>
82-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
82+
[Intrinsic]
8383
[return: NotNullIfNotNull(nameof(location1))]
84+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8485
public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T value) where T : class? =>
8586
Unsafe.As<T>(Exchange(ref Unsafe.As<T, object?>(ref location1), value));
8687
#endregion
@@ -134,8 +135,9 @@ public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T
134135
/// <returns>The original value in <paramref name="location1"/>.</returns>
135136
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
136137
/// <typeparam name="T">The type to be used for <paramref name="location1"/>, <paramref name="value"/>, and <paramref name="comparand"/>. This type must be a reference type.</typeparam>
137-
[return: NotNullIfNotNull(nameof(location1))]
138138
[Intrinsic]
139+
[return: NotNullIfNotNull(nameof(location1))]
140+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
139141
public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class? =>
140142
Unsafe.As<T>(CompareExchange(ref Unsafe.As<T, object?>(ref location1), value, comparand));
141143
#endregion

src/coreclr/jit/importercalls.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3245,16 +3245,18 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
32453245
case NI_System_Threading_Interlocked_CompareExchange:
32463246
{
32473247
var_types retType = JITtype2varType(sig->retType);
3248-
if ((retType == TYP_LONG) && (TARGET_POINTER_SIZE == 4))
3248+
if (genTypeSize(retType) > TARGET_POINTER_SIZE)
32493249
{
32503250
break;
32513251
}
3252-
if ((retType == TYP_REF) && impStackTop(1).val->IsIntegralConst(0))
3252+
3253+
if ((retType == TYP_REF) &&
3254+
(impStackTop(1).val->IsIntegralConst(0) || impStackTop(1).val->IsIconHandle(GTF_ICON_OBJ_HDL)))
32533255
{
32543256
// Intrinsify "object" overload in case of null assignment
32553257
// since we don't need the write barrier.
32563258
}
3257-
else if ((retType != TYP_INT) && (retType != TYP_LONG))
3259+
else if (!varTypeIsIntegral(retType))
32583260
{
32593261
break;
32603262
}
@@ -3265,7 +3267,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
32653267
GenTree* op3 = impPopStack().val; // comparand
32663268
GenTree* op2 = impPopStack().val; // value
32673269
GenTree* op1 = impPopStack().val; // location
3268-
retNode = gtNewAtomicNode(GT_CMPXCHG, genActualType(callType), op1, op2, op3);
3270+
retNode = gtNewAtomicNode(GT_CMPXCHG, callType, op1, op2, op3);
32693271
break;
32703272
}
32713273

@@ -3276,17 +3278,19 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
32763278
assert(sig->numArgs == 2);
32773279

32783280
var_types retType = JITtype2varType(sig->retType);
3279-
if ((retType == TYP_LONG) && (TARGET_POINTER_SIZE == 4))
3281+
if (genTypeSize(retType) > TARGET_POINTER_SIZE)
32803282
{
32813283
break;
32823284
}
3283-
if ((retType == TYP_REF) && impStackTop().val->IsIntegralConst(0))
3285+
3286+
if ((retType == TYP_REF) &&
3287+
(impStackTop().val->IsIntegralConst(0) || impStackTop().val->IsIconHandle(GTF_ICON_OBJ_HDL)))
32843288
{
32853289
// Intrinsify "object" overload in case of null assignment
32863290
// since we don't need the write barrier.
32873291
assert(ni == NI_System_Threading_Interlocked_Exchange);
32883292
}
3289-
else if ((retType != TYP_INT) && (retType != TYP_LONG))
3293+
else if (!varTypeIsIntegral(retType))
32903294
{
32913295
break;
32923296
}
@@ -3300,7 +3304,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
33003304
// field_addr (for example)
33013305
//
33023306
retNode = gtNewAtomicNode(ni == NI_System_Threading_Interlocked_ExchangeAdd ? GT_XADD : GT_XCHG,
3303-
genActualType(callType), op1, op2);
3307+
callType, op1, op2);
33043308
break;
33053309
}
33063310
#endif // defined(TARGET_XARCH) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ public static long CompareExchange(ref long location1, long value, long comparan
2424
}
2525

2626
[Intrinsic]
27-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2827
[return: NotNullIfNotNull(nameof(location1))]
28+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2929
public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class?
3030
{
3131
return Unsafe.As<T>(RuntimeImports.InterlockedCompareExchange(ref Unsafe.As<T, object?>(ref location1), value, comparand));
@@ -69,8 +69,8 @@ public static long Exchange(ref long location1, long value)
6969
}
7070

7171
[Intrinsic]
72-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7372
[return: NotNullIfNotNull(nameof(location1))]
73+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7474
public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T value) where T : class?
7575
{
7676
return Unsafe.As<T>(RuntimeImports.InterlockedExchange(ref Unsafe.As<T, object?>(ref location1), value));

src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public static ulong Decrement(ref ulong location) =>
5454
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
5555
/// <returns>The original value of <paramref name="location1"/>.</returns>
5656
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
57+
[Intrinsic]
5758
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5859
[CLSCompliant(false)]
5960
public static uint Exchange(ref uint location1, uint value) =>
@@ -64,6 +65,7 @@ public static uint Exchange(ref uint location1, uint value) =>
6465
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
6566
/// <returns>The original value of <paramref name="location1"/>.</returns>
6667
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
68+
[Intrinsic]
6769
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6870
[CLSCompliant(false)]
6971
public static ulong Exchange(ref ulong location1, ulong value) =>
@@ -92,6 +94,7 @@ public static double Exchange(ref double location1, double value)
9294
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
9395
/// <returns>The original value of <paramref name="location1"/>.</returns>
9496
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
97+
[Intrinsic]
9598
[MethodImpl(MethodImplOptions.AggressiveInlining)]
9699
public static IntPtr Exchange(ref IntPtr location1, IntPtr value)
97100
{
@@ -109,6 +112,7 @@ public static IntPtr Exchange(ref IntPtr location1, IntPtr value)
109112
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
110113
/// <returns>The original value of <paramref name="location1"/>.</returns>
111114
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
115+
[Intrinsic]
112116
[CLSCompliant(false)]
113117
[MethodImpl(MethodImplOptions.AggressiveInlining)]
114118
public static UIntPtr Exchange(ref UIntPtr location1, UIntPtr value)
@@ -128,6 +132,7 @@ public static UIntPtr Exchange(ref UIntPtr location1, UIntPtr value)
128132
/// <param name="comparand">The value that is compared to the value at <paramref name="location1"/>.</param>
129133
/// <returns>The original value in <paramref name="location1"/>.</returns>
130134
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
135+
[Intrinsic]
131136
[MethodImpl(MethodImplOptions.AggressiveInlining)]
132137
[CLSCompliant(false)]
133138
public static uint CompareExchange(ref uint location1, uint value, uint comparand) =>
@@ -139,6 +144,7 @@ public static uint CompareExchange(ref uint location1, uint value, uint comparan
139144
/// <param name="comparand">The value that is compared to the value at <paramref name="location1"/>.</param>
140145
/// <returns>The original value in <paramref name="location1"/>.</returns>
141146
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
147+
[Intrinsic]
142148
[MethodImpl(MethodImplOptions.AggressiveInlining)]
143149
[CLSCompliant(false)]
144150
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
170176
/// <param name="comparand">The <see cref="IntPtr"/> that is compared to the value at <paramref name="location1"/>.</param>
171177
/// <returns>The original value in <paramref name="location1"/>.</returns>
172178
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
179+
[Intrinsic]
173180
[MethodImpl(MethodImplOptions.AggressiveInlining)]
174181
public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand)
175182
{
@@ -188,6 +195,7 @@ public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr
188195
/// <param name="comparand">The <see cref="UIntPtr"/> that is compared to the value at <paramref name="location1"/>.</param>
189196
/// <returns>The original value in <paramref name="location1"/>.</returns>
190197
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
198+
[Intrinsic]
191199
[CLSCompliant(false)]
192200
[MethodImpl(MethodImplOptions.AggressiveInlining)]
193201
public static UIntPtr CompareExchange(ref UIntPtr location1, UIntPtr value, UIntPtr comparand)

0 commit comments

Comments
 (0)