Skip to content

Commit b3fdac7

Browse files
Updating Vector256 to have its software fallback be 2x Vector128<T> ops (#76221)
* Updating Vector256<T> to be implemented as 2x Vector128<T> ops * Updating Vector256 to be implemented as 2x Vector128<T> ops * Simplify the NRE handling * A couple of small bug fixes * Ensure MONO_TYPE_I and MONO_TYPE_U are handled in simd-intrinsics * Ensure generic paths are handled for SN_CreateScalar and SN_CreateScalarUnsafe * Ensure nint/nuint are handled in the relevant fallback paths * Fixing braces to match mono code-styling * Fixing the "Any" implementation to use `||` * Fixing Narrow and Widen * Use Unsafe.ReadUnaligned for the software fallback of Vector256.AsVector() * Adjust an assert in fgMorphMultiregStructArg to account for certain Unsafe.As reinterprets
1 parent 221717b commit b3fdac7

File tree

8 files changed

+1191
-2036
lines changed

8 files changed

+1191
-2036
lines changed

src/coreclr/jit/morph.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,9 +3789,19 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg)
37893789
ArgElem& lastElem = elems[elemCount - 1];
37903790
assert((elemCount == arg->AbiInfo.NumRegs) || arg->AbiInfo.IsSplit());
37913791

3792+
if (layout != nullptr)
3793+
{
3794+
assert(ClassLayout::AreCompatible(typGetObjLayout(arg->GetSignatureClassHandle()), layout));
3795+
}
3796+
else
3797+
{
3798+
assert(varTypeIsSIMD(argValue) && varTypeIsSIMD(arg->GetSignatureType()));
3799+
}
3800+
37923801
if (arg->AbiInfo.IsHfaArg() && arg->AbiInfo.IsPassedInFloatRegisters())
37933802
{
37943803
var_types hfaType = arg->AbiInfo.GetHfaType();
3804+
37953805
for (unsigned inx = 0; inx < elemCount; inx++)
37963806
{
37973807
elems[inx].Type = hfaType;
@@ -3801,7 +3811,6 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg)
38013811
else
38023812
{
38033813
assert(structSize <= MAX_ARG_REG_COUNT * TARGET_POINTER_SIZE);
3804-
assert((layout != nullptr) || varTypeIsSIMD(argValue));
38053814

38063815
auto getSlotType = [layout](unsigned inx) {
38073816
return (layout != nullptr) ? layout->GetGCPtrType(inx) : TYP_I_IMPL;
@@ -3974,14 +3983,6 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg)
39743983
for (unsigned inx = 0; inx < elemCount; inx++)
39753984
{
39763985
unsigned offset = lclOffset + elems[inx].Offset;
3977-
#ifdef DEBUG
3978-
// Make sure we've set up correct GC types above.
3979-
unsigned slotIdx = offset / TARGET_POINTER_SIZE;
3980-
var_types argGcType = varTypeIsGC(elems[inx].Type) ? elems[inx].Type : TYP_I_IMPL;
3981-
var_types lclGcType = varDsc->HasGCPtr() ? varDsc->GetLayout()->GetGCPtrType(slotIdx) : TYP_I_IMPL;
3982-
assert(argGcType == lclGcType);
3983-
#endif // DEBUG
3984-
39853986
GenTree* lclFld = gtNewLclFldNode(lclNum, elems[inx].Type, offset);
39863987
newArg->AddField(this, lclFld, offset, lclFld->TypeGet());
39873988
}

src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristi
105105
{
106106
8 => ValueTypeShapeCharacteristics.Vector64Aggregate,
107107
16 => ValueTypeShapeCharacteristics.Vector128Aggregate,
108+
32 => ValueTypeShapeCharacteristics.Vector128Aggregate,
108109
_ => ValueTypeShapeCharacteristics.None
109110
};
110111
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ public static Vector128<T> Abs<T>(Vector128<T> vector)
6060
{
6161
return vector;
6262
}
63+
else if (typeof(T) == typeof(nuint))
64+
{
65+
return vector;
66+
}
6367
else if (typeof(T) == typeof(ushort))
6468
{
6569
return vector;
@@ -709,6 +713,14 @@ public static unsafe Vector128<T> Create<T>(T value)
709713
{
710714
return Create((long)(object)value).As<long, T>();
711715
}
716+
else if (typeof(T) == typeof(nint))
717+
{
718+
return Create((nint)(object)value).As<nint, T>();
719+
}
720+
else if (typeof(T) == typeof(nuint))
721+
{
722+
return Create((nuint)(object)value).As<nuint, T>();
723+
}
712724
else if (typeof(T) == typeof(sbyte))
713725
{
714726
return Create((sbyte)(object)value).As<sbyte, T>();
@@ -1538,6 +1550,20 @@ static Vector128<ulong> SoftwareFallback(Vector64<ulong> lower, Vector64<ulong>
15381550
}
15391551
}
15401552

1553+
/// <summary>Creates a new <see cref="Vector128{T}" /> instance with the first element initialized to the specified value and the remaining elements initialized to zero.</summary>
1554+
/// <typeparam name="T">The type of the elements in the vector.</typeparam>
1555+
/// <param name="value">The value that element 0 will be initialized to.</param>
1556+
/// <returns>A new <see cref="Vector128{T}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements initialized to zero.</returns>
1557+
/// <exception cref="NotSupportedException">The type of <paramref name="value" /> (<typeparamref name="T" />) is not supported.</exception>
1558+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1559+
internal static unsafe Vector128<T> CreateScalar<T>(T value)
1560+
where T : struct
1561+
{
1562+
Vector128<T> result = Vector128<T>.Zero;
1563+
result.SetElementUnsafe(0, value);
1564+
return result;
1565+
}
1566+
15411567
/// <summary>Creates a new <see cref="Vector128{Byte}" /> instance with the first element initialized to the specified value and the remaining elements initialized to zero.</summary>
15421568
/// <param name="value">The value that element 0 will be initialized to.</param>
15431569
/// <returns>A new <see cref="Vector128{Byte}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements initialized to zero.</returns>

0 commit comments

Comments
 (0)