diff options
author | Jacek Blaszczynski <biosciencenow@outlook.com> | 2018-09-21 01:09:36 +0200 |
---|---|---|
committer | Tanner Gooding <tagoo@outlook.com> | 2018-09-20 16:09:36 -0700 |
commit | 4180182cae098b55cb6e2711cb2c2c43decaac0a (patch) | |
tree | 079048b756acc20a80a3deee523e6fc3cbf9e545 /tests | |
parent | e30f187cda3767e1c50b870864de8d0eb5f8582a (diff) | |
download | coreclr-4180182cae098b55cb6e2711cb2c2c43decaac0a.tar.gz coreclr-4180182cae098b55cb6e2711cb2c2c43decaac0a.tar.bz2 coreclr-4180182cae098b55cb6e2711cb2c2c43decaac0a.zip |
Convert Sse2 tests PackSignedSaturate, PackUnsignedSaturate, UnpackHigh and UnpackLow to template based (#19670)
* Convert PackSignedSaturate, PackUnsignedSaturate, UnpackHigh, UnpackLow tests to template based
* Add generated Sse2 Pack***Saturate, UnpackHigh, UnpackLow tests, remove replaced tests
* Remove deleted Sse2 Pack** Unpack** tests from Test.lst files for arm and arm64 Windows targets
Diffstat (limited to 'tests')
39 files changed, 8559 insertions, 1248 deletions
diff --git a/tests/arm/Tests.lst b/tests/arm/Tests.lst index 26257ae1e3..bf868fe5e7 100644 --- a/tests/arm/Tests.lst +++ b/tests/arm/Tests.lst @@ -1,9 +1,9 @@ ## This list file has been produced automatically. Any changes ## are subject to being overwritten when reproducing this file. -## +## ## Last Updated: 09-May-2018 17:42:09 ## Commit: aa8dd0d8a9b1bb47e00fcd694342ed5defb46508 -## +## [int8_il_r.cmd_1] RelativePath=JIT\Directed\shift\int8_il_r\int8_il_r.cmd WorkingDir=JIT\Directed\shift\int8_il_r @@ -91364,14 +91364,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[UnpackLow_ro.cmd_11532] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_ro\UnpackLow_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [LoadAlignedVector128_ro.cmd_11533] RelativePath=JIT\HardwareIntrinsics\X86\Sse2\LoadAlignedVector128_ro\LoadAlignedVector128_ro.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\LoadAlignedVector128_ro @@ -91820,22 +91812,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[UnpackHigh_r.cmd_11596] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_r\UnpackHigh_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - -[PackSignedSaturate_r.cmd_11597] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_r\PackSignedSaturate_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [Sqrt_ro.cmd_11598] RelativePath=JIT\HardwareIntrinsics\X86\Sse\Sqrt_ro\Sqrt_ro.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse\Sqrt_ro @@ -92380,14 +92356,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW HostStyle=0 -[PackUnsignedSaturate_ro.cmd_11679] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_ro\PackUnsignedSaturate_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [Equality.cmd_11680] RelativePath=JIT\opt\Types\Equality\Equality.cmd WorkingDir=JIT\opt\Types\Equality @@ -93212,14 +93180,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[PackSignedSaturate_ro.cmd_11804] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_ro\PackSignedSaturate_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [HorizontalAdd_r.cmd_11805] RelativePath=JIT\HardwareIntrinsics\X86\Avx\HorizontalAdd_r\HorizontalAdd_r.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Avx\HorizontalAdd_r @@ -93468,14 +93428,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW HostStyle=0 -[UnpackLow_r.cmd_11838] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_r\UnpackLow_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [ReciprocalSqrtScalar_r.cmd_11839] RelativePath=JIT\HardwareIntrinsics\X86\Sse\ReciprocalSqrtScalar_r\ReciprocalSqrtScalar_r.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse\ReciprocalSqrtScalar_r @@ -93524,14 +93476,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW HostStyle=0 -[UnpackHigh_ro.cmd_11845] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_ro\UnpackHigh_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [ConvertToVector128_r.cmd_11846] RelativePath=JIT\HardwareIntrinsics\X86\Sse41\ConvertToVector128_r\ConvertToVector128_r.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse41\ConvertToVector128_r @@ -93612,14 +93556,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[PackUnsignedSaturate_r.cmd_11858] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_r\PackUnsignedSaturate_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [genericcontext.cmd_11859] RelativePath=Regressions\coreclr\15241\genericcontext\genericcontext.cmd WorkingDir=Regressions\coreclr\15241\genericcontext diff --git a/tests/arm64/Tests.lst b/tests/arm64/Tests.lst index 8bb2287dc8..5bd7cdef5e 100644 --- a/tests/arm64/Tests.lst +++ b/tests/arm64/Tests.lst @@ -1,9 +1,9 @@ ## This list file has been produced automatically. Any changes ## are subject to being overwritten when reproducing this file. -## +## ## Last Updated: 09-May-2018 17:46:52 ## Commit: aa8dd0d8a9b1bb47e00fcd694342ed5defb46508 -## +## [Dev10_535767.cmd_0] RelativePath=baseservices\compilerservices\dynamicobjectproperties\Dev10_535767\Dev10_535767.cmd WorkingDir=baseservices\compilerservices\dynamicobjectproperties\Dev10_535767 @@ -91364,14 +91364,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[UnpackLow_ro.cmd_11849] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_ro\UnpackLow_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [LoadAlignedVector128_ro.cmd_11850] RelativePath=JIT\HardwareIntrinsics\X86\Sse2\LoadAlignedVector128_ro\LoadAlignedVector128_ro.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\LoadAlignedVector128_ro @@ -91828,22 +91820,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[UnpackHigh_r.cmd_11913] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_r\UnpackHigh_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - -[PackSignedSaturate_r.cmd_11914] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_r\PackSignedSaturate_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [Sqrt_ro.cmd_11915] RelativePath=JIT\HardwareIntrinsics\X86\Sse\Sqrt_ro\Sqrt_ro.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse\Sqrt_ro @@ -92388,14 +92364,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW HostStyle=0 -[PackUnsignedSaturate_ro.cmd_11997] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_ro\PackUnsignedSaturate_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [Equality.cmd_11998] RelativePath=JIT\opt\Types\Equality\Equality.cmd WorkingDir=JIT\opt\Types\Equality @@ -93228,14 +93196,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[PackSignedSaturate_ro.cmd_12123] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_ro\PackSignedSaturate_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackSignedSaturate_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [eventsourcetrace.cmd_12124] RelativePath=tracing\eventsourcetrace\eventsourcetrace\eventsourcetrace.cmd WorkingDir=tracing\eventsourcetrace\eventsourcetrace @@ -93452,14 +93412,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW HostStyle=0 -[UnpackLow_r.cmd_12153] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_r\UnpackLow_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackLow_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [ReciprocalSqrtScalar_r.cmd_12154] RelativePath=JIT\HardwareIntrinsics\X86\Sse\ReciprocalSqrtScalar_r\ReciprocalSqrtScalar_r.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse\ReciprocalSqrtScalar_r @@ -93508,14 +93460,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW HostStyle=0 -[UnpackHigh_ro.cmd_12160] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_ro\UnpackHigh_ro.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\UnpackHigh_ro -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [ConvertToVector128_r.cmd_12161] RelativePath=JIT\HardwareIntrinsics\X86\Sse41\ConvertToVector128_r\ConvertToVector128_r.cmd WorkingDir=JIT\HardwareIntrinsics\X86\Sse41\ConvertToVector128_r @@ -93580,14 +93524,6 @@ MaxAllowedDurationSeconds=600 Categories=EXPECTED_PASS;NEW;EXCLUDED HostStyle=0 -[PackUnsignedSaturate_r.cmd_12172] -RelativePath=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_r\PackUnsignedSaturate_r.cmd -WorkingDir=JIT\HardwareIntrinsics\X86\Sse2\PackUnsignedSaturate_r -Expected=0 -MaxAllowedDurationSeconds=600 -Categories=EXPECTED_PASS;NEW;EXCLUDED -HostStyle=0 - [genericcontext.cmd_12173] RelativePath=Regressions\coreclr\15241\genericcontext\genericcontext.cmd WorkingDir=Regressions\coreclr\15241\genericcontext diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx index 191d0bf6af..469dddb84c 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx @@ -203,6 +203,9 @@ private static readonly (string templateFileName, Dictionary<string, string> tem ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "(ushort)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(ushort)(left[i] | right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "(uint)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(uint)(left[i] | right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "(ulong)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(ulong)(left[i] | right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (short)Math.Min(Math.Max(left[0], short.MinValue), short.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 4) ? (short)Math.Min(Math.Max(left[i], short.MinValue), short.MaxValue) : (short)Math.Min(Math.Max(right[i%4], short.MinValue), short.MaxValue))"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (sbyte)Math.Min(Math.Max(left[0], sbyte.MinValue), sbyte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 8) ? (sbyte)Math.Min(Math.Max(left[i], sbyte.MinValue), sbyte.MaxValue) : (sbyte)Math.Min(Math.Max(right[i%8], sbyte.MinValue), sbyte.MaxValue))"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (byte)Math.Min(Math.Max(left[0], byte.MinValue), byte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 8) ? (byte)Math.Min(Math.Max(left[i], byte.MinValue), byte.MaxValue) : (byte)Math.Min(Math.Max(right[i%8], byte.MinValue), byte.MaxValue))"}), ("ScalarSimdUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SetAllVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != firstOp", ["ValidateRemainingResults"] = "result[i] != firstOp"}), ("ScalarSimdUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SetAllVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != firstOp", ["ValidateRemainingResults"] = "result[i] != firstOp"}), ("ScalarSimdUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SetAllVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != firstOp", ["ValidateRemainingResults"] = "result[i] != firstOp"}), @@ -270,6 +273,24 @@ private static readonly (string templateFileName, Dictionary<string, string> tem ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Sse2Verify.SubtractSaturate(left[0], right[0], result[0])", ["ValidateRemainingResults"] = "Sse2Verify.SubtractSaturate(left[i], right[i], result[i])"}), ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "Sse2Verify.SubtractSaturate(left[0], right[0], result[0])", ["ValidateRemainingResults"] = "Sse2Verify.SubtractSaturate(left[i], right[i], result[i])"}), ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0] - right[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[1])", ["ValidateRemainingResults"] = "(i % 2 == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2+1]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2 + 1])"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != left[1] || result[1] != right[1]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != left[1] || result[1] != right[1]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != left[2]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != left[2]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != left[4]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != left[4]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != left[8]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != left[8]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[0])", ["ValidateRemainingResults"] = "(i % 2 == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2])"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != left[0] || result[1] != right[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != left[0] || result[1] != right[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(BitConverter.DoubleToInt64Bits(left[0]) ^ BitConverter.DoubleToInt64Bits(right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(left[i]) ^ BitConverter.DoubleToInt64Bits(right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "(byte)(left[0] ^ right[0]) != result[0]", ["ValidateRemainingResults"] = "(byte)(left[i] ^ right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "(short)(left[0] ^ right[0]) != result[0]", ["ValidateRemainingResults"] = "(short)(left[i] ^ right[i]) != result[i]"}), diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.Int16.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.Int16.cs new file mode 100644 index 0000000000..02b94e9eef --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.Int16.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void PackSignedSaturateInt16() + { + var test = new SimpleBinaryOpTest__PackSignedSaturateInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PackSignedSaturateInt16 + { + private struct TestStruct + { + public Vector128<Int32> _fld1; + public Vector128<Int32> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PackSignedSaturateInt16 testClass) + { + var result = Sse2.PackSignedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128<Int32> _clsVar1; + private static Vector128<Int32> _clsVar2; + + private Vector128<Int32> _fld1; + private Vector128<Int32> _fld2; + + private SimpleBinaryOpTest__DataTable<Int16, Int32, Int32> _dataTable; + + static SimpleBinaryOpTest__PackSignedSaturateInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + } + + public SimpleBinaryOpTest__PackSignedSaturateInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Int16, Int32, Int32>(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.PackSignedSaturate( + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.PackSignedSaturate( + Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.PackSignedSaturate( + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackSignedSaturate), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackSignedSaturate), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackSignedSaturate), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.PackSignedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr); + var result = Sse2.PackSignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Sse2.PackSignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Sse2.PackSignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PackSignedSaturateInt16(); + var result = Sse2.PackSignedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.PackSignedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.PackSignedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int32> left, Vector128<Int32> right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [CallerMemberName] string method = "") + { + if (result[0] != (short)Math.Min(Math.Max(left[0], short.MinValue), short.MaxValue)) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != ((i < 4) ? (short)Math.Min(Math.Max(left[i], short.MinValue), short.MaxValue) : (short)Math.Min(Math.Max(right[i%4], short.MinValue), short.MaxValue))) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.PackSignedSaturate)}<Int16>(Vector128<Int32>, Vector128<Int32>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.SByte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.SByte.cs new file mode 100644 index 0000000000..7f02656842 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.SByte.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void PackSignedSaturateSByte() + { + var test = new SimpleBinaryOpTest__PackSignedSaturateSByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PackSignedSaturateSByte + { + private struct TestStruct + { + public Vector128<Int16> _fld1; + public Vector128<Int16> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PackSignedSaturateSByte testClass) + { + var result = Sse2.PackSignedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128<Int16> _clsVar1; + private static Vector128<Int16> _clsVar2; + + private Vector128<Int16> _fld1; + private Vector128<Int16> _fld2; + + private SimpleBinaryOpTest__DataTable<SByte, Int16, Int16> _dataTable; + + static SimpleBinaryOpTest__PackSignedSaturateSByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + } + + public SimpleBinaryOpTest__PackSignedSaturateSByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new SimpleBinaryOpTest__DataTable<SByte, Int16, Int16>(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.PackSignedSaturate( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.PackSignedSaturate( + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.PackSignedSaturate( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackSignedSaturate), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackSignedSaturate), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackSignedSaturate), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.PackSignedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr); + var result = Sse2.PackSignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.PackSignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.PackSignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PackSignedSaturateSByte(); + var result = Sse2.PackSignedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.PackSignedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.PackSignedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> left, Vector128<Int16> right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [CallerMemberName] string method = "") + { + if (result[0] != (sbyte)Math.Min(Math.Max(left[0], sbyte.MinValue), sbyte.MaxValue)) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != ((i < 8) ? (sbyte)Math.Min(Math.Max(left[i], sbyte.MinValue), sbyte.MaxValue) : (sbyte)Math.Min(Math.Max(right[i%8], sbyte.MinValue), sbyte.MaxValue))) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.PackSignedSaturate)}<SByte>(Vector128<Int16>, Vector128<Int16>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.cs deleted file mode 100644 index ebe447d1c9..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace IntelHardwareIntrinsicTest -{ - internal static partial class Program - { - const int Pass = 100; - const int Fail = 0; - - internal static unsafe int Main(string[] args) - { - int testResult = Pass; - int testsCount = 21; - string methodUnderTestName = nameof(Sse2.PackSignedSaturate); - - if (Sse2.IsSupported) - { - using (var intTable = TestTableSse2<int, short>.Create(testsCount, 0.5)) - using (var shortTable = TestTableSse2<short, sbyte>.Create(testsCount, 0.5)) - { - intTable.Initialize(InitMode.NumberFirstVectors); - for (int i = 0; i < testsCount; i++) - { - (Vector128<int>, Vector128<int>) value = intTable[i]; - Vector128<short> result = Sse2.PackSignedSaturate(value.Item1, value.Item2); - intTable.SetOutArrayU(result, i); - } - - shortTable.Initialize(InitMode.NumberFirstVectors); - for (int i = 0; i < testsCount; i++) - { - (Vector128<short>, Vector128<short>) value = shortTable[i]; - Vector128<sbyte> result = Sse2.PackSignedSaturate(value.Item1, value.Item2); - shortTable.SetOutArrayU(result); - } - - CheckMethodSix<int, short> checkInt32 = - (ValueTuple<int, int, int, int> x, ValueTuple<int, int, int, int> y, - ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> z, - ref short a1, ref short a2, ref short a3, ref short a4, ref short a5, ref short a6, ref short a7, ref short a8) => - { - a1 = ToInt16Saturate(x.Item1); - a2 = ToInt16Saturate(x.Item2); - a3 = ToInt16Saturate(x.Item3); - a4 = ToInt16Saturate(x.Item4); - a5 = ToInt16Saturate(y.Item1); - a6 = ToInt16Saturate(y.Item2); - a7 = ToInt16Saturate(y.Item3); - a8 = ToInt16Saturate(y.Item4); - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4 && - a5 == z.Item5 && a6 == z.Item6 && a7 == z.Item7 && a8 == z.Item8; - }; - - if (!intTable.CheckPackSaturate(checkInt32)) - { - PrintError(intTable, methodUnderTestName, "CheckPackSaturate", checkInt32); - testResult = Fail; - } - - CheckMethodSixteen<short, sbyte> checkInt16 = - (ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> x, - ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> y, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> z1, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> z2, - ref sbyte a1, ref sbyte a2, ref sbyte a3, ref sbyte a4, ref sbyte a5, ref sbyte a6, ref sbyte a7, ref sbyte a8, - ref sbyte a9, ref sbyte a10, ref sbyte a11, ref sbyte a12, ref sbyte a13, ref sbyte a14, ref sbyte a15, ref sbyte a16) => - { - a1 = ToSByteSaturate(x.Item1); - a2 = ToSByteSaturate(x.Item2); - a3 = ToSByteSaturate(x.Item3); - a4 = ToSByteSaturate(x.Item4); - a5 = ToSByteSaturate(x.Item5); - a6 = ToSByteSaturate(x.Item6); - a7 = ToSByteSaturate(x.Item7); - a8 = ToSByteSaturate(x.Item8); - a9 = ToSByteSaturate(y.Item1); - a10 = ToSByteSaturate(y.Item2); - a11 = ToSByteSaturate(y.Item3); - a12 = ToSByteSaturate(y.Item4); - a13 = ToSByteSaturate(y.Item5); - a14 = ToSByteSaturate(y.Item6); - a15 = ToSByteSaturate(y.Item7); - a16 = ToSByteSaturate(y.Item8); - - return a1 == z1.Item1 && a2 == z1.Item2 && a3 == z1.Item3 && a4 == z1.Item4 && - a5 == z1.Item5 && a6 == z1.Item6 && a7 == z1.Item7 && a8 == z1.Item8 && - a9 == z2.Item1 && a10 == z2.Item2 && a11 == z2.Item3 && a12 == z2.Item4 && - a13 == z2.Item5 && a14 == z2.Item6 && a15 == z2.Item7 && a16 == z2.Item8; - }; - - - if (!shortTable.CheckPackSaturate(checkInt16)) - { - PrintError(shortTable, methodUnderTestName, "CheckPackSaturate", checkInt16); - testResult = Fail; - } - } - } - else - { - Console.WriteLine($"Sse2.IsSupported: {Sse2.IsSupported}, skipped tests of {typeof(Sse2)}.{methodUnderTestName}"); - } - return testResult; - } - - private static short ToInt16Saturate(int value) - { - return (short)(value > short.MaxValue ? short.MaxValue : value < short.MinValue ? short.MinValue : value); - } - - private static sbyte ToSByteSaturate(short value) - { - return (sbyte)(value > sbyte.MaxValue ? sbyte.MaxValue : value < sbyte.MinValue ? sbyte.MinValue : value); - } - } -} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate_r.csproj deleted file mode 100644 index 6d91074990..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate_r.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{A0B71B98-843A-4CEB-84D5-EF1058A4830D}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize></Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="PackSignedSaturate.cs" /> - <Compile Include="TestTableSse2.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate_ro.csproj deleted file mode 100644 index 7ee2401d28..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackSignedSaturate_ro.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{A1A59671-D8A9-4580-9211-9DCB9CDC338F}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize>True</Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="PackSignedSaturate.cs" /> - <Compile Include="TestTableSse2.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate.Byte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate.Byte.cs new file mode 100644 index 0000000000..21575637ac --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate.Byte.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void PackUnsignedSaturateByte() + { + var test = new SimpleBinaryOpTest__PackUnsignedSaturateByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PackUnsignedSaturateByte + { + private struct TestStruct + { + public Vector128<Int16> _fld1; + public Vector128<Int16> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PackUnsignedSaturateByte testClass) + { + var result = Sse2.PackUnsignedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128<Int16> _clsVar1; + private static Vector128<Int16> _clsVar2; + + private Vector128<Int16> _fld1; + private Vector128<Int16> _fld2; + + private SimpleBinaryOpTest__DataTable<Byte, Int16, Int16> _dataTable; + + static SimpleBinaryOpTest__PackUnsignedSaturateByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + } + + public SimpleBinaryOpTest__PackUnsignedSaturateByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Byte, Int16, Int16>(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.PackUnsignedSaturate( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.PackUnsignedSaturate( + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.PackUnsignedSaturate( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackUnsignedSaturate), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackUnsignedSaturate), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.PackUnsignedSaturate), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.PackUnsignedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr); + var result = Sse2.PackUnsignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.PackUnsignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.PackUnsignedSaturate(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PackUnsignedSaturateByte(); + var result = Sse2.PackUnsignedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.PackUnsignedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.PackUnsignedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> left, Vector128<Int16> right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Byte[] result, [CallerMemberName] string method = "") + { + if (result[0] != (byte)Math.Min(Math.Max(left[0], byte.MinValue), byte.MaxValue)) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != ((i < 8) ? (byte)Math.Min(Math.Max(left[i], byte.MinValue), byte.MaxValue) : (byte)Math.Min(Math.Max(right[i%8], byte.MinValue), byte.MaxValue))) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.PackUnsignedSaturate)}<Byte>(Vector128<Int16>, Vector128<Int16>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate.cs deleted file mode 100644 index c0e6a0848a..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace IntelHardwareIntrinsicTest -{ - internal static partial class Program - { - const int Pass = 100; - const int Fail = 0; - - internal static unsafe int Main(string[] args) - { - int testResult = Pass; - int testsCount = 21; - string methodUnderTestName = nameof(Sse2.PackUnsignedSaturate); - - if (Sse2.IsSupported) - { - using (var shortTable = TestTableSse2<short, byte>.Create(testsCount, 0.5)) - { - for (int i = 0; i < testsCount; i++) - { - (Vector128<short>, Vector128<short>) value = shortTable[i]; - Vector128<byte> result = Sse2.PackUnsignedSaturate(value.Item1, value.Item2); - shortTable.SetOutArrayU(result); - } - - CheckMethodSixteen<short, byte> checkInt16 = - (ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> x, - ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> y, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> z1, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> z2, - ref byte a1, ref byte a2, ref byte a3, ref byte a4, ref byte a5, ref byte a6, ref byte a7, ref byte a8, - ref byte a9, ref byte a10, ref byte a11, ref byte a12, ref byte a13, ref byte a14, ref byte a15, ref byte a16) => - { - a1 = ToByteSaturate(x.Item1); - a2 = ToByteSaturate(x.Item2); - a3 = ToByteSaturate(x.Item3); - a4 = ToByteSaturate(x.Item4); - a5 = ToByteSaturate(x.Item5); - a6 = ToByteSaturate(x.Item6); - a7 = ToByteSaturate(x.Item7); - a8 = ToByteSaturate(x.Item8); - a9 = ToByteSaturate(y.Item1); - a10 = ToByteSaturate(y.Item2); - a11 = ToByteSaturate(y.Item3); - a12 = ToByteSaturate(y.Item4); - a13 = ToByteSaturate(y.Item5); - a14 = ToByteSaturate(y.Item6); - a15 = ToByteSaturate(y.Item7); - a16 = ToByteSaturate(y.Item8); - - return a1 == z1.Item1 && a2 == z1.Item2 && a3 == z1.Item3 && a4 == z1.Item4 && - a5 == z1.Item5 && a6 == z1.Item6 && a7 == z1.Item7 && a8 == z1.Item8 && - a9 == z2.Item1 && a10 == z2.Item2 && a11 == z2.Item3 && a12 == z2.Item4 && - a13 == z2.Item5 && a14 == z2.Item6 && a15 == z2.Item7 && a16 == z2.Item8; - }; - - if (!shortTable.CheckPackSaturate(checkInt16)) - { - PrintError(shortTable, methodUnderTestName, "CheckPackSaturate", checkInt16); - testResult = Fail; - } - } - } - else - { - Console.WriteLine($"Sse2.IsSupported: {Sse2.IsSupported}, skipped tests of {typeof(Sse2)}.{methodUnderTestName}"); - } - - return testResult; - } - - private static byte ToByteSaturate(short value) - { - return (byte)(value > byte.MaxValue ? byte.MaxValue : value < 0 ? 0 : value); - } - } -} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate_r.csproj deleted file mode 100644 index 18ba828d89..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate_r.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{A11D2E47-7AA7-4D13-9087-39785BB82D7C}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize></Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="PackUnsignedSaturate.cs" /> - <Compile Include="TestTableSse2.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate_ro.csproj deleted file mode 100644 index 382124d1b6..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/PackUnsignedSaturate_ro.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{C8295B8E-35C4-4A29-8BF7-44A1F9525ACC}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize>True</Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="PackUnsignedSaturate.cs" /> - <Compile Include="TestTableSse2.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs index d654dff58a..aacdaa3e6d 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs @@ -138,6 +138,9 @@ namespace JIT.HardwareIntrinsics.X86 ["Or.UInt16"] = OrUInt16, ["Or.UInt32"] = OrUInt32, ["Or.UInt64"] = OrUInt64, + ["PackSignedSaturate.Int16"] = PackSignedSaturateInt16, + ["PackSignedSaturate.SByte"] = PackSignedSaturateSByte, + ["PackUnsignedSaturate.Byte"] = PackUnsignedSaturateByte, ["SetAllVector128.Byte"] = SetAllVector128Byte, ["SetAllVector128.SByte"] = SetAllVector128SByte, ["SetAllVector128.Int16"] = SetAllVector128Int16, @@ -205,6 +208,24 @@ namespace JIT.HardwareIntrinsics.X86 ["SubtractSaturate.Int16"] = SubtractSaturateInt16, ["SubtractSaturate.UInt16"] = SubtractSaturateUInt16, ["SubtractScalar.Double"] = SubtractScalarDouble, + ["UnpackHigh.Double"] = UnpackHighDouble, + ["UnpackHigh.Int64"] = UnpackHighInt64, + ["UnpackHigh.UInt64"] = UnpackHighUInt64, + ["UnpackHigh.Int32"] = UnpackHighInt32, + ["UnpackHigh.UInt32"] = UnpackHighUInt32, + ["UnpackHigh.Int16"] = UnpackHighInt16, + ["UnpackHigh.UInt16"] = UnpackHighUInt16, + ["UnpackHigh.SByte"] = UnpackHighSByte, + ["UnpackHigh.Byte"] = UnpackHighByte, + ["UnpackLow.Double"] = UnpackLowDouble, + ["UnpackLow.Int64"] = UnpackLowInt64, + ["UnpackLow.UInt64"] = UnpackLowUInt64, + ["UnpackLow.Int32"] = UnpackLowInt32, + ["UnpackLow.UInt32"] = UnpackLowUInt32, + ["UnpackLow.Int16"] = UnpackLowInt16, + ["UnpackLow.UInt16"] = UnpackLowUInt16, + ["UnpackLow.SByte"] = UnpackLowSByte, + ["UnpackLow.Byte"] = UnpackLowByte, ["Xor.Double"] = XorDouble, ["Xor.Byte"] = XorByte, ["Xor.Int16"] = XorInt16, diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj index 982745a072..b9101fc579 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj @@ -40,7 +40,7 @@ <Compile Include="AddSaturate.SByte.cs"/> <Compile Include="AddSaturate.Int16.cs"/> <Compile Include="AddSaturate.UInt16.cs"/> - <Compile Include="AddScalar.Double.cs"/> + <Compile Include="AddScalar.Double.cs"/> <Compile Include="And.Double.cs" /> <Compile Include="And.Byte.cs" /> <Compile Include="And.Int16.cs" /> @@ -153,6 +153,9 @@ <Compile Include="Or.UInt16.cs" /> <Compile Include="Or.UInt32.cs" /> <Compile Include="Or.UInt64.cs" /> + <Compile Include="PackSignedSaturate.Int16.cs" /> + <Compile Include="PackSignedSaturate.SByte.cs" /> + <Compile Include="PackUnsignedSaturate.Byte.cs" /> <Compile Include="SetAllVector128.Byte.cs" /> <Compile Include="SetAllVector128.SByte.cs" /> <Compile Include="SetAllVector128.Int16.cs" /> @@ -219,7 +222,25 @@ <Compile Include="SubtractSaturate.SByte.cs"/> <Compile Include="SubtractSaturate.Int16.cs"/> <Compile Include="SubtractSaturate.UInt16.cs"/> - <Compile Include="SubtractScalar.Double.cs" /> + <Compile Include="SubtractScalar.Double.cs" /> + <Compile Include="UnpackHigh.Double.cs" /> + <Compile Include="UnpackHigh.Int64.cs" /> + <Compile Include="UnpackHigh.UInt64.cs" /> + <Compile Include="UnpackHigh.Int32.cs" /> + <Compile Include="UnpackHigh.UInt32.cs" /> + <Compile Include="UnpackHigh.Int16.cs" /> + <Compile Include="UnpackHigh.UInt16.cs" /> + <Compile Include="UnpackHigh.SByte.cs" /> + <Compile Include="UnpackHigh.Byte.cs" /> + <Compile Include="UnpackLow.Double.cs" /> + <Compile Include="UnpackLow.Int64.cs" /> + <Compile Include="UnpackLow.UInt64.cs" /> + <Compile Include="UnpackLow.Int32.cs" /> + <Compile Include="UnpackLow.UInt32.cs" /> + <Compile Include="UnpackLow.Int16.cs" /> + <Compile Include="UnpackLow.UInt16.cs" /> + <Compile Include="UnpackLow.SByte.cs" /> + <Compile Include="UnpackLow.Byte.cs" /> <Compile Include="Xor.Double.cs" /> <Compile Include="Xor.Byte.cs" /> <Compile Include="Xor.Int16.cs" /> @@ -231,7 +252,7 @@ <Compile Include="Xor.UInt64.cs" /> <Compile Include="Program.Sse2.cs" /> <Compile Include="..\Shared\Program.cs" /> - <Compile Include="..\Shared\BooleanCmpOpTest_DataTable.cs" /> + <Compile Include="..\Shared\BooleanCmpOpTest_DataTable.cs" /> <Compile Include="..\Shared\SimpleBinOpTest_DataTable.cs" /> <Compile Include="..\Shared\SimpleUnOpTest_DataTable.cs" /> <Compile Include="..\Shared\ScalarSimdUnOpTest_DataTable.cs" /> diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj index 0aef213b1d..563bc43c5e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj @@ -40,7 +40,7 @@ <Compile Include="AddSaturate.Int16.cs"/> <Compile Include="AddSaturate.SByte.cs"/> <Compile Include="AddSaturate.UInt16.cs"/> - <Compile Include="AddScalar.Double.cs"/> + <Compile Include="AddScalar.Double.cs"/> <Compile Include="And.Byte.cs" /> <Compile Include="And.Double.cs" /> <Compile Include="And.Int16.cs" /> @@ -60,7 +60,7 @@ <Compile Include="AndNot.UInt32.cs" /> <Compile Include="AndNot.UInt64.cs" /> <Compile Include="Average.Byte.cs"/> - <Compile Include="Average.UInt16.cs"/> + <Compile Include="Average.UInt16.cs"/> <Compile Include="CompareEqual.Byte.cs" /> <Compile Include="CompareEqual.Double.cs" /> <Compile Include="CompareEqual.Int16.cs" /> @@ -125,7 +125,7 @@ <Compile Include="ConvertToVector128Int32WithTruncation.Vector128Double.cs" /> <Compile Include="ConvertToVector128Int32WithTruncation.Vector128Single.cs" /> <Compile Include="ConvertToVector128Single.Vector128Double.cs" /> - <Compile Include="ConvertToVector128Single.Vector128Int32.cs" /> + <Compile Include="ConvertToVector128Single.Vector128Int32.cs" /> <Compile Include="Divide.Double.cs" /> <Compile Include="DivideScalar.Double.cs" /> <Compile Include="Extract.UInt16.1.cs" /> @@ -153,9 +153,12 @@ <Compile Include="Or.UInt16.cs" /> <Compile Include="Or.UInt32.cs" /> <Compile Include="Or.UInt64.cs" /> + <Compile Include="PackSignedSaturate.Int16.cs" /> + <Compile Include="PackSignedSaturate.SByte.cs" /> + <Compile Include="PackUnsignedSaturate.Byte.cs" /> <Compile Include="Program.Sse2.cs" /> <Compile Include="SetAllVector128.Byte.cs" /> - <Compile Include="SetAllVector128.Double.cs" /> + <Compile Include="SetAllVector128.Double.cs" /> <Compile Include="SetAllVector128.Int16.cs" /> <Compile Include="SetAllVector128.Int32.cs" /> <Compile Include="SetAllVector128.Int64.cs" /> @@ -220,7 +223,25 @@ <Compile Include="SubtractSaturate.Int16.cs"/> <Compile Include="SubtractSaturate.SByte.cs"/> <Compile Include="SubtractSaturate.UInt16.cs"/> - <Compile Include="SubtractScalar.Double.cs" /> + <Compile Include="SubtractScalar.Double.cs" /> + <Compile Include="UnpackHigh.Double.cs" /> + <Compile Include="UnpackHigh.Int64.cs" /> + <Compile Include="UnpackHigh.UInt64.cs" /> + <Compile Include="UnpackHigh.Int32.cs" /> + <Compile Include="UnpackHigh.UInt32.cs" /> + <Compile Include="UnpackHigh.Int16.cs" /> + <Compile Include="UnpackHigh.UInt16.cs" /> + <Compile Include="UnpackHigh.SByte.cs" /> + <Compile Include="UnpackHigh.Byte.cs" /> + <Compile Include="UnpackLow.Double.cs" /> + <Compile Include="UnpackLow.Int64.cs" /> + <Compile Include="UnpackLow.UInt64.cs" /> + <Compile Include="UnpackLow.Int32.cs" /> + <Compile Include="UnpackLow.UInt32.cs" /> + <Compile Include="UnpackLow.Int16.cs" /> + <Compile Include="UnpackLow.UInt16.cs" /> + <Compile Include="UnpackLow.SByte.cs" /> + <Compile Include="UnpackLow.Byte.cs" /> <Compile Include="Xor.Byte.cs" /> <Compile Include="Xor.Double.cs" /> <Compile Include="Xor.Int16.cs" /> diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Byte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Byte.cs new file mode 100644 index 0000000000..c2b1de090c --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Byte.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighByte() + { + var test = new SimpleBinaryOpTest__UnpackHighByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighByte + { + private struct TestStruct + { + public Vector128<Byte> _fld1; + public Vector128<Byte> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighByte testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector128<Byte> _clsVar1; + private static Vector128<Byte> _clsVar2; + + private Vector128<Byte> _fld1; + private Vector128<Byte> _fld2; + + private SimpleBinaryOpTest__DataTable<Byte, Byte, Byte> _dataTable; + + static SimpleBinaryOpTest__UnpackHighByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + } + + public SimpleBinaryOpTest__UnpackHighByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Byte, Byte, Byte>(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Byte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Byte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighByte(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Byte> left, Vector128<Byte> right, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[8]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<Byte>(Vector128<Byte>, Vector128<Byte>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Double.cs new file mode 100644 index 0000000000..04babb54ef --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Double.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighDouble() + { + var test = new SimpleBinaryOpTest__UnpackHighDouble(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighDouble + { + private struct TestStruct + { + public Vector128<Double> _fld1; + public Vector128<Double> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighDouble testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double); + + private static Double[] _data1 = new Double[Op1ElementCount]; + private static Double[] _data2 = new Double[Op2ElementCount]; + + private static Vector128<Double> _clsVar1; + private static Vector128<Double> _clsVar2; + + private Vector128<Double> _fld1; + private Vector128<Double> _fld2; + + private SimpleBinaryOpTest__DataTable<Double, Double, Double> _dataTable; + + static SimpleBinaryOpTest__UnpackHighDouble() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + } + + public SimpleBinaryOpTest__UnpackHighDouble() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Double, Double, Double>(_data1, _data2, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighDouble(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Double> left, Vector128<Double> right, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] inArray2 = new Double[Op2ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] inArray2 = new Double[Op2ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Double>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Double>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "") + { + if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[1])) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2+1]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2 + 1])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<Double>(Vector128<Double>, Vector128<Double>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int16.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int16.cs new file mode 100644 index 0000000000..ab6dc392c8 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int16.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighInt16() + { + var test = new SimpleBinaryOpTest__UnpackHighInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighInt16 + { + private struct TestStruct + { + public Vector128<Int16> _fld1; + public Vector128<Int16> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighInt16 testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128<Int16> _clsVar1; + private static Vector128<Int16> _clsVar2; + + private Vector128<Int16> _fld1; + private Vector128<Int16> _fld2; + + private SimpleBinaryOpTest__DataTable<Int16, Int16, Int16> _dataTable; + + static SimpleBinaryOpTest__UnpackHighInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + } + + public SimpleBinaryOpTest__UnpackHighInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Int16, Int16, Int16>(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighInt16(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> left, Vector128<Int16> right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[4]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<Int16>(Vector128<Int16>, Vector128<Int16>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int32.cs new file mode 100644 index 0000000000..4d6994b730 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int32.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighInt32() + { + var test = new SimpleBinaryOpTest__UnpackHighInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighInt32 + { + private struct TestStruct + { + public Vector128<Int32> _fld1; + public Vector128<Int32> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighInt32 testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128<Int32> _clsVar1; + private static Vector128<Int32> _clsVar2; + + private Vector128<Int32> _fld1; + private Vector128<Int32> _fld2; + + private SimpleBinaryOpTest__DataTable<Int32, Int32, Int32> _dataTable; + + static SimpleBinaryOpTest__UnpackHighInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + } + + public SimpleBinaryOpTest__UnpackHighInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Int32, Int32, Int32>(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighInt32(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int32> left, Vector128<Int32> right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[2]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<Int32>(Vector128<Int32>, Vector128<Int32>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int64.cs new file mode 100644 index 0000000000..8c6cfca34b --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.Int64.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighInt64() + { + var test = new SimpleBinaryOpTest__UnpackHighInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighInt64 + { + private struct TestStruct + { + public Vector128<Int64> _fld1; + public Vector128<Int64> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighInt64 testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128<Int64> _clsVar1; + private static Vector128<Int64> _clsVar2; + + private Vector128<Int64> _fld1; + private Vector128<Int64> _fld2; + + private SimpleBinaryOpTest__DataTable<Int64, Int64, Int64> _dataTable; + + static SimpleBinaryOpTest__UnpackHighInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + } + + public SimpleBinaryOpTest__UnpackHighInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Int64, Int64, Int64>(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighInt64(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int64> left, Vector128<Int64> right, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[1] || result[1] != right[1]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<Int64>(Vector128<Int64>, Vector128<Int64>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.SByte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.SByte.cs new file mode 100644 index 0000000000..098acf728c --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.SByte.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighSByte() + { + var test = new SimpleBinaryOpTest__UnpackHighSByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighSByte + { + private struct TestStruct + { + public Vector128<SByte> _fld1; + public Vector128<SByte> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighSByte testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128<SByte> _clsVar1; + private static Vector128<SByte> _clsVar2; + + private Vector128<SByte> _fld1; + private Vector128<SByte> _fld2; + + private SimpleBinaryOpTest__DataTable<SByte, SByte, SByte> _dataTable; + + static SimpleBinaryOpTest__UnpackHighSByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + } + + public SimpleBinaryOpTest__UnpackHighSByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new SimpleBinaryOpTest__DataTable<SByte, SByte, SByte>(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighSByte(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<SByte> left, Vector128<SByte> right, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[8]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<SByte>(Vector128<SByte>, Vector128<SByte>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt16.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt16.cs new file mode 100644 index 0000000000..cc2939ab02 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt16.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighUInt16() + { + var test = new SimpleBinaryOpTest__UnpackHighUInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighUInt16 + { + private struct TestStruct + { + public Vector128<UInt16> _fld1; + public Vector128<UInt16> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighUInt16 testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector128<UInt16> _clsVar1; + private static Vector128<UInt16> _clsVar2; + + private Vector128<UInt16> _fld1; + private Vector128<UInt16> _fld2; + + private SimpleBinaryOpTest__DataTable<UInt16, UInt16, UInt16> _dataTable; + + static SimpleBinaryOpTest__UnpackHighUInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + } + + public SimpleBinaryOpTest__UnpackHighUInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new SimpleBinaryOpTest__DataTable<UInt16, UInt16, UInt16>(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighUInt16(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt16> left, Vector128<UInt16> right, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[4]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<UInt16>(Vector128<UInt16>, Vector128<UInt16>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt32.cs new file mode 100644 index 0000000000..7ca7a2e9d1 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt32.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighUInt32() + { + var test = new SimpleBinaryOpTest__UnpackHighUInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighUInt32 + { + private struct TestStruct + { + public Vector128<UInt32> _fld1; + public Vector128<UInt32> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighUInt32 testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector128<UInt32> _clsVar1; + private static Vector128<UInt32> _clsVar2; + + private Vector128<UInt32> _fld1; + private Vector128<UInt32> _fld2; + + private SimpleBinaryOpTest__DataTable<UInt32, UInt32, UInt32> _dataTable; + + static SimpleBinaryOpTest__UnpackHighUInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + } + + public SimpleBinaryOpTest__UnpackHighUInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new SimpleBinaryOpTest__DataTable<UInt32, UInt32, UInt32>(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighUInt32(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt32> left, Vector128<UInt32> right, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[2]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<UInt32>(Vector128<UInt32>, Vector128<UInt32>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt64.cs new file mode 100644 index 0000000000..83e0d9236e --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.UInt64.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackHighUInt64() + { + var test = new SimpleBinaryOpTest__UnpackHighUInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackHighUInt64 + { + private struct TestStruct + { + public Vector128<UInt64> _fld1; + public Vector128<UInt64> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackHighUInt64 testClass) + { + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector128<UInt64> _clsVar1; + private static Vector128<UInt64> _clsVar2; + + private Vector128<UInt64> _fld1; + private Vector128<UInt64> _fld2; + + private SimpleBinaryOpTest__DataTable<UInt64, UInt64, UInt64> _dataTable; + + static SimpleBinaryOpTest__UnpackHighUInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + } + + public SimpleBinaryOpTest__UnpackHighUInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new SimpleBinaryOpTest__DataTable<UInt64, UInt64, UInt64>(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackHigh( + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackHigh( + Sse2.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackHigh( + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackHigh( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackHigh(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackHighUInt64(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackHigh(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackHigh(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt64> left, Vector128<UInt64> right, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[1] || result[1] != right[1]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackHigh)}<UInt64>(Vector128<UInt64>, Vector128<UInt64>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.cs deleted file mode 100644 index 768299fa23..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh.cs +++ /dev/null @@ -1,302 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace IntelHardwareIntrinsicTest -{ - internal static partial class Program - { - const int Pass = 100; - const int Fail = 0; - - static unsafe int Main(string[] args) - { - int testResult = Pass; - int testsCount = 21; - string methodUnderTestName = nameof(Sse2.UnpackHigh); - - if (Sse2.IsSupported) - { - using (var doubleTable = TestTableSse2<double, double>.Create(testsCount, 1.0)) - using (var longTable = TestTableSse2<long, long>.Create(testsCount, 1.0)) - using (var ulongTable = TestTableSse2<ulong, ulong>.Create(testsCount, 1.0)) - using (var intTable = TestTableSse2<int, int>.Create(testsCount, 1.0)) - using (var uintTable = TestTableSse2<uint, uint>.Create(testsCount, 1.0)) - using (var shortTable = TestTableSse2<short, short>.Create(testsCount, 1.0)) - using (var ushortTable = TestTableSse2<ushort, ushort>.Create(testsCount, 1.0)) - using (var sbyteTable = TestTableSse2<sbyte, sbyte>.Create(testsCount, 1.0)) - using (var byteTable = TestTableSse2<byte, byte>.Create(testsCount, 1.0)) - { - for (int i = 0; i < testsCount; i++) - { - (Vector128<double>, Vector128<double>) value = doubleTable[i]; - Vector128<double> result = Sse2.UnpackHigh(value.Item1, value.Item2); - doubleTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<long>, Vector128<long>) value = longTable[i]; - Vector128<long> result = Sse2.UnpackHigh(value.Item1, value.Item2); - longTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<ulong>, Vector128<ulong>) value = ulongTable[i]; - Vector128<ulong> result = Sse2.UnpackHigh(value.Item1, value.Item2); - ulongTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<int>, Vector128<int>) value = intTable[i]; - Vector128<int> result = Sse2.UnpackHigh(value.Item1, value.Item2); - intTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<uint>, Vector128<uint>) value = uintTable[i]; - Vector128<uint> result = Sse2.UnpackHigh(value.Item1, value.Item2); - uintTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<short>, Vector128<short>) value = shortTable[i]; - Vector128<short> result = Sse2.UnpackHigh(value.Item1, value.Item2); - shortTable.SetOutArray(result); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<ushort>, Vector128<ushort>) value = ushortTable[i]; - Vector128<ushort> result = Sse2.UnpackHigh(value.Item1, value.Item2); - ushortTable.SetOutArray(result); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<sbyte>, Vector128<sbyte>) value = sbyteTable[i]; - Vector128<sbyte> result = Sse2.UnpackHigh(value.Item1, value.Item2); - sbyteTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<byte>, Vector128<byte>) value = byteTable[i]; - Vector128<byte> result = Sse2.UnpackHigh(value.Item1, value.Item2); - byteTable.SetOutArray(result, i); - } - - CheckMethodFive<double, double> checkDouble = (double x1, double x2, double y1, double y2, double z1, double z2, ref double a1, ref double a2) => - { - return (a1 = x2) == z1 && (a2 = y2) == z2; - }; - - if (!doubleTable.CheckUnpackHiDouble(checkDouble)) - { - PrintError(doubleTable, methodUnderTestName, "(double x, double y, double z, ref double a) => (a = BitwiseXor(x, y)) == z", checkDouble); - testResult = Fail; - } - - CheckMethodFive<long, long> checkLong = (long x1, long x2, long y1, long y2, long z1, long z2, ref long a1, ref long a2) => - { - return (a1 = x2) == z1 && (a2 = y2) == z2; - }; - - if (!longTable.CheckUnpackHiDouble(checkLong)) - { - PrintError(longTable, methodUnderTestName, "(long x, long y, long z, ref long a) => (a = x ^ y) == z", checkLong); - testResult = Fail; - } - - CheckMethodFive<ulong, ulong> checkUlong = (ulong x1, ulong x2, ulong y1, ulong y2, ulong z1, ulong z2, ref ulong a1, ref ulong a2) => - { - return (a1 = x2) == z1 && (a2 = y2) == z2; - }; - - if (!longTable.CheckUnpackHiDouble(checkLong)) - { - PrintError(ulongTable, methodUnderTestName, "(ulong x1, ulong x2, ulong y1, ulong y2, ulong z1, ulong z2, ref ulong a1, ref ulong a2) => (a1 = x2) == z1 && (a2 = y2) == z2", checkUlong); - testResult = Fail; - } - - CheckMethodFourTFourU<int, int> checkInt32 = - (ValueTuple<int, int, int, int> x, ValueTuple<int, int, int, int> y, - ValueTuple<int, int, int, int> z, - ref int a1, ref int a2, ref int a3, ref int a4) => - { - a1 = x.Item3; - a2 = y.Item3; - a3 = x.Item4; - a4 = y.Item4; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4; - }; - - if (!intTable.CheckUnpack(checkInt32)) - { - PrintError(intTable, methodUnderTestName, "(int x, int y, int z, ref int a) => (a = x ^ y) == z", checkInt32); - testResult = Fail; - } - - CheckMethodFourTFourU<uint, uint> checkUInt32 = - (ValueTuple<uint, uint, uint, uint> x, ValueTuple<uint, uint, uint, uint> y, - ValueTuple<uint, uint, uint, uint> z, - ref uint a1, ref uint a2, ref uint a3, ref uint a4) => - { - a1 = x.Item3; - a2 = y.Item3; - a3 = x.Item4; - a4 = y.Item4; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4; - }; - - if (!uintTable.CheckUnpack(checkUInt32)) - { - PrintError(uintTable, methodUnderTestName, "(uint x, uint y, uint z, ref uint a) => (a = x ^ y) == z", checkUInt32); - testResult = Fail; - } - - CheckMethodEightOfTEightOfU<short, short> checkInt16 = - (ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> x, - ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> y, - ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> z, - ref short a1, ref short a2, ref short a3, ref short a4, ref short a5, ref short a6, ref short a7, ref short a8) => - { - a1 = x.Item5; - a2 = y.Item5; - a3 = x.Item6; - a4 = y.Item6; - a5 = x.Item7; - a6 = y.Item7; - a7 = x.Item8; - a8 = y.Item8; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4 && - a5 == z.Item5 && a6 == z.Item6 && a7 == z.Item7 && a8 == z.Item8; - }; - - if (!shortTable.CheckUnpack(checkInt16)) - { - PrintError(shortTable, methodUnderTestName, "CheckUnpack(CheckMethodEightOfTEightOfU<short, short>)", checkInt16); - testResult = Fail; - } - - CheckMethodEightOfTEightOfU<ushort, ushort> checkUInt16 = - (ValueTuple<ushort, ushort, ushort, ushort, ushort, ushort, ushort, ValueTuple<ushort>> x, - ValueTuple<ushort, ushort, ushort, ushort, ushort, ushort, ushort, ValueTuple<ushort>> y, - ValueTuple<ushort, ushort, ushort, ushort, ushort, ushort, ushort, ValueTuple<ushort>> z, - ref ushort a1, ref ushort a2, ref ushort a3, ref ushort a4, ref ushort a5, ref ushort a6, ref ushort a7, ref ushort a8) => - { - a1 = x.Item5; - a2 = y.Item5; - a3 = x.Item6; - a4 = y.Item6; - a5 = x.Item7; - a6 = y.Item7; - a7 = x.Item8; - a8 = y.Item8; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4 && - a5 == z.Item5 && a6 == z.Item6 && a7 == z.Item7 && a8 == z.Item8; - }; - - if (!ushortTable.CheckUnpack(checkUInt16)) - { - PrintError(ushortTable, methodUnderTestName, "(ushort x, ushort y, ushort z, ref ushort a) => (a = (ushort)(x ^ y)) == z", checkUInt16); - testResult = Fail; - } - - CheckMethodSixteenOfAll<sbyte, sbyte> checkSByte = - (ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> x1, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> x, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> y1, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> y, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> z1, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> z2, - ref sbyte a1, ref sbyte a2, ref sbyte a3, ref sbyte a4, ref sbyte a5, ref sbyte a6, ref sbyte a7, ref sbyte a8, - ref sbyte a9, ref sbyte a10, ref sbyte a11, ref sbyte a12, ref sbyte a13, ref sbyte a14, ref sbyte a15, ref sbyte a16) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - a5 = x.Item3; - a6 = y.Item3; - a7 = x.Item4; - a8 = y.Item4; - a9 = x.Item5; - a10 = y.Item5; - a11 = x.Item6; - a12 = y.Item6; - a13 = x.Item7; - a14 = y.Item7; - a15 = x.Item8; - a16 = y.Item8; - - return a1 == z1.Item1 && a2 == z1.Item2 && a3 == z1.Item3 && a4 == z1.Item4 && - a5 == z1.Item5 && a6 == z1.Item6 && a7 == z1.Item7 && a8 == z1.Item8 && - a9 == z2.Item1 && a10 == z2.Item2 && a11 == z2.Item3 && a12 == z2.Item4 && - a13 == z2.Item5 && a14 == z2.Item6 && a15 == z2.Item7 && a16 == z2.Item8; - }; - - if (!sbyteTable.CheckUnpack(checkSByte)) - { - PrintError(sbyteTable, methodUnderTestName, "(sbyte x, sbyte y, sbyte z, ref sbyte a) => (a = (sbyte)(x ^ y)) == z", checkSByte); - testResult = Fail; - } - - CheckMethodSixteenOfAll<byte, byte> checkByte = - (ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> x1, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> x, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> y1, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> y, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> z1, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> z2, - ref byte a1, ref byte a2, ref byte a3, ref byte a4, ref byte a5, ref byte a6, ref byte a7, ref byte a8, - ref byte a9, ref byte a10, ref byte a11, ref byte a12, ref byte a13, ref byte a14, ref byte a15, ref byte a16) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - a5 = x.Item3; - a6 = y.Item3; - a7 = x.Item4; - a8 = y.Item4; - a9 = x.Item5; - a10 = y.Item5; - a11 = x.Item6; - a12 = y.Item6; - a13 = x.Item7; - a14 = y.Item7; - a15 = x.Item8; - a16 = y.Item8; - - return a1 == z1.Item1 && a2 == z1.Item2 && a3 == z1.Item3 && a4 == z1.Item4 && - a5 == z1.Item5 && a6 == z1.Item6 && a7 == z1.Item7 && a8 == z1.Item8 && - a9 == z2.Item1 && a10 == z2.Item2 && a11 == z2.Item3 && a12 == z2.Item4 && - a13 == z2.Item5 && a14 == z2.Item6 && a15 == z2.Item7 && a16 == z2.Item8; - }; - - if (!byteTable.CheckUnpack(checkByte)) - { - PrintError(byteTable, methodUnderTestName, "(byte x, byte y, byte z, ref byte a) => (a = (byte)(x ^ y)) == z", checkByte); - testResult = Fail; - } - } - } - else - { - Console.WriteLine($"Sse2.IsSupported: {Sse2.IsSupported}, skipped tests of {typeof(Sse2)}.{methodUnderTestName}"); - } - - return testResult; - } - } -} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh_r.csproj deleted file mode 100644 index 25dd8fd9cf..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh_r.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{1D430B7E-0A5B-4D0F-8F6F-7138D12FD57E}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize></Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="TestTableSse2.cs" /> - <Compile Include="UnpackHigh.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh_ro.csproj deleted file mode 100644 index c5ebd44bb6..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackHigh_ro.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{D72FD8F6-CCE9-4026-ABA8-67862FE5ECB8}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize>True</Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="TestTableSse2.cs" /> - <Compile Include="UnpackHigh.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Byte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Byte.cs new file mode 100644 index 0000000000..4815b01a8a --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Byte.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowByte() + { + var test = new SimpleBinaryOpTest__UnpackLowByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowByte + { + private struct TestStruct + { + public Vector128<Byte> _fld1; + public Vector128<Byte> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowByte testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector128<Byte> _clsVar1; + private static Vector128<Byte> _clsVar2; + + private Vector128<Byte> _fld1; + private Vector128<Byte> _fld2; + + private SimpleBinaryOpTest__DataTable<Byte, Byte, Byte> _dataTable; + + static SimpleBinaryOpTest__UnpackLowByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + } + + public SimpleBinaryOpTest__UnpackLowByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Byte, Byte, Byte>(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Byte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Byte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowByte(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Byte> left, Vector128<Byte> right, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<Byte>(Vector128<Byte>, Vector128<Byte>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Double.cs new file mode 100644 index 0000000000..82879249cd --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Double.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowDouble() + { + var test = new SimpleBinaryOpTest__UnpackLowDouble(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowDouble + { + private struct TestStruct + { + public Vector128<Double> _fld1; + public Vector128<Double> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowDouble testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double); + + private static Double[] _data1 = new Double[Op1ElementCount]; + private static Double[] _data2 = new Double[Op2ElementCount]; + + private static Vector128<Double> _clsVar1; + private static Vector128<Double> _clsVar2; + + private Vector128<Double> _fld1; + private Vector128<Double> _fld2; + + private SimpleBinaryOpTest__DataTable<Double, Double, Double> _dataTable; + + static SimpleBinaryOpTest__UnpackLowDouble() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + } + + public SimpleBinaryOpTest__UnpackLowDouble() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Double, Double, Double>(_data1, _data2, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowDouble(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Double> left, Vector128<Double> right, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] inArray2 = new Double[Op2ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] inArray2 = new Double[Op2ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Double>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Double>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "") + { + if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[0])) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<Double>(Vector128<Double>, Vector128<Double>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int16.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int16.cs new file mode 100644 index 0000000000..97b939bcb9 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int16.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowInt16() + { + var test = new SimpleBinaryOpTest__UnpackLowInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowInt16 + { + private struct TestStruct + { + public Vector128<Int16> _fld1; + public Vector128<Int16> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowInt16 testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128<Int16> _clsVar1; + private static Vector128<Int16> _clsVar2; + + private Vector128<Int16> _fld1; + private Vector128<Int16> _fld2; + + private SimpleBinaryOpTest__DataTable<Int16, Int16, Int16> _dataTable; + + static SimpleBinaryOpTest__UnpackLowInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + } + + public SimpleBinaryOpTest__UnpackLowInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Int16, Int16, Int16>(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowInt16(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int16> left, Vector128<Int16> right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<Int16>(Vector128<Int16>, Vector128<Int16>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int32.cs new file mode 100644 index 0000000000..f31b3418ce --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int32.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowInt32() + { + var test = new SimpleBinaryOpTest__UnpackLowInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowInt32 + { + private struct TestStruct + { + public Vector128<Int32> _fld1; + public Vector128<Int32> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowInt32 testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128<Int32> _clsVar1; + private static Vector128<Int32> _clsVar2; + + private Vector128<Int32> _fld1; + private Vector128<Int32> _fld2; + + private SimpleBinaryOpTest__DataTable<Int32, Int32, Int32> _dataTable; + + static SimpleBinaryOpTest__UnpackLowInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + } + + public SimpleBinaryOpTest__UnpackLowInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Int32, Int32, Int32>(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowInt32(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int32> left, Vector128<Int32> right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<Int32>(Vector128<Int32>, Vector128<Int32>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int64.cs new file mode 100644 index 0000000000..8cd4d81be1 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.Int64.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowInt64() + { + var test = new SimpleBinaryOpTest__UnpackLowInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowInt64 + { + private struct TestStruct + { + public Vector128<Int64> _fld1; + public Vector128<Int64> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowInt64 testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128<Int64> _clsVar1; + private static Vector128<Int64> _clsVar2; + + private Vector128<Int64> _fld1; + private Vector128<Int64> _fld2; + + private SimpleBinaryOpTest__DataTable<Int64, Int64, Int64> _dataTable; + + static SimpleBinaryOpTest__UnpackLowInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + } + + public SimpleBinaryOpTest__UnpackLowInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new SimpleBinaryOpTest__DataTable<Int64, Int64, Int64>(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowInt64(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<Int64> left, Vector128<Int64> right, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0] || result[1] != right[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<Int64>(Vector128<Int64>, Vector128<Int64>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.SByte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.SByte.cs new file mode 100644 index 0000000000..77a11e24bf --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.SByte.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowSByte() + { + var test = new SimpleBinaryOpTest__UnpackLowSByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowSByte + { + private struct TestStruct + { + public Vector128<SByte> _fld1; + public Vector128<SByte> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowSByte testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128<SByte> _clsVar1; + private static Vector128<SByte> _clsVar2; + + private Vector128<SByte> _fld1; + private Vector128<SByte> _fld2; + + private SimpleBinaryOpTest__DataTable<SByte, SByte, SByte> _dataTable; + + static SimpleBinaryOpTest__UnpackLowSByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + } + + public SimpleBinaryOpTest__UnpackLowSByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new SimpleBinaryOpTest__DataTable<SByte, SByte, SByte>(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowSByte(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<SByte> left, Vector128<SByte> right, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<SByte>(Vector128<SByte>, Vector128<SByte>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt16.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt16.cs new file mode 100644 index 0000000000..0cbe160003 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt16.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowUInt16() + { + var test = new SimpleBinaryOpTest__UnpackLowUInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowUInt16 + { + private struct TestStruct + { + public Vector128<UInt16> _fld1; + public Vector128<UInt16> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowUInt16 testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector128<UInt16> _clsVar1; + private static Vector128<UInt16> _clsVar2; + + private Vector128<UInt16> _fld1; + private Vector128<UInt16> _fld2; + + private SimpleBinaryOpTest__DataTable<UInt16, UInt16, UInt16> _dataTable; + + static SimpleBinaryOpTest__UnpackLowUInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + } + + public SimpleBinaryOpTest__UnpackLowUInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new SimpleBinaryOpTest__DataTable<UInt16, UInt16, UInt16>(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowUInt16(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt16> left, Vector128<UInt16> right, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<UInt16>(Vector128<UInt16>, Vector128<UInt16>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt32.cs new file mode 100644 index 0000000000..420afbb740 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt32.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowUInt32() + { + var test = new SimpleBinaryOpTest__UnpackLowUInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowUInt32 + { + private struct TestStruct + { + public Vector128<UInt32> _fld1; + public Vector128<UInt32> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowUInt32 testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector128<UInt32> _clsVar1; + private static Vector128<UInt32> _clsVar2; + + private Vector128<UInt32> _fld1; + private Vector128<UInt32> _fld2; + + private SimpleBinaryOpTest__DataTable<UInt32, UInt32, UInt32> _dataTable; + + static SimpleBinaryOpTest__UnpackLowUInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + } + + public SimpleBinaryOpTest__UnpackLowUInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new SimpleBinaryOpTest__DataTable<UInt32, UInt32, UInt32>(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowUInt32(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt32> left, Vector128<UInt32> right, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<UInt32>(Vector128<UInt32>, Vector128<UInt32>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt64.cs new file mode 100644 index 0000000000..756c03edf4 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.UInt64.cs @@ -0,0 +1,403 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void UnpackLowUInt64() + { + var test = new SimpleBinaryOpTest__UnpackLowUInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + + // Validates calling via reflection works, using LoadAligned + test.RunReflectionScenario_LoadAligned(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (Sse2.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + + // Validates passing a local works, using LoadAligned + test.RunLclVarScenario_LoadAligned(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__UnpackLowUInt64 + { + private struct TestStruct + { + public Vector128<UInt64> _fld1; + public Vector128<UInt64> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__UnpackLowUInt64 testClass) + { + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector128<UInt64> _clsVar1; + private static Vector128<UInt64> _clsVar2; + + private Vector128<UInt64> _fld1; + private Vector128<UInt64> _fld2; + + private SimpleBinaryOpTest__DataTable<UInt64, UInt64, UInt64> _dataTable; + + static SimpleBinaryOpTest__UnpackLowUInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + } + + public SimpleBinaryOpTest__UnpackLowUInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new SimpleBinaryOpTest__DataTable<UInt64, UInt64, UInt64>(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Sse2.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Sse2.UnpackLow( + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Sse2.UnpackLow( + Sse2.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = Sse2.UnpackLow( + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) }) + .Invoke(null, new object[] { + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr), + Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) }) + .Invoke(null, new object[] { + Sse2.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); + + var result = typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) }) + .Invoke(null, new object[] { + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray1Ptr)), + Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Sse2.UnpackLow( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var left = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr); + var right = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var left = Sse2.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned)); + + var left = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray1Ptr)); + var right = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = Sse2.UnpackLow(left, right); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__UnpackLowUInt64(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Sse2.UnpackLow(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Sse2.UnpackLow(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector128<UInt64> left, Vector128<UInt64> right, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), left); + Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0] || result[1] != right[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i % 2 == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.UnpackLow)}<UInt64>(Vector128<UInt64>, Vector128<UInt64>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.cs deleted file mode 100644 index 91a716c2fe..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow.cs +++ /dev/null @@ -1,302 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace IntelHardwareIntrinsicTest -{ - internal static partial class Program - { - const int Pass = 100; - const int Fail = 0; - - static unsafe int Main(string[] args) - { - int testResult = Pass; - int testsCount = 21; - string methodUnderTestName = nameof(Sse2.UnpackLow); - - if (Sse2.IsSupported) - { - using (var doubleTable = TestTableSse2<double, double>.Create(testsCount, 1.0)) - using (var longTable = TestTableSse2<long, long>.Create(testsCount, 1.0)) - using (var ulongTable = TestTableSse2<ulong, ulong>.Create(testsCount, 1.0)) - using (var intTable = TestTableSse2<int, int>.Create(testsCount, 1.0)) - using (var uintTable = TestTableSse2<uint, uint>.Create(testsCount, 1.0)) - using (var shortTable = TestTableSse2<short, short>.Create(testsCount, 1.0)) - using (var ushortTable = TestTableSse2<ushort, ushort>.Create(testsCount, 1.0)) - using (var sbyteTable = TestTableSse2<sbyte, sbyte>.Create(testsCount, 1.0)) - using (var byteTable = TestTableSse2<byte, byte>.Create(testsCount, 1.0)) - { - for (int i = 0; i < testsCount; i++) - { - (Vector128<double>, Vector128<double>) value = doubleTable[i]; - Vector128<double> result = Sse2.UnpackLow(value.Item1, value.Item2); - doubleTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<long>, Vector128<long>) value = longTable[i]; - Vector128<long> result = Sse2.UnpackLow(value.Item1, value.Item2); - longTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<ulong>, Vector128<ulong>) value = ulongTable[i]; - Vector128<ulong> result = Sse2.UnpackLow(value.Item1, value.Item2); - ulongTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<int>, Vector128<int>) value = intTable[i]; - Vector128<int> result = Sse2.UnpackLow(value.Item1, value.Item2); - intTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<uint>, Vector128<uint>) value = uintTable[i]; - Vector128<uint> result = Sse2.UnpackLow(value.Item1, value.Item2); - uintTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<short>, Vector128<short>) value = shortTable[i]; - Vector128<short> result = Sse2.UnpackLow(value.Item1, value.Item2); - shortTable.SetOutArray(result); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<ushort>, Vector128<ushort>) value = ushortTable[i]; - Vector128<ushort> result = Sse2.UnpackLow(value.Item1, value.Item2); - ushortTable.SetOutArray(result); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<sbyte>, Vector128<sbyte>) value = sbyteTable[i]; - Vector128<sbyte> result = Sse2.UnpackLow(value.Item1, value.Item2); - sbyteTable.SetOutArray(result, i); - } - - for (int i = 0; i < testsCount; i++) - { - (Vector128<byte>, Vector128<byte>) value = byteTable[i]; - Vector128<byte> result = Sse2.UnpackLow(value.Item1, value.Item2); - byteTable.SetOutArray(result, i); - } - - CheckMethodFive<double, double> checkDouble = (double x1, double x2, double y1, double y2, double z1, double z2, ref double a1, ref double a2) => - { - return (a1 = x1) == z1 && (a2 = y1) == z2; - }; - - if (!doubleTable.CheckUnpackHiDouble(checkDouble)) - { - PrintError(doubleTable, methodUnderTestName, "(double x, double y, double z, ref double a) => (a = BitwiseXor(x, y)) == z", checkDouble); - testResult = Fail; - } - - CheckMethodFive<long, long> checkLong = (long x1, long x2, long y1, long y2, long z1, long z2, ref long a1, ref long a2) => - { - return (a1 = x1) == z1 && (a2 = y1) == z2; - }; - - if (!longTable.CheckUnpackHiDouble(checkLong)) - { - PrintError(longTable, methodUnderTestName, "(long x, long y, long z, ref long a) => (a = x ^ y) == z", checkLong); - testResult = Fail; - } - - CheckMethodFive<ulong, ulong> checkUlong = (ulong x1, ulong x2, ulong y1, ulong y2, ulong z1, ulong z2, ref ulong a1, ref ulong a2) => - { - return (a1 = x1) == z1 && (a2 = y1) == z2; - }; - - if (!longTable.CheckUnpackHiDouble(checkLong)) - { - PrintError(ulongTable, methodUnderTestName, "(ulong x1, ulong x2, ulong y1, ulong y2, ulong z1, ulong z2, ref ulong a1, ref ulong a2) => (a1 = x2) == z1 && (a2 = y2) == z2", checkUlong); - testResult = Fail; - } - - CheckMethodFourTFourU<int, int> checkInt32 = - (ValueTuple<int, int, int, int> x, ValueTuple<int, int, int, int> y, - ValueTuple<int, int, int, int> z, - ref int a1, ref int a2, ref int a3, ref int a4) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4; - }; - - if (!intTable.CheckUnpack(checkInt32)) - { - PrintError(intTable, methodUnderTestName, "(int x, int y, int z, ref int a) => (a = x ^ y) == z", checkInt32); - testResult = Fail; - } - - CheckMethodFourTFourU<uint, uint> checkUInt32 = - (ValueTuple<uint, uint, uint, uint> x, ValueTuple<uint, uint, uint, uint> y, - ValueTuple<uint, uint, uint, uint> z, - ref uint a1, ref uint a2, ref uint a3, ref uint a4) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4; - }; - - if (!uintTable.CheckUnpack(checkUInt32)) - { - PrintError(uintTable, methodUnderTestName, "(uint x, uint y, uint z, ref uint a) => (a = x ^ y) == z", checkUInt32); - testResult = Fail; - } - - CheckMethodEightOfTEightOfU<short, short> checkInt16 = - (ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> x, - ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> y, - ValueTuple<short, short, short, short, short, short, short, ValueTuple<short>> z, - ref short a1, ref short a2, ref short a3, ref short a4, ref short a5, ref short a6, ref short a7, ref short a8) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - a5 = x.Item3; - a6 = y.Item3; - a7 = x.Item4; - a8 = y.Item4; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4 && - a5 == z.Item5 && a6 == z.Item6 && a7 == z.Item7 && a8 == z.Item8; - }; - - if (!shortTable.CheckUnpack(checkInt16)) - { - PrintError(shortTable, methodUnderTestName, "CheckUnpack(CheckMethodEightOfTEightOfU<short, short>)", checkInt16); - testResult = Fail; - } - - CheckMethodEightOfTEightOfU<ushort, ushort> checkUInt16 = - (ValueTuple<ushort, ushort, ushort, ushort, ushort, ushort, ushort, ValueTuple<ushort>> x, - ValueTuple<ushort, ushort, ushort, ushort, ushort, ushort, ushort, ValueTuple<ushort>> y, - ValueTuple<ushort, ushort, ushort, ushort, ushort, ushort, ushort, ValueTuple<ushort>> z, - ref ushort a1, ref ushort a2, ref ushort a3, ref ushort a4, ref ushort a5, ref ushort a6, ref ushort a7, ref ushort a8) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - a5 = x.Item3; - a6 = y.Item3; - a7 = x.Item4; - a8 = y.Item4; - return a1 == z.Item1 && a2 == z.Item2 && a3 == z.Item3 && a4 == z.Item4 && - a5 == z.Item5 && a6 == z.Item6 && a7 == z.Item7 && a8 == z.Item8; - }; - - if (!ushortTable.CheckUnpack(checkUInt16)) - { - PrintError(ushortTable, methodUnderTestName, "(ushort x, ushort y, ushort z, ref ushort a) => (a = (ushort)(x ^ y)) == z", checkUInt16); - testResult = Fail; - } - - CheckMethodSixteenOfAll<sbyte, sbyte> checkSByte = - (ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> x, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> x1, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> y, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> y1, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> z1, - ValueTuple<sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, sbyte, ValueTuple<sbyte>> z2, - ref sbyte a1, ref sbyte a2, ref sbyte a3, ref sbyte a4, ref sbyte a5, ref sbyte a6, ref sbyte a7, ref sbyte a8, - ref sbyte a9, ref sbyte a10, ref sbyte a11, ref sbyte a12, ref sbyte a13, ref sbyte a14, ref sbyte a15, ref sbyte a16) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - a5 = x.Item3; - a6 = y.Item3; - a7 = x.Item4; - a8 = y.Item4; - a9 = x.Item5; - a10 = y.Item5; - a11 = x.Item6; - a12 = y.Item6; - a13 = x.Item7; - a14 = y.Item7; - a15 = x.Item8; - a16 = y.Item8; - - return a1 == z1.Item1 && a2 == z1.Item2 && a3 == z1.Item3 && a4 == z1.Item4 && - a5 == z1.Item5 && a6 == z1.Item6 && a7 == z1.Item7 && a8 == z1.Item8 && - a9 == z2.Item1 && a10 == z2.Item2 && a11 == z2.Item3 && a12 == z2.Item4 && - a13 == z2.Item5 && a14 == z2.Item6 && a15 == z2.Item7 && a16 == z2.Item8; - }; - - if (!sbyteTable.CheckUnpack(checkSByte)) - { - PrintError(sbyteTable, methodUnderTestName, "(sbyte x, sbyte y, sbyte z, ref sbyte a) => (a = (sbyte)(x ^ y)) == z", checkSByte); - testResult = Fail; - } - - CheckMethodSixteenOfAll<byte, byte> checkByte = - (ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> x, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> x1, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> y, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> y1, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> z1, - ValueTuple<byte, byte, byte, byte, byte, byte, byte, ValueTuple<byte>> z2, - ref byte a1, ref byte a2, ref byte a3, ref byte a4, ref byte a5, ref byte a6, ref byte a7, ref byte a8, - ref byte a9, ref byte a10, ref byte a11, ref byte a12, ref byte a13, ref byte a14, ref byte a15, ref byte a16) => - { - a1 = x.Item1; - a2 = y.Item1; - a3 = x.Item2; - a4 = y.Item2; - a5 = x.Item3; - a6 = y.Item3; - a7 = x.Item4; - a8 = y.Item4; - a9 = x.Item5; - a10 = y.Item5; - a11 = x.Item6; - a12 = y.Item6; - a13 = x.Item7; - a14 = y.Item7; - a15 = x.Item8; - a16 = y.Item8; - - return a1 == z1.Item1 && a2 == z1.Item2 && a3 == z1.Item3 && a4 == z1.Item4 && - a5 == z1.Item5 && a6 == z1.Item6 && a7 == z1.Item7 && a8 == z1.Item8 && - a9 == z2.Item1 && a10 == z2.Item2 && a11 == z2.Item3 && a12 == z2.Item4 && - a13 == z2.Item5 && a14 == z2.Item6 && a15 == z2.Item7 && a16 == z2.Item8; - }; - - if (!byteTable.CheckUnpack(checkByte)) - { - PrintError(byteTable, methodUnderTestName, "(byte x, byte y, byte z, ref byte a) => (a = (byte)(x ^ y)) == z", checkByte); - testResult = Fail; - } - } - } - else - { - Console.WriteLine($"Sse2.IsSupported: {Sse2.IsSupported}, skipped tests of {typeof(Sse2)}.{methodUnderTestName}"); - } - - return testResult; - } - } -} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow_r.csproj deleted file mode 100644 index 7b2ad44f7f..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow_r.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{FC28F10A-3F47-43E8-AEE5-DFCE881F19EF}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize></Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="TestTableSse2.cs" /> - <Compile Include="UnpackLow.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow_ro.csproj deleted file mode 100644 index 030ee6f4d4..0000000000 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/UnpackLow_ro.csproj +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{929ECE5C-8D63-4677-B5A6-C52543F41798}</ProjectGuid> - <OutputType>Exe</OutputType> - <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - </PropertyGroup> - <!-- Default configurations to help VS understand the configurations --> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> - <ItemGroup> - <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> - <Visible>False</Visible> - </CodeAnalysisDependentAssemblyPaths> - </ItemGroup> - <PropertyGroup> - <DebugType>Embedded</DebugType> - <Optimize>True</Optimize> - </PropertyGroup> - <ItemGroup> - <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> - </ItemGroup> - <ItemGroup> - <Compile Include="TestTableSse2.cs" /> - <Compile Include="UnpackLow.cs" /> - </ItemGroup> - <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> - <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "> - </PropertyGroup> -</Project>
\ No newline at end of file |