Skip to content

Commit 15ffcff

Browse files
Expose an internal ISimdVector interface and being using it to deduplicate some SIMD code (#90764)
* Adding an internal ISimdVector`2 interface * Move LastIndexOfValueType to use ISimdVector`2 * Fix a couple minor whitespace nits and remove an unnecessary local
1 parent b9e0145 commit 15ffcff

File tree

15 files changed

+1963
-700
lines changed

15 files changed

+1963
-700
lines changed

src/coreclr/jit/hwintrinsicarm64.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,12 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
547547
case NI_Vector128_Ceiling:
548548
{
549549
assert(sig->numArgs == 1);
550-
assert(varTypeIsFloating(simdBaseType));
550+
551+
if (!varTypeIsFloating(simdBaseType))
552+
{
553+
retNode = impSIMDPopStack();
554+
break;
555+
}
551556

552557
op1 = impSIMDPopStack();
553558
retNode = gtNewSimdCeilNode(retType, op1, simdBaseJitType, simdSize);
@@ -1098,7 +1103,12 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
10981103
case NI_Vector128_Floor:
10991104
{
11001105
assert(sig->numArgs == 1);
1101-
assert(varTypeIsFloating(simdBaseType));
1106+
1107+
if (!varTypeIsFloating(simdBaseType))
1108+
{
1109+
retNode = impSIMDPopStack();
1110+
break;
1111+
}
11021112

11031113
op1 = impSIMDPopStack();
11041114
retNode = gtNewSimdFloorNode(retType, op1, simdBaseJitType, simdSize);

src/coreclr/jit/hwintrinsicxarch.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,7 +1371,12 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
13711371
case NI_Vector512_Ceiling:
13721372
{
13731373
assert(sig->numArgs == 1);
1374-
assert(varTypeIsFloating(simdBaseType));
1374+
1375+
if (!varTypeIsFloating(simdBaseType))
1376+
{
1377+
retNode = impSIMDPopStack();
1378+
break;
1379+
}
13751380

13761381
if ((simdSize < 32) && !compOpportunisticallyDependsOn(InstructionSet_SSE41))
13771382
{
@@ -1986,7 +1991,12 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
19861991
case NI_Vector512_Floor:
19871992
{
19881993
assert(sig->numArgs == 1);
1989-
assert(varTypeIsFloating(simdBaseType));
1994+
1995+
if (!varTypeIsFloating(simdBaseType))
1996+
{
1997+
retNode = impSIMDPopStack();
1998+
break;
1999+
}
19902000

19912001
if ((simdSize < 32) && !compOpportunisticallyDependsOn(InstructionSet_SSE41))
19922002
{

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,9 @@
10141014
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\UnmanagedType.cs" />
10151015
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\VarEnum.cs" />
10161016
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\VariantWrapper.cs" />
1017+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\ISimdVector_2.cs" />
10171018
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Scalar.cs" />
1019+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\SimdVectorExtensions.cs" />
10181020
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector128.cs" />
10191021
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector128_1.cs" />
10201022
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector128DebugView_1.cs" />

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs

Lines changed: 558 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace System.Runtime.Intrinsics
5+
{
6+
internal static unsafe class SimdVectorExtensions
7+
{
8+
// TODO: As<TFrom, TTo>
9+
10+
/// <summary>Copies a vector to a given array.</summary>
11+
/// <typeparam name="TVector">The type of the vector.</typeparam>
12+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
13+
/// <param name="vector">The vector to be copied.</param>
14+
/// <param name="destination">The array to which <paramref name="vector" /> is copied.</param>
15+
/// <exception cref="ArgumentException">The length of <paramref name="destination" /> is less than <see cref="ISimdVector{TVector, T}.Count" />.</exception>
16+
/// <exception cref="NullReferenceException"><paramref name="destination" /> is <c>null</c>.</exception>
17+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
18+
public static void CopyTo<TVector, T>(this TVector vector, T[] destination)
19+
where TVector : ISimdVector<TVector, T>
20+
{
21+
TVector.CopyTo(vector, destination);
22+
}
23+
24+
/// <summary>Copies a vector to a given array starting at the specified index.</summary>
25+
/// <typeparam name="TVector">The type of the vector.</typeparam>
26+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
27+
/// <param name="vector">The vector to be copied.</param>
28+
/// <param name="destination">The array to which <paramref name="vector" /> is copied.</param>
29+
/// <param name="startIndex">The starting index of <paramref name="destination" /> which <paramref name="vector" /> will be copied to.</param>
30+
/// <exception cref="ArgumentException">The length of <paramref name="destination" /> is less than <see cref="ISimdVector{TVector, T}.Count" />.</exception>
31+
/// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex" /> is negative or greater than the length of <paramref name="destination" />.</exception>
32+
/// <exception cref="NullReferenceException"><paramref name="destination" /> is <c>null</c>.</exception>
33+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
34+
public static void CopyTo<TVector, T>(this TVector vector, T[] destination, int startIndex)
35+
where TVector : ISimdVector<TVector, T>
36+
{
37+
TVector.CopyTo(vector, destination, startIndex);
38+
}
39+
40+
/// <summary>Copies a vector to a given span.</summary>
41+
/// <typeparam name="TVector">The type of the vector.</typeparam>
42+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
43+
/// <param name="vector">The vector to be copied.</param>
44+
/// <param name="destination">The span to which the <paramref name="vector" /> is copied.</param>
45+
/// <exception cref="ArgumentException">The length of <paramref name="destination" /> is less than <see cref="ISimdVector{TVector, T}.Count" />.</exception>
46+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
47+
public static void CopyTo<TVector, T>(this TVector vector, Span<T> destination)
48+
where TVector : ISimdVector<TVector, T>
49+
{
50+
TVector.CopyTo(vector, destination);
51+
}
52+
53+
/// <summary>Gets the element at the specified index.</summary>
54+
/// <typeparam name="TVector">The type of the vector.</typeparam>
55+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
56+
/// <param name="vector">The vector to get the element from.</param>
57+
/// <param name="index">The index of the element to get.</param>
58+
/// <returns>The value of the element at <paramref name="index" />.</returns>
59+
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
60+
/// <exception cref="NotSupportedException">The type of <paramref name="vector" /> (<typeparamref name="T" />) is not supported.</exception>
61+
public static T GetElement<TVector, T>(this TVector vector, int index)
62+
where TVector : ISimdVector<TVector, T>
63+
{
64+
return TVector.GetElement(vector, index);
65+
}
66+
67+
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T')
68+
/// <summary>Stores a vector at the given destination.</summary>
69+
/// <typeparam name="TVector">The type of the vector.</typeparam>
70+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
71+
/// <param name="source">The vector that will be stored.</param>
72+
/// <param name="destination">The destination at which <paramref name="source" /> will be stored.</param>
73+
/// <exception cref="NotSupportedException">The type of <paramref name="source" /> (<typeparamref name="T" />) is not supported.</exception>
74+
public static void Store<TVector, T>(this TVector source, T* destination)
75+
where TVector : ISimdVector<TVector, T>
76+
{
77+
TVector.Store(source, destination);
78+
}
79+
80+
/// <summary>Stores a vector at the given aligned destination.</summary>
81+
/// <typeparam name="TVector">The type of the vector.</typeparam>
82+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
83+
/// <param name="source">The vector that will be stored.</param>
84+
/// <param name="destination">The aligned destination at which <paramref name="source" /> will be stored.</param>
85+
/// <exception cref="NotSupportedException">The type of <paramref name="source" /> (<typeparamref name="T" />) is not supported.</exception>
86+
public static void StoreAligned<TVector, T>(this TVector source, T* destination)
87+
where TVector : ISimdVector<TVector, T>
88+
{
89+
TVector.StoreAligned(source, destination);
90+
}
91+
92+
/// <summary>Stores a vector at the given aligned destination.</summary>
93+
/// <typeparam name="TVector">The type of the vector.</typeparam>
94+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
95+
/// <param name="source">The vector that will be stored.</param>
96+
/// <param name="destination">The aligned destination at which <paramref name="source" /> will be stored.</param>
97+
/// <remarks>This method may bypass the cache on certain platforms.</remarks>
98+
/// <exception cref="NotSupportedException">The type of <paramref name="source" /> (<typeparamref name="T" />) is not supported.</exception>
99+
public static void StoreAlignedNonTemporal<TVector, T>(this TVector source, T* destination)
100+
where TVector : ISimdVector<TVector, T>
101+
{
102+
TVector.StoreAlignedNonTemporal(source, destination);
103+
}
104+
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T')
105+
106+
/// <summary>Stores a vector at the given destination.</summary>
107+
/// <typeparam name="TVector">The type of the vector.</typeparam>
108+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
109+
/// <param name="vector">The vector that will be stored.</param>
110+
/// <param name="destination">The destination at which the vector will be stored.</param>
111+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
112+
public static void StoreUnsafe<TVector, T>(this TVector vector, ref T destination)
113+
where TVector : ISimdVector<TVector, T>
114+
{
115+
TVector.StoreUnsafe(vector, ref destination);
116+
}
117+
118+
/// <summary>Stores a vector at the given destination.</summary>
119+
/// <typeparam name="TVector">The type of the vector.</typeparam>
120+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
121+
/// <param name="vector">The vector that will be stored.</param>
122+
/// <param name="destination">The destination to which <paramref name="elementOffset" /> will be added before the vector will be stored.</param>
123+
/// <param name="elementOffset">The element offset from <paramref name="destination" /> from which the vector will be stored.</param>
124+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
125+
public static void StoreUnsafe<TVector, T>(this TVector vector, ref T destination, nuint elementOffset)
126+
where TVector : ISimdVector<TVector, T>
127+
{
128+
TVector.StoreUnsafe(vector, ref destination, elementOffset);
129+
}
130+
131+
/// <summary>Converts the given vector to a scalar containing the value of the first element.</summary>
132+
/// <typeparam name="TVector">The type of the vector.</typeparam>
133+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
134+
/// <param name="vector">The vector to get the first element from.</param>
135+
/// <returns>A scalar <typeparamref name="T" /> containing the value of the first element.</returns>
136+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
137+
public static T ToScalar<TVector, T>(this TVector vector)
138+
where TVector : ISimdVector<TVector, T>
139+
{
140+
return TVector.ToScalar(vector);
141+
}
142+
143+
/// <summary>Tries to copy a vector to a given span.</summary>
144+
/// <typeparam name="TVector">The type of the vector.</typeparam>
145+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
146+
/// <param name="vector">The vector to copy.</param>
147+
/// <param name="destination">The span to which <paramref name="destination" /> is copied.</param>
148+
/// <returns><c>true</c> if <paramref name="vector" /> was successfully copied to <paramref name="destination" />; otherwise, <c>false</c> if the length of <paramref name="destination" /> is less than <see cref="ISimdVector{TVector, T}.Count" />.</returns>
149+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
150+
public static bool TryCopyTo<TVector, T>(this TVector vector, Span<T> destination)
151+
where TVector : ISimdVector<TVector, T>
152+
{
153+
return TVector.TryCopyTo(vector, destination);
154+
}
155+
156+
/// <summary>Creates a new vector with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector.</summary>
157+
/// <typeparam name="TVector">The type of the vector.</typeparam>
158+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
159+
/// <param name="vector">The vector to get the remaining elements from.</param>
160+
/// <param name="index">The index of the element to set.</param>
161+
/// <param name="value">The value to set the element to.</param>
162+
/// <returns>A vector 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="vector" />.</returns>
163+
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
164+
/// <exception cref="NotSupportedException">The type of the elements in the vector (<typeparamref name="T" />) is not supported.</exception>
165+
public static TVector WithElement<TVector, T>(this TVector vector, int index, T value)
166+
where TVector : ISimdVector<TVector, T>
167+
{
168+
return TVector.WithElement(vector, index, value);
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)