Skip to content

Commit 6c6d71e

Browse files
committed
Continue tracking the System.Numerics and System.Runtime.Intrinsics APIs as intrinsic for the profitability boost
1 parent 3eae1a6 commit 6c6d71e

19 files changed

+514
-18
lines changed

src/coreclr/jit/importercalls.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,6 +3089,13 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
30893089
}
30903090
#endif // FEATURE_HW_INTRINSICS
30913091

3092+
if ((ni == NI_System_Numerics_Intrinsic) || (ni == NI_System_Runtime_Intrinsics_Intrinsic))
3093+
{
3094+
// These are special markers used just to ensure we still get the inlining profitability
3095+
// boost. We actually have the implementation in managed, however, to keep the JIT simpler.
3096+
return nullptr;
3097+
}
3098+
30923099
if (!isIntrinsic)
30933100
{
30943101
// Outside the cases above, there are many intrinsics which apply to only a
@@ -10080,6 +10087,12 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
1008010087

1008110088
result = NI_Throw_PlatformNotSupportedException;
1008210089
}
10090+
else
10091+
{
10092+
// Otherwise mark this as a general intrinsic in the namespace
10093+
// so we can still get the inlining profitability boost.
10094+
result = NI_System_Runtime_Intrinsics_Intrinsic;
10095+
}
1008310096
}
1008410097
}
1008510098
}
@@ -10304,6 +10317,12 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
1030410317

1030510318
result = NI_Throw_PlatformNotSupportedException;
1030610319
}
10320+
else
10321+
{
10322+
// Otherwise mark this as a general intrinsic in the namespace
10323+
// so we can still get the inlining profitability boost.
10324+
result = NI_System_Numerics_Intrinsic;
10325+
}
1030710326
}
1030810327
}
1030910328
}

src/coreclr/jit/namedintrinsiclist.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ enum NamedIntrinsic : unsigned short
140140
NI_System_Threading_Interlocked_MemoryBarrier,
141141
NI_System_Threading_Interlocked_ReadMemoryBarrier,
142142

143+
// These two are special marker IDs so that we still get the inlining profitability boost
144+
NI_System_Numerics_Intrinsic,
145+
NI_System_Runtime_Intrinsics_Intrinsic,
146+
143147
#ifdef FEATURE_HW_INTRINSICS
144148
NI_HW_INTRINSIC_START,
145149
#if defined(TARGET_XARCH)

src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public struct Plane : IEquatable<Plane>
2727
/// <param name="y">The Y component of the normal.</param>
2828
/// <param name="z">The Z component of the normal.</param>
2929
/// <param name="d">The distance of the plane along its normal from the origin.</param>
30+
[Intrinsic]
3031
public Plane(float x, float y, float z, float d)
3132
{
3233
this = Vector128.Create(x, y, z, d).AsPlane();
@@ -35,13 +36,15 @@ public Plane(float x, float y, float z, float d)
3536
/// <summary>Creates a <see cref="Plane" /> object from a specified normal and the distance along the normal from the origin.</summary>
3637
/// <param name="normal">The plane's normal vector.</param>
3738
/// <param name="d">The plane's distance from the origin along its normal vector.</param>
39+
[Intrinsic]
3840
public Plane(Vector3 normal, float d)
3941
{
4042
this = new Vector4(normal, d).AsPlane();
4143
}
4244

4345
/// <summary>Creates a <see cref="Plane" /> object from a specified four-dimensional vector.</summary>
4446
/// <param name="value">A vector whose first three elements describe the normal vector, and whose <see cref="Vector4.W" /> defines the distance along that normal from the origin.</param>
47+
[Intrinsic]
4548
public Plane(Vector4 value)
4649
{
4750
this = value.AsPlane();
@@ -103,6 +106,7 @@ public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 p
103106
/// <param name="plane">The plane.</param>
104107
/// <param name="value">The four-dimensional vector.</param>
105108
/// <returns>The dot product.</returns>
109+
[Intrinsic]
106110
[MethodImpl(MethodImplOptions.AggressiveInlining)]
107111
public static float Dot(Plane plane, Vector4 value) => Vector128.Dot(plane.AsVector128(), value.AsVector128());
108112

@@ -204,6 +208,7 @@ public static Plane Transform(Plane plane, Quaternion rotation)
204208
/// <returns><see langword="true" /> if <paramref name="value1" /> and <paramref name="value2" /> are equal; otherwise, <see langword="false" />.</returns>
205209
/// <remarks>Two <see cref="Plane" /> objects are equal if their <see cref="Normal" /> and <see cref="D" /> fields are equal.
206210
/// The <see cref="op_Equality" /> method defines the operation of the equality operator for <see cref="Plane" /> objects.</remarks>
211+
[Intrinsic]
207212
[MethodImpl(MethodImplOptions.AggressiveInlining)]
208213
public static bool operator ==(Plane value1, Plane value2) => value1.AsVector128() == value2.AsVector128();
209214

@@ -212,6 +217,7 @@ public static Plane Transform(Plane plane, Quaternion rotation)
212217
/// <param name="value2">The second plane to compare.</param>
213218
/// <returns><see langword="true" /> if <paramref name="value1" /> and <paramref name="value2" /> are not equal; otherwise, <see langword="false" />.</returns>
214219
/// <remarks>The <see cref="op_Inequality" /> method defines the operation of the inequality operator for <see cref="Plane" /> objects.</remarks>
220+
[Intrinsic]
215221
public static bool operator !=(Plane value1, Plane value2) => !(value1 == value2);
216222

217223
/// <summary>Returns a value that indicates whether this instance and a specified object are equal.</summary>

src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public static unsafe partial class Vector
1414
/// <param name="index">The index of the element to get.</param>
1515
/// <returns>The value of the element at <paramref name="index" />.</returns>
1616
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
17+
[Intrinsic]
1718
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1819
internal static float GetElement(this Quaternion quaternion, int index)
1920
{
@@ -26,6 +27,7 @@ internal static float GetElement(this Quaternion quaternion, int index)
2627
/// <param name="value">The value to set the element to.</param>
2728
/// <returns>A <see cref="Quaternion" /> with the value of the element at <paramref name="index" /> set to <paramref name="value" /> and the remaining elements set to the same value as that in <paramref name="quaternion" />.</returns>
2829
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
30+
[Intrinsic]
2931
internal static Quaternion WithElement(this Quaternion quaternion, int index, float value)
3032
{
3133
return quaternion.AsVector128().WithElement(index, value).AsQuaternion();

src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public struct Quaternion : IEquatable<Quaternion>
3535
/// <param name="y">The value to assign to the Y component of the quaternion.</param>
3636
/// <param name="z">The value to assign to the Z component of the quaternion.</param>
3737
/// <param name="w">The value to assign to the W component of the quaternion.</param>
38+
[Intrinsic]
3839
public Quaternion(float x, float y, float z, float w)
3940
{
4041
this = Vector128.Create(x, y, z, w).AsQuaternion();
@@ -43,25 +44,35 @@ public Quaternion(float x, float y, float z, float w)
4344
/// <summary>Creates a quaternion from the specified vector and rotation parts.</summary>
4445
/// <param name="vectorPart">The vector part of the quaternion.</param>
4546
/// <param name="scalarPart">The rotation part of the quaternion.</param>
47+
[Intrinsic]
4648
public Quaternion(Vector3 vectorPart, float scalarPart)
4749
{
4850
this = new Vector4(vectorPart, scalarPart).AsQuaternion();
4951
}
5052

5153
/// <summary>Gets a quaternion that represents a zero.</summary>
5254
/// <value>A quaternion whose values are <c>(0, 0, 0, 0)</c>.</value>
53-
public static Quaternion Zero => default;
55+
public static Quaternion Zero
56+
{
57+
[Intrinsic]
58+
get => default;
59+
}
5460

5561
/// <summary>Gets a quaternion that represents no rotation.</summary>
5662
/// <value>A quaternion whose values are <c>(0, 0, 0, 1)</c>.</value>
57-
public static Quaternion Identity => new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
63+
public static Quaternion Identity
64+
{
65+
[Intrinsic]
66+
get => new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
67+
}
5868

5969
/// <summary>Gets or sets the element at the specified index.</summary>
6070
/// <param name="index">The index of the element to get or set.</param>
6171
/// <returns>The element at <paramref name="index" />.</returns>
6272
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
6373
public float this[int index]
6474
{
75+
[Intrinsic]
6576
readonly get => this.GetElement(index);
6677

6778
set => this = this.WithElement(index, value);
@@ -77,6 +88,7 @@ public float this[int index]
7788
/// <param name="value2">The second quaternion.</param>
7889
/// <returns>The quaternion that contains the summed values of <paramref name="value1" /> and <paramref name="value2" />.</returns>
7990
/// <remarks>The <see cref="op_Addition" /> method defines the operation of the addition operator for <see cref="Quaternion" /> objects.</remarks>
91+
[Intrinsic]
8092
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8193
public static Quaternion operator +(Quaternion value1, Quaternion value2) => (value1.AsVector128() + value2.AsVector128()).AsQuaternion();
8294

@@ -129,13 +141,15 @@ public float this[int index]
129141
/// <returns><see langword="true" /> if the two quaternions are equal; otherwise, <see langword="false" />.</returns>
130142
/// <remarks>Two quaternions are equal if each of their corresponding components is equal.
131143
/// The <see cref="op_Equality" /> method defines the operation of the equality operator for <see cref="Quaternion" /> objects.</remarks>
144+
[Intrinsic]
132145
[MethodImpl(MethodImplOptions.AggressiveInlining)]
133146
public static bool operator ==(Quaternion value1, Quaternion value2) => value1.AsVector128() == value2.AsVector128();
134147

135148
/// <summary>Returns a value that indicates whether two quaternions are not equal.</summary>
136149
/// <param name="value1">The first quaternion to compare.</param>
137150
/// <param name="value2">The second quaternion to compare.</param>
138151
/// <returns><see langword="true" /> if <paramref name="value1" /> and <paramref name="value2" /> are not equal; otherwise, <see langword="false" />.</returns>
152+
[Intrinsic]
139153
public static bool operator !=(Quaternion value1, Quaternion value2) => !(value1 == value2);
140154

141155
/// <summary>Returns the quaternion that results from multiplying two quaternions together.</summary>
@@ -191,6 +205,7 @@ public float this[int index]
191205
/// <param name="value2">The scalar value.</param>
192206
/// <returns>The scaled quaternion.</returns>
193207
/// <remarks>The <see cref="Quaternion.op_Multiply" /> method defines the operation of the multiplication operator for <see cref="Quaternion" /> objects.</remarks>
208+
[Intrinsic]
194209
[MethodImpl(MethodImplOptions.AggressiveInlining)]
195210
public static Quaternion operator *(Quaternion value1, float value2) => (value1.AsVector128() * value2).AsQuaternion();
196211

@@ -199,20 +214,23 @@ public float this[int index]
199214
/// <param name="value2">The second quaternion.</param>
200215
/// <returns>The quaternion containing the values that result from subtracting each element in <paramref name="value2" /> from its corresponding element in <paramref name="value1" />.</returns>
201216
/// <remarks>The <see cref="op_Subtraction" /> method defines the operation of the subtraction operator for <see cref="Quaternion" /> objects.</remarks>
217+
[Intrinsic]
202218
[MethodImpl(MethodImplOptions.AggressiveInlining)]
203219
public static Quaternion operator -(Quaternion value1, Quaternion value2) => (value1.AsVector128() - value2.AsVector128()).AsQuaternion();
204220

205221
/// <summary>Reverses the sign of each component of the quaternion.</summary>
206222
/// <param name="value">The quaternion to negate.</param>
207223
/// <returns>The negated quaternion.</returns>
208224
/// <remarks>The <see cref="op_UnaryNegation" /> method defines the operation of the unary negation operator for <see cref="Quaternion" /> objects.</remarks>
225+
[Intrinsic]
209226
[MethodImpl(MethodImplOptions.AggressiveInlining)]
210227
public static Quaternion operator -(Quaternion value) => (-value.AsVector128()).AsQuaternion();
211228

212229
/// <summary>Adds each element in one quaternion with its corresponding element in a second quaternion.</summary>
213230
/// <param name="value1">The first quaternion.</param>
214231
/// <param name="value2">The second quaternion.</param>
215232
/// <returns>The quaternion that contains the summed values of <paramref name="value1" /> and <paramref name="value2" />.</returns>
233+
[Intrinsic]
216234
public static Quaternion Add(Quaternion value1, Quaternion value2) => value1 + value2;
217235

218236
/// <summary>Concatenates two quaternions.</summary>
@@ -253,6 +271,7 @@ public static Quaternion Concatenate(Quaternion value1, Quaternion value2)
253271
/// <summary>Returns the conjugate of a specified quaternion.</summary>
254272
/// <param name="value">The quaternion.</param>
255273
/// <returns>A new quaternion that is the conjugate of <see langword="value" />.</returns>
274+
[Intrinsic]
256275
[MethodImpl(MethodImplOptions.AggressiveInlining)]
257276
public static Quaternion Conjugate(Quaternion value) => (value.AsVector128() * Vector128.Create(-1.0f, -1.0f, -1.0f, 1.0f)).AsQuaternion();
258277

@@ -372,12 +391,14 @@ public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float ro
372391
/// <param name="quaternion1">The first quaternion.</param>
373392
/// <param name="quaternion2">The second quaternion.</param>
374393
/// <returns>The dot product.</returns>
394+
[Intrinsic]
375395
[MethodImpl(MethodImplOptions.AggressiveInlining)]
376396
public static float Dot(Quaternion quaternion1, Quaternion quaternion2) => Vector128.Dot(quaternion1.AsVector128(), quaternion2.AsVector128());
377397

378398
/// <summary>Returns the inverse of a quaternion.</summary>
379399
/// <param name="value">The quaternion.</param>
380400
/// <returns>The inverted quaternion.</returns>
401+
[Intrinsic]
381402
[MethodImpl(MethodImplOptions.AggressiveInlining)]
382403
public static Quaternion Inverse(Quaternion value)
383404
{
@@ -440,16 +461,19 @@ public static Quaternion Lerp(Quaternion quaternion1, Quaternion quaternion2, fl
440461
/// <param name="value1">The source quaternion.</param>
441462
/// <param name="value2">The scalar value.</param>
442463
/// <returns>The scaled quaternion.</returns>
464+
[Intrinsic]
443465
public static Quaternion Multiply(Quaternion value1, float value2) => value1 * value2;
444466

445467
/// <summary>Reverses the sign of each component of the quaternion.</summary>
446468
/// <param name="value">The quaternion to negate.</param>
447469
/// <returns>The negated quaternion.</returns>
470+
[Intrinsic]
448471
public static Quaternion Negate(Quaternion value) => -value;
449472

450473
/// <summary>Divides each component of a specified <see cref="Quaternion" /> by its length.</summary>
451474
/// <param name="value">The quaternion to normalize.</param>
452475
/// <returns>The normalized quaternion.</returns>
476+
[Intrinsic]
453477
[MethodImpl(MethodImplOptions.AggressiveInlining)]
454478
public static Quaternion Normalize(Quaternion value) => (value.AsVector128() / value.Length()).AsQuaternion();
455479

@@ -506,6 +530,7 @@ public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, f
506530
/// <param name="value1">The first quaternion.</param>
507531
/// <param name="value2">The second quaternion.</param>
508532
/// <returns>The quaternion containing the values that result from subtracting each element in <paramref name="value2" /> from its corresponding element in <paramref name="value1" />.</returns>
533+
[Intrinsic]
509534
public static Quaternion Subtract(Quaternion value1, Quaternion value2) => value1 - value2;
510535

511536
/// <summary>Returns a value that indicates whether this instance and a specified object are equal.</summary>
@@ -527,10 +552,12 @@ public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, f
527552

528553
/// <summary>Calculates the length of the quaternion.</summary>
529554
/// <returns>The computed length of the quaternion.</returns>
555+
[Intrinsic]
530556
public readonly float Length() => MathF.Sqrt(LengthSquared());
531557

532558
/// <summary>Calculates the squared length of the quaternion.</summary>
533559
/// <returns>The length squared of the quaternion.</returns>
560+
[Intrinsic]
534561
public readonly float LengthSquared() => Dot(this, this);
535562

536563
/// <summary>Returns a string that represents this quaternion.</summary>

0 commit comments

Comments
 (0)