}
break;
}
+
+ case NI_VectorT128_Sum:
+ {
+ // TODO-XArch-CQ: We could support this all the way down to SSE2 and that might be
+ // worthwhile so we can accelerate cases like byte/sbyte and long/ulong
+
+ if (varTypeIsFloating(simdBaseType))
+ {
+ if (!compOpportunisticallyDependsOn(InstructionSet_SSE3))
+ {
+ // Floating-point types require SSE3.HorizontalAdd
+ return nullptr;
+ }
+ }
+ else if (!compOpportunisticallyDependsOn(InstructionSet_SSSE3))
+ {
+ // Integral types require SSSE3.HorizontalAdd
+ return nullptr;
+ }
+ break;
+ }
#endif // TARGET_XARCH
default:
}
case NI_VectorT128_Sum:
{
- if (compOpportunisticallyDependsOn(InstructionSet_SSSE3))
- {
- GenTree* tmp;
- unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType);
- int haddCount = genLog2(vectorLength);
- for (int i = 0; i < haddCount; i++)
- {
- op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL,
- nullptr DEBUGARG("Clone op1 for Vector<T>.Sum"));
- op1 = gtNewSimdAsHWIntrinsicNode(simdType, op1, tmp, NI_SSSE3_HorizontalAdd,
- simdBaseJitType, simdSize);
- }
+ GenTree* tmp;
+ unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType);
+ int haddCount = genLog2(vectorLength);
- return gtNewSimdAsHWIntrinsicNode(retType, op1, NI_Vector128_ToScalar, simdBaseJitType,
- simdSize);
+ NamedIntrinsic horizontalAdd =
+ varTypeIsFloating(simdBaseType) ? NI_SSE3_HorizontalAdd : NI_SSSE3_HorizontalAdd;
+
+ for (int i = 0; i < haddCount; i++)
+ {
+ op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL,
+ nullptr DEBUGARG("Clone op1 for Vector<T>.Sum"));
+ op1 = gtNewSimdAsHWIntrinsicNode(simdType, op1, tmp, horizontalAdd, simdBaseJitType, simdSize);
}
- return nullptr;
+ return gtNewSimdAsHWIntrinsicNode(retType, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize);
}
case NI_VectorT256_Sum:
{
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+using System;
+using System.Numerics;
+using System.Runtime.Intrinsics.Arm;
+using System.Runtime.Intrinsics.X86;
+
+internal partial class VectorTest
+{
+ private const int Pass = 100;
+ private const int Fail = -1;
+
+ private class VectorSumTest<T> where T : struct, IComparable<T>, IEquatable<T>
+ {
+ public static int VectorSum(T a, T b)
+ {
+ Vector<T> A = new Vector<T>(a);
+ T B = Vector.Sum(A);
+
+ if (!(CheckValue<T>(B, b)))
+ {
+ return Fail;
+ }
+ return Pass;
+ }
+ }
+
+ private static int Main()
+ {
+ int returnVal = Pass;
+
+ if (VectorSumTest<float>.VectorSum(1, (float)Vector<float>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<double>.VectorSum(1, (double)Vector<double>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<int>.VectorSum(1, (int)Vector<int>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<long>.VectorSum(1, (long)Vector<long>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<ushort>.VectorSum(1, (ushort)Vector<ushort>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<byte>.VectorSum(1, (byte)Vector<byte>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<short>.VectorSum(-1, (short)(-Vector<short>.Count)) != Pass) returnVal = Fail;
+ if (VectorSumTest<sbyte>.VectorSum(-1, (sbyte)(-Vector<sbyte>.Count)) != Pass) returnVal = Fail;
+ if (VectorSumTest<uint>.VectorSum(0x41000000u, 0x41000000u * (uint)Vector<uint>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<ulong>.VectorSum(0x4100000000000000ul, 0x4100000000000000ul * (uint)Vector<ulong>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<nint>.VectorSum(1, (nint)Vector<nint>.Count) != Pass) returnVal = Fail;
+ if (VectorSumTest<nuint>.VectorSum(0x41000000u, 0x41000000u * (nuint)(uint)Vector<nuint>.Count) != Pass) returnVal = Fail;
+
+ JitLog jitLog = new JitLog();
+
+ if (Sse3.IsSupported || AdvSimd.IsSupported)
+ {
+ if (!jitLog.Check("Sum", "Single")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "Double")) returnVal = Fail;
+ }
+
+ if (Ssse3.IsSupported || AdvSimd.IsSupported)
+ {
+ if (!jitLog.Check("Sum", "Int16")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "Int32")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "UInt16")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "UInt32")) returnVal = Fail;
+ }
+
+ if (AdvSimd.IsSupported)
+ {
+ if (!jitLog.Check("Sum", "Byte")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "Int64")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "IntPtr")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "SByte")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "UInt64")) returnVal = Fail;
+ if (!jitLog.Check("Sum", "UIntPtr")) returnVal = Fail;
+ }
+
+ jitLog.Dispose();
+
+ return returnVal;
+ }
+}