From eb57af5faeb71460d747fe87710b0e3d0b15b214 Mon Sep 17 00:00:00 2001 From: Fei Peng Date: Mon, 12 Mar 2018 22:24:40 -0700 Subject: [PATCH] Add tests for AVX Insert/ExtractVector128 --- .../JIT/HardwareIntrinsics/X86/Avx/Avx_r.csproj | 20 ++ .../JIT/HardwareIntrinsics/X86/Avx/Avx_ro.csproj | 20 ++ .../X86/Avx/ExtractVector128.Byte.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.Byte.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.Double.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.Double.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.Int16.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.Int16.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.Int32.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.Int32.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.Int64.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.Int64.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.SByte.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.SByte.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.Single.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.Single.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.UInt16.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.UInt16.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.UInt32.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.UInt32.1.cs | 321 +++++++++++++++++++ .../X86/Avx/ExtractVector128.UInt64.1.Store.cs | 297 ++++++++++++++++++ .../X86/Avx/ExtractVector128.UInt64.1.cs | 321 +++++++++++++++++++ .../X86/Avx/InsertExtractVector128.Avx.cs | 38 +++ .../X86/Avx/InsertExtractVector128_r.csproj | 60 ++++ .../X86/Avx/InsertExtractVector128_ro.csproj | 60 ++++ .../X86/Avx/InsertVector128.Byte.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.Byte.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.Double.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.Double.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.Int16.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.Int16.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.Int32.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.Int32.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.Int64.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.Int64.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.SByte.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.SByte.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.Single.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.Single.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.UInt16.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.UInt16.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.UInt32.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.UInt32.1.cs | 346 +++++++++++++++++++++ .../X86/Avx/InsertVector128.UInt64.1.Load.cs | 339 ++++++++++++++++++++ .../X86/Avx/InsertVector128.UInt64.1.cs | 346 +++++++++++++++++++++ .../JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs | 20 ++ .../X86/Shared/GenerateTests.csx | 20 ++ 47 files changed, 13268 insertions(+) create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.Store.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128.Avx.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_r.csproj create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_ro.csproj create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.Load.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.cs diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_r.csproj index e1d1a8d..ed36c63 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_r.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_r.csproj @@ -54,6 +54,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_ro.csproj index 4dd281b..897f037 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_ro.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_ro.csproj @@ -54,6 +54,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.Store.cs new file mode 100644 index 0000000..b43bb97 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128Byte1Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128Byte1Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Byte1Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int RetElementCount = 16 / sizeof(Byte); + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Byte1Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Byte1Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (Byte*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (Byte*)_dataTable.outArrayPtr, + Avx.LoadVector256((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (Byte*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Byte*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Byte*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Byte*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Byte*)), + Avx.LoadVector256((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Byte*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Byte*)), + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (Byte*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((Byte*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Byte*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Byte*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Byte*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Byte*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Byte1Store(); + Avx.ExtractVector128((Byte*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((Byte*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[16]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 16])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.cs new file mode 100644 index 0000000..4a8d646 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Byte.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128Byte1() + { + var test = new SimpleUnaryOpTest__ExtractVector128Byte1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Byte1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int RetElementCount = 16 / sizeof(Byte); + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Byte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Byte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Byte*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Byte*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Byte1(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[16]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 16])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.Store.cs new file mode 100644 index 0000000..4c80be7 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128Double1Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128Double1Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Double1Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Double); + private const int RetElementCount = 16 / sizeof(Double); + + private static Double[] _data = new Double[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Double1Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Double1Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (double)(random.NextDouble()); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Double[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (Double*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (Double*)_dataTable.outArrayPtr, + Avx.LoadVector256((Double*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (Double*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((Double*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Double*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Double*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Double*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Double*)), + Avx.LoadVector256((Double*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Double*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Double*)), + Avx.LoadAlignedVector256((Double*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (Double*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((Double*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Double*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Double*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Double*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Double*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Double1Store(); + Avx.ExtractVector128((Double*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((Double*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[2])) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i + 2]))) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.cs new file mode 100644 index 0000000..a048510 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Double.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128Double1() + { + var test = new SimpleUnaryOpTest__ExtractVector128Double1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Double1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Double); + private const int RetElementCount = 16 / sizeof(Double); + + private static Double[] _data = new Double[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Double1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Double1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (double)(random.NextDouble()); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Double[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((Double*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((Double*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Double) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Double) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Double*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Double) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Double*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Double*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Double*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Double1(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[2]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 2])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.Store.cs new file mode 100644 index 0000000..8732da3 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128Int161Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int161Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Int161Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int RetElementCount = 16 / sizeof(Int16); + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Int161Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Int161Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, short.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (Int16*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (Int16*)_dataTable.outArrayPtr, + Avx.LoadVector256((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (Int16*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int16*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int16*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int16*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int16*)), + Avx.LoadVector256((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int16*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int16*)), + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (Int16*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((Int16*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Int16*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Int16*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Int16*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Int16*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int161Store(); + Avx.ExtractVector128((Int16*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((Int16*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[8]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 8])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.cs new file mode 100644 index 0000000..8ef99ca --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int16.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128Int161() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int161(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Int161 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int RetElementCount = 16 / sizeof(Int16); + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Int161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Int161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, short.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int16) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int16) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int16) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Int16*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Int16*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int161(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[8]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 8])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.Store.cs new file mode 100644 index 0000000..886c0bd --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128Int321Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int321Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Int321Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int RetElementCount = 16 / sizeof(Int32); + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Int321Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Int321Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (Int32*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (Int32*)_dataTable.outArrayPtr, + Avx.LoadVector256((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (Int32*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int32*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int32*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int32*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int32*)), + Avx.LoadVector256((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int32*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int32*)), + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (Int32*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((Int32*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Int32*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Int32*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Int32*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Int32*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int321Store(); + Avx.ExtractVector128((Int32*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((Int32*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[4]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 4])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.cs new file mode 100644 index 0000000..11b97be --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int32.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128Int321() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int321(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Int321 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int RetElementCount = 16 / sizeof(Int32); + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Int321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Int321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int32) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int32) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int32) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Int32*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Int32*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int321(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[4]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 4])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.Store.cs new file mode 100644 index 0000000..005fc82 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128Int641Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int641Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Int641Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int RetElementCount = 16 / sizeof(Int64); + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Int641Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Int641Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (Int64*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (Int64*)_dataTable.outArrayPtr, + Avx.LoadVector256((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (Int64*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int64*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int64*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int64*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int64*)), + Avx.LoadVector256((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Int64*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Int64*)), + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (Int64*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((Int64*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Int64*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Int64*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Int64*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Int64*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int641Store(); + Avx.ExtractVector128((Int64*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((Int64*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[2]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 2])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.cs new file mode 100644 index 0000000..f6f8c1b --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Int64.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128Int641() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int641(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Int641 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int RetElementCount = 16 / sizeof(Int64); + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Int641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Int641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int64) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int64) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Int64*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Int64*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Int641(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[2]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 2])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.Store.cs new file mode 100644 index 0000000..fa745d2 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128SByte1Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128SByte1Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128SByte1Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int RetElementCount = 16 / sizeof(SByte); + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128SByte1Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128SByte1Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (SByte*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (SByte*)_dataTable.outArrayPtr, + Avx.LoadVector256((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (SByte*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(SByte*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(SByte*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(SByte*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(SByte*)), + Avx.LoadVector256((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(SByte*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(SByte*)), + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (SByte*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((SByte*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((SByte*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((SByte*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((SByte*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((SByte*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128SByte1Store(); + Avx.ExtractVector128((SByte*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((SByte*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[16]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 16])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.cs new file mode 100644 index 0000000..2dddbe5 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.SByte.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128SByte1() + { + var test = new SimpleUnaryOpTest__ExtractVector128SByte1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128SByte1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int RetElementCount = 16 / sizeof(SByte); + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128SByte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128SByte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(SByte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(SByte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(SByte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((SByte*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((SByte*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128SByte1(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[16]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 16])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.Store.cs new file mode 100644 index 0000000..3fe06f5 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128Single1Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128Single1Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Single1Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int RetElementCount = 16 / sizeof(Single); + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Single1Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Single1Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (Single*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (Single*)_dataTable.outArrayPtr, + Avx.LoadVector256((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (Single*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Single*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Single*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Single*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Single*)), + Avx.LoadVector256((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(Single*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(Single*)), + Avx.LoadAlignedVector256((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (Single*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((Single*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Single*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Single*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Single*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((Single*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Single1Store(); + Avx.ExtractVector128((Single*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((Single*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + if (BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[4])) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i + 4]))) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.cs new file mode 100644 index 0000000..7b72949 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.Single.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128Single1() + { + var test = new SimpleUnaryOpTest__ExtractVector128Single1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128Single1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int RetElementCount = 16 / sizeof(Single); + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128Single1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128Single1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Single) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Single) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Single) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((Single*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((Single*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128Single1(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[4]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 4])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.Store.cs new file mode 100644 index 0000000..4f3d5a1 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128UInt161Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt161Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128UInt161Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int RetElementCount = 16 / sizeof(UInt16); + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128UInt161Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128UInt161Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (UInt16*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (UInt16*)_dataTable.outArrayPtr, + Avx.LoadVector256((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (UInt16*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt16*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt16*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt16*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt16*)), + Avx.LoadVector256((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt16*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt16*)), + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (UInt16*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((UInt16*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((UInt16*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((UInt16*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((UInt16*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt161Store(); + Avx.ExtractVector128((UInt16*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((UInt16*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[8]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 8])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.cs new file mode 100644 index 0000000..855580c --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt16.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128UInt161() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt161(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128UInt161 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int RetElementCount = 16 / sizeof(UInt16); + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128UInt161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128UInt161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((UInt16*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt161(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[8]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 8])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.Store.cs new file mode 100644 index 0000000..1420220 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128UInt321Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt321Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128UInt321Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int RetElementCount = 16 / sizeof(UInt32); + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128UInt321Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128UInt321Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (UInt32*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (UInt32*)_dataTable.outArrayPtr, + Avx.LoadVector256((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (UInt32*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt32*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt32*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt32*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt32*)), + Avx.LoadVector256((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt32*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt32*)), + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (UInt32*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((UInt32*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((UInt32*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((UInt32*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((UInt32*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt321Store(); + Avx.ExtractVector128((UInt32*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((UInt32*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[4]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 4])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.cs new file mode 100644 index 0000000..25fd064 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt32.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128UInt321() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt321(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128UInt321 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int RetElementCount = 16 / sizeof(UInt32); + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128UInt321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128UInt321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((UInt32*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt321(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[4]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 4])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.Store.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.Store.cs new file mode 100644 index 0000000..fc22be9 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.Store.cs @@ -0,0 +1,297 @@ +// 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.Reflection; +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 ExtractVector128UInt641Store() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt641Store(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128UInt641Store + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int RetElementCount = 16 / sizeof(UInt64); + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128UInt641Store() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128UInt641Store() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + Avx.ExtractVector128( + (UInt64*)_dataTable.outArrayPtr, + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + Avx.ExtractVector128( + (UInt64*)_dataTable.outArrayPtr, + Avx.LoadVector256((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + Avx.ExtractVector128( + (UInt64*)_dataTable.outArrayPtr, + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt64*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt64*)), + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt64*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt64*)), + Avx.LoadVector256((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + typeof(Avx).GetMethod(nameof(Avx.ExtractVector128), new Type[] { typeof(UInt64*), typeof(Vector256), typeof(byte) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.outArrayPtr, typeof(UInt64*)), + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + Avx.ExtractVector128( + (UInt64*)_dataTable.outArrayPtr, + _clsVar, + 1 + ); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + Avx.ExtractVector128((UInt64*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((UInt64*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((UInt64*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArrayPtr)); + Avx.ExtractVector128((UInt64*)_dataTable.outArrayPtr, firstOp, 1); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt641Store(); + Avx.ExtractVector128((UInt64*)_dataTable.outArrayPtr, test._fld, 1); + } + + public void RunFldScenario() + { + Avx.ExtractVector128((UInt64*)_dataTable.outArrayPtr, _fld, 1); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[2]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 2])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.cs new file mode 100644 index 0000000..d43f651 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/ExtractVector128.UInt64.1.cs @@ -0,0 +1,321 @@ +// 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.Reflection; +using System.Linq; +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 ExtractVector128UInt641() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt641(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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 SimpleUnaryOpTest__ExtractVector128UInt641 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int RetElementCount = 16 / sizeof(UInt64); + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector256 _clsVar; + + private Vector256 _fld; + + private SimpleUnaryOpTest__DataTable _dataTable; + + static SimpleUnaryOpTest__ExtractVector128UInt641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), VectorSize); + } + + public SimpleUnaryOpTest__ExtractVector128UInt641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleUnaryOpTest__DataTable(_data, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.ExtractVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.ExtractVector128( + Avx.LoadVector256((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.ExtractVector128( + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.ExtractVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.ExtractVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var firstOp = Avx.LoadVector256((UInt64*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var firstOp = Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArrayPtr)); + var result = Avx.ExtractVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleUnaryOpTest__ExtractVector128UInt641(); + var result = Avx.ExtractVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.ExtractVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + if (result[0] != firstOp[2]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((result[i] != firstOp[i + 2])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.ExtractVector128)}(Vector256<9>): {method} failed:"); + Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128.Avx.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128.Avx.cs new file mode 100644 index 0000000..63f9233 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128.Avx.cs @@ -0,0 +1,38 @@ +// 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.Collections.Generic; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + static Program() + { + TestList = new Dictionary() { + ["ExtractVector128.Byte.1"] = ExtractVector128Byte1, + ["ExtractVector128.SByte.1"] = ExtractVector128SByte1, + ["ExtractVector128.Int16.1"] = ExtractVector128Int161, + ["ExtractVector128.UInt16.1"] = ExtractVector128UInt161, + ["ExtractVector128.Int32.1"] = ExtractVector128Int321, + ["ExtractVector128.UInt32.1"] = ExtractVector128UInt321, + ["ExtractVector128.Int64.1"] = ExtractVector128Int641, + ["ExtractVector128.UInt64.1"] = ExtractVector128UInt641, + ["ExtractVector128.Single.1"] = ExtractVector128Single1, + ["ExtractVector128.Double.1"] = ExtractVector128Double1, + ["InsertVector128.Byte.1"] = InsertVector128Byte1, + ["InsertVector128.SByte.1"] = InsertVector128SByte1, + ["InsertVector128.Int16.1"] = InsertVector128Int161, + ["InsertVector128.UInt16.1"] = InsertVector128UInt161, + ["InsertVector128.Int32.1"] = InsertVector128Int321, + ["InsertVector128.UInt32.1"] = InsertVector128UInt321, + ["InsertVector128.Int64.1"] = InsertVector128Int641, + ["InsertVector128.UInt64.1"] = InsertVector128UInt641, + ["InsertVector128.Single.1"] = InsertVector128Single1, + ["InsertVector128.Double.1"] = InsertVector128Double1, + }; + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_r.csproj new file mode 100644 index 0000000..68189b4 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_r.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + None + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_ro.csproj new file mode 100644 index 0000000..68189b4 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertExtractVector128_ro.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + None + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.Load.cs new file mode 100644 index 0000000..0d7c578 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Byte1Load() + { + var test = new SimpleBinaryOpTest__InsertVector128Byte1Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Byte1Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int Op2ElementCount = 16 / sizeof(Byte); + private const int RetElementCount = VectorSize / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Byte1Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Byte1Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (byte)(random.Next(0, byte.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (Byte*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Byte*)(_dataTable.inArray1Ptr)), + (Byte*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArray1Ptr)), + (Byte*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Byte*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Byte*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Byte*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Byte*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Byte*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Byte*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Byte*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (Byte*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (Byte*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (Byte*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Byte*)(_dataTable.inArray1Ptr)); + var right = (Byte*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Byte*)(_dataTable.inArray1Ptr)); + var right = (Byte*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Byte1Load(); + var result = Avx.InsertVector128(test._fld1, (Byte*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (Byte*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (Byte*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (Byte*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 15 ? result[i] != right[i - 16] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.cs new file mode 100644 index 0000000..ffcce7b --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Byte.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Byte1() + { + var test = new SimpleBinaryOpTest__InsertVector128Byte1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Byte1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Byte); + private const int Op2ElementCount = 16 / sizeof(Byte); + private const int RetElementCount = VectorSize / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Byte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Byte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (byte)(random.Next(0, byte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (byte)(random.Next(0, byte.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Byte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Byte*)(_dataTable.inArray1Ptr)), + LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Byte*)(_dataTable.inArray1Ptr)), + LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Byte*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Byte*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Byte*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Byte1(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 15 ? result[i] != right[i - 16] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.Load.cs new file mode 100644 index 0000000..db00d65 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Double1Load() + { + var test = new SimpleBinaryOpTest__InsertVector128Double1Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Double1Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Double); + private const int Op2ElementCount = 16 / sizeof(Double); + private const int RetElementCount = VectorSize / sizeof(Double); + + private static Double[] _data1 = new Double[Op1ElementCount]; + private static Double[] _data2 = new Double[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Double1Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Double1Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Double[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (Double*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)), + (Double*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)), + (Double*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Double*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Double*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Double*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Double*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Double*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Double*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (Double*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (Double*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (Double*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)); + var right = (Double*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)); + var right = (Double*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Double1Load(); + var result = Avx.InsertVector128(test._fld1, (Double*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (Double*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (Double*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (Double*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] inArray2 = new Double[Op2ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 1 ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[i - 2]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i]))) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.cs new file mode 100644 index 0000000..188c9ef --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Double.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Double1() + { + var test = new SimpleBinaryOpTest__InsertVector128Double1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Double1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Double); + private const int Op2ElementCount = 16 / sizeof(Double); + private const int RetElementCount = VectorSize / sizeof(Double); + + private static Double[] _data1 = new Double[Op1ElementCount]; + private static Double[] _data2 = new Double[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Double1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Double1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Double[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)), + LoadVector128((Double*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Double) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Double) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)), + LoadVector128((Double*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Double) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((Double*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Double1(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + Double[] inArray1 = new Double[Op1ElementCount]; + Double[] inArray2 = new Double[Op2ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i > 1 ? result[i] != right[i - 2] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.Load.cs new file mode 100644 index 0000000..0f032f8 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Int161Load() + { + var test = new SimpleBinaryOpTest__InsertVector128Int161Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Int161Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int Op2ElementCount = 16 / sizeof(Int16); + private const int RetElementCount = VectorSize / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Int161Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(0,short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Int161Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(0,short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(0, short.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(0,short.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (Int16*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Int16*)(_dataTable.inArray1Ptr)), + (Int16*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArray1Ptr)), + (Int16*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int16*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int16*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int16*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int16*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int16*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int16*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int16*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (Int16*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (Int16*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (Int16*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Int16*)(_dataTable.inArray1Ptr)); + var right = (Int16*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Int16*)(_dataTable.inArray1Ptr)); + var right = (Int16*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Int161Load(); + var result = Avx.InsertVector128(test._fld1, (Int16*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (Int16*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (Int16*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (Int16*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 7 ? result[i] != right[i - 8] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.cs new file mode 100644 index 0000000..592d795 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int16.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Int161() + { + var test = new SimpleBinaryOpTest__InsertVector128Int161(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Int161 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int16); + private const int Op2ElementCount = 16 / sizeof(Int16); + private const int RetElementCount = VectorSize / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Int161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Int161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(0, short.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(0, short.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(0, short.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Int16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Int16*)(_dataTable.inArray1Ptr)), + LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int16) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int16) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int16*)(_dataTable.inArray1Ptr)), + LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int16) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int16*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Int16*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Int16*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Int161(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 7 ? result[i] != right[i - 8] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.Load.cs new file mode 100644 index 0000000..50e36a3 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Int321Load() + { + var test = new SimpleBinaryOpTest__InsertVector128Int321Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Int321Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int Op2ElementCount = 16 / sizeof(Int32); + private const int RetElementCount = VectorSize / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Int321Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (int)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Int321Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (int)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (int)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (int)(random.Next(0,int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (Int32*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Int32*)(_dataTable.inArray1Ptr)), + (Int32*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArray1Ptr)), + (Int32*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int32*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int32*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int32*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int32*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int32*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int32*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int32*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (Int32*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (Int32*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (Int32*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Int32*)(_dataTable.inArray1Ptr)); + var right = (Int32*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Int32*)(_dataTable.inArray1Ptr)); + var right = (Int32*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Int321Load(); + var result = Avx.InsertVector128(test._fld1, (Int32*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (Int32*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (Int32*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (Int32*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 3 ? result[i] != right[i - 4] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.cs new file mode 100644 index 0000000..fcc13d2 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int32.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Int321() + { + var test = new SimpleBinaryOpTest__InsertVector128Int321(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Int321 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int32); + private const int Op2ElementCount = 16 / sizeof(Int32); + private const int RetElementCount = VectorSize / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Int321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Int321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (int)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (int)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (int)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Int32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Int32*)(_dataTable.inArray1Ptr)), + LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int32) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int32) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int32*)(_dataTable.inArray1Ptr)), + LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int32) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int32*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Int32*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Int32*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Int321(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 3 ? result[i] != right[i - 4] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.Load.cs new file mode 100644 index 0000000..1aaa274 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Int641Load() + { + var test = new SimpleBinaryOpTest__InsertVector128Int641Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Int641Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int Op2ElementCount = 16 / sizeof(Int64); + private const int RetElementCount = VectorSize / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Int641Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (long)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Int641Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (long)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (long)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (long)(random.Next(0,int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (Int64*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Int64*)(_dataTable.inArray1Ptr)), + (Int64*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArray1Ptr)), + (Int64*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int64*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int64*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int64*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int64*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int64*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Int64*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Int64*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (Int64*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (Int64*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (Int64*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Int64*)(_dataTable.inArray1Ptr)); + var right = (Int64*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Int64*)(_dataTable.inArray1Ptr)); + var right = (Int64*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Int641Load(); + var result = Avx.InsertVector128(test._fld1, (Int64*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (Int64*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (Int64*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (Int64*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i > 1 ? result[i] != right[i - 2] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.cs new file mode 100644 index 0000000..0d353ae --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Int64.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Int641() + { + var test = new SimpleBinaryOpTest__InsertVector128Int641(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Int641 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Int64); + private const int Op2ElementCount = 16 / sizeof(Int64); + private const int RetElementCount = VectorSize / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Int641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Int641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (long)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (long)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (long)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Int64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Int64*)(_dataTable.inArray1Ptr)), + LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int64) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Int64*)(_dataTable.inArray1Ptr)), + LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Int64) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Int64*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Int64*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Int64*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Int641(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i > 1 ? result[i] != right[i - 2] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.Load.cs new file mode 100644 index 0000000..4b584fb --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128SByte1Load() + { + var test = new SimpleBinaryOpTest__InsertVector128SByte1Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128SByte1Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int Op2ElementCount = 16 / sizeof(SByte); + private const int RetElementCount = VectorSize / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128SByte1Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (sbyte)(random.Next(0,sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128SByte1Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (sbyte)(random.Next(0,sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (sbyte)(random.Next(0,sbyte.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (SByte*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((SByte*)(_dataTable.inArray1Ptr)), + (SByte*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArray1Ptr)), + (SByte*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(SByte*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(SByte*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(SByte*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((SByte*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(SByte*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(SByte*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(SByte*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (SByte*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (SByte*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (SByte*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((SByte*)(_dataTable.inArray1Ptr)); + var right = (SByte*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((SByte*)(_dataTable.inArray1Ptr)); + var right = (SByte*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128SByte1Load(); + var result = Avx.InsertVector128(test._fld1, (SByte*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (SByte*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (SByte*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (SByte*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 15 ? result[i] != right[i - 16] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.cs new file mode 100644 index 0000000..7dcd2f0 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.SByte.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128SByte1() + { + var test = new SimpleBinaryOpTest__InsertVector128SByte1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128SByte1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(SByte); + private const int Op2ElementCount = 16 / sizeof(SByte); + private const int RetElementCount = VectorSize / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128SByte1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128SByte1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new SByte[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((SByte*)(_dataTable.inArray1Ptr)), + LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(SByte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(SByte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((SByte*)(_dataTable.inArray1Ptr)), + LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(SByte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((SByte*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((SByte*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((SByte*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128SByte1(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 15 ? result[i] != right[i - 16] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.Load.cs new file mode 100644 index 0000000..a41d40d --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Single1Load() + { + var test = new SimpleBinaryOpTest__InsertVector128Single1Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Single1Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int Op2ElementCount = 16 / sizeof(Single); + private const int RetElementCount = VectorSize / sizeof(Single); + + private static Single[] _data1 = new Single[Op1ElementCount]; + private static Single[] _data2 = new Single[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Single1Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Single1Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (float)(random.NextDouble()); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (Single*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)), + (Single*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)), + (Single*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Single*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Single*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Single*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Single*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(Single*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(Single*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (Single*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (Single*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (Single*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)); + var right = (Single*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)); + var right = (Single*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Single1Load(); + var result = Avx.InsertVector128(test._fld1, (Single*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (Single*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (Single*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (Single*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] inArray2 = new Single[Op2ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] inArray2 = new Single[Op2ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "") + { + if (BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(left[0])) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i > 3 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(right[i - 4]) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(left[i]))) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.cs new file mode 100644 index 0000000..6b12b57 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.Single.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128Single1() + { + var test = new SimpleBinaryOpTest__InsertVector128Single1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128Single1 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(Single); + private const int Op2ElementCount = 16 / sizeof(Single); + private const int RetElementCount = VectorSize / sizeof(Single); + + private static Single[] _data1 = new Single[Op1ElementCount]; + private static Single[] _data2 = new Single[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128Single1() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128Single1() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (float)(random.NextDouble()); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (float)(random.NextDouble()); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new Single[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)), + LoadVector128((Single*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Single) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Single) }) + .Invoke(null, new object[] { + Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)), + LoadVector128((Single*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(Single) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((Single*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128Single1(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] inArray2 = new Single[Op2ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "") + { + Single[] inArray1 = new Single[Op1ElementCount]; + Single[] inArray2 = new Single[Op2ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i > 3 ? result[i] != right[i - 4] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.Load.cs new file mode 100644 index 0000000..47fc2ca --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128UInt161Load() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt161Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128UInt161Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int Op2ElementCount = 16 / sizeof(UInt16); + private const int RetElementCount = VectorSize / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128UInt161Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ushort)(random.Next(0,ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128UInt161Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ushort)(random.Next(0,ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ushort)(random.Next(0,ushort.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (UInt16*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((UInt16*)(_dataTable.inArray1Ptr)), + (UInt16*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArray1Ptr)), + (UInt16*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt16*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt16*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt16*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt16*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt16*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt16*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt16*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (UInt16*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (UInt16*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (UInt16*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((UInt16*)(_dataTable.inArray1Ptr)); + var right = (UInt16*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArray1Ptr)); + var right = (UInt16*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt161Load(); + var result = Avx.InsertVector128(test._fld1, (UInt16*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (UInt16*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (UInt16*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (UInt16*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 7 ? result[i] != right[i - 8] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.cs new file mode 100644 index 0000000..6eff087 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt16.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128UInt161() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt161(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128UInt161 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt16); + private const int Op2ElementCount = 16 / sizeof(UInt16); + private const int RetElementCount = VectorSize / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128UInt161() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128UInt161() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ushort)(random.Next(0, ushort.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new UInt16[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((UInt16*)(_dataTable.inArray1Ptr)), + LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt16*)(_dataTable.inArray1Ptr)), + LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((UInt16*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((UInt16*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt161(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 7 ? result[i] != right[i - 8] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.Load.cs new file mode 100644 index 0000000..da9e5bf --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128UInt321Load() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt321Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128UInt321Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int Op2ElementCount = 16 / sizeof(UInt32); + private const int RetElementCount = VectorSize / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128UInt321Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (uint)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128UInt321Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (uint)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (uint)(random.Next(0,int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (UInt32*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((UInt32*)(_dataTable.inArray1Ptr)), + (UInt32*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArray1Ptr)), + (UInt32*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt32*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt32*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt32*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt32*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt32*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt32*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt32*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (UInt32*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (UInt32*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (UInt32*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((UInt32*)(_dataTable.inArray1Ptr)); + var right = (UInt32*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArray1Ptr)); + var right = (UInt32*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt321Load(); + var result = Avx.InsertVector128(test._fld1, (UInt32*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (UInt32*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (UInt32*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (UInt32*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 3 ? result[i] != right[i - 4] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.cs new file mode 100644 index 0000000..4a11f6f --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt32.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128UInt321() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt321(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128UInt321 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt32); + private const int Op2ElementCount = 16 / sizeof(UInt32); + private const int RetElementCount = VectorSize / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128UInt321() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128UInt321() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (uint)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (uint)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new UInt32[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((UInt32*)(_dataTable.inArray1Ptr)), + LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt32*)(_dataTable.inArray1Ptr)), + LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((UInt32*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((UInt32*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt321(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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 > 3 ? result[i] != right[i - 4] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.Load.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.Load.cs new file mode 100644 index 0000000..8fb7b27 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.Load.cs @@ -0,0 +1,339 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128UInt641Load() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt641Load(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128UInt641Load + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int Op2ElementCount = 16 / sizeof(UInt64); + private const int RetElementCount = VectorSize / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128UInt641Load() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ulong)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128UInt641Load() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ulong)(random.Next(0,int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ulong)(random.Next(0,int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + (UInt64*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((UInt64*)(_dataTable.inArray1Ptr)), + (UInt64*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArray1Ptr)), + (UInt64*)(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt64*), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt64*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt64*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt64*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt64*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethod(nameof(Avx.InsertVector128), new Type[] { typeof(Vector256), typeof(UInt64*), typeof(byte) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArray1Ptr)), + Pointer.Box(_dataTable.inArray2Ptr, typeof(UInt64*)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + (UInt64*)_dataTable.inArray2Ptr, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, (UInt64*)_dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = (UInt64*)_dataTable.inArray2Ptr; + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((UInt64*)(_dataTable.inArray1Ptr)); + var right = (UInt64*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArray1Ptr)); + var right = (UInt64*)(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt641Load(); + var result = Avx.InsertVector128(test._fld1, (UInt64*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, (UInt64*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, (UInt64*)(_dataTable.inArray2Ptr), 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, (UInt64*)(_dataTable.inArray2Ptr), _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, void* right, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i > 1 ? result[i] != right[i - 2] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.cs new file mode 100644 index 0000000..5074265 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/InsertVector128.UInt64.1.cs @@ -0,0 +1,346 @@ +// 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.Reflection; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using static System.Runtime.Intrinsics.X86.Sse2; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + private static void InsertVector128UInt641() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt641(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (Avx.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 (Avx.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 (Avx.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 works + test.RunLclFldScenario(); + + // Validates passing an instance member works + test.RunFldScenario(); + } + 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__InsertVector128UInt641 + { + private const int VectorSize = 32; + + private const int Op1ElementCount = VectorSize / sizeof(UInt64); + private const int Op2ElementCount = 16 / sizeof(UInt64); + private const int RetElementCount = VectorSize / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector256 _clsVar1; + private static Vector128 _clsVar2; + + private Vector256 _fld1; + private Vector128 _fld2; + + private SimpleBinaryOpTest__DataTable _dataTable; + + static SimpleBinaryOpTest__InsertVector128UInt641() + { + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), VectorSize); + } + + public SimpleBinaryOpTest__InsertVector128UInt641() + { + Succeeded = true; + + var random = new Random(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), VectorSize); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ulong)(random.Next(0, int.MaxValue)); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), VectorSize); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (ulong)(random.Next(0, int.MaxValue)); } + _dataTable = new SimpleBinaryOpTest__DataTable(_data1, _data2, new UInt64[RetElementCount], VectorSize); + } + + public bool IsSupported => Avx.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + var result = Avx.InsertVector128( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + var result = Avx.InsertVector128( + Avx.LoadVector256((UInt64*)(_dataTable.inArray1Ptr)), + LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + var result = Avx.InsertVector128( + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Avx.LoadVector256((UInt64*)(_dataTable.inArray1Ptr)), + LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_LoadAligned() + { + var result = typeof(Avx).GetMethods(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault( mi => mi.Name == nameof(Avx.InsertVector128) && mi.IsGenericMethod) + .MakeGenericMethod(new[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArray1Ptr)), + LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + var result = Avx.InsertVector128( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + var left = Unsafe.Read>(_dataTable.inArray1Ptr); + var right = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + var left = Avx.LoadVector256((UInt64*)(_dataTable.inArray1Ptr)); + var right = LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_LoadAligned() + { + var left = Avx.LoadAlignedVector256((UInt64*)(_dataTable.inArray1Ptr)); + var right = LoadAlignedVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = Avx.InsertVector128(left, right, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(left, right, _dataTable.outArrayPtr); + } + + public void RunLclFldScenario() + { + var test = new SimpleBinaryOpTest__InsertVector128UInt641(); + var result = Avx.InsertVector128(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunFldScenario() + { + var result = Avx.InsertVector128(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(Vector256 left, Vector128 right, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left); + Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + 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(ref inArray1[0]), ref Unsafe.AsRef(left), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(right), VectorSize); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), VectorSize); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + if (result[0] != left[0]) + { + Succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ((i > 1 ? result[i] != right[i - 2] : result[i] != left[i])) + { + Succeeded = false; + break; + } + } + } + + if (!Succeeded) + { + Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.InsertVector128)}(Vector256, Vector128.1): {method} failed:"); + Console.WriteLine($" left: ({string.Join(", ", left)})"); + Console.WriteLine($" right: ({string.Join(", ", right)})"); + Console.WriteLine($" result: ({string.Join(", ", result)})"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs index d74b22f..cb741ed 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs @@ -39,6 +39,26 @@ namespace JIT.HardwareIntrinsics.X86 ["ExtendToVector256.UInt16"] = ExtendToVector256UInt16, ["ExtendToVector256.UInt32"] = ExtendToVector256UInt32, ["ExtendToVector256.UInt64"] = ExtendToVector256UInt64, + ["ExtractVector128.Byte.1.Store"] = ExtractVector128Byte1Store, + ["ExtractVector128.SByte.1.Store"] = ExtractVector128SByte1Store, + ["ExtractVector128.Int16.1.Store"] = ExtractVector128Int161Store, + ["ExtractVector128.UInt16.1.Store"] = ExtractVector128UInt161Store, + ["ExtractVector128.Int32.1.Store"] = ExtractVector128Int321Store, + ["ExtractVector128.UInt32.1.Store"] = ExtractVector128UInt321Store, + ["ExtractVector128.Int64.1.Store"] = ExtractVector128Int641Store, + ["ExtractVector128.UInt64.1.Store"] = ExtractVector128UInt641Store, + ["ExtractVector128.Single.1.Store"] = ExtractVector128Single1Store, + ["ExtractVector128.Double.1.Store"] = ExtractVector128Double1Store, + ["InsertVector128.Byte.1.Load"] = InsertVector128Byte1Load, + ["InsertVector128.SByte.1.Load"] = InsertVector128SByte1Load, + ["InsertVector128.Int16.1.Load"] = InsertVector128Int161Load, + ["InsertVector128.UInt16.1.Load"] = InsertVector128UInt161Load, + ["InsertVector128.Int32.1.Load"] = InsertVector128Int321Load, + ["InsertVector128.UInt32.1.Load"] = InsertVector128UInt321Load, + ["InsertVector128.Int64.1.Load"] = InsertVector128Int641Load, + ["InsertVector128.UInt64.1.Load"] = InsertVector128UInt641Load, + ["InsertVector128.Single.1.Load"] = InsertVector128Single1Load, + ["InsertVector128.Double.1.Load"] = InsertVector128Double1Load, ["Floor.Double"] = FloorDouble, ["Floor.Single"] = FloorSingle, ["GetLowerHalf.Byte"] = GetLowerHalfByte, diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx index 200fc4f..25245c2 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx @@ -429,6 +429,26 @@ private static readonly (string templateFileName, Dictionary tem ("GenericUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Sse2",["Method"] = "ExtendToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["VectorSize"] = "32", ["NextValueOp1"] = "(ushort)(random.Next(0, ushort.MaxValue))", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != ((i < (RetElementCount / 2)) ? firstOp[i] : 0)"}), ("GenericUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Sse2",["Method"] = "ExtendToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["VectorSize"] = "32", ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != ((i < (RetElementCount / 2)) ? firstOp[i] : 0)"}), ("GenericUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Sse2",["Method"] = "ExtendToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["VectorSize"] = "32", ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != ((i < (RetElementCount / 2)) ? firstOp[i] : 0)"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Byte", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(byte)(random.Next(0, byte.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[16]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 16])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "SByte", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(sbyte)(random.Next(0, sbyte.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[16]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 16])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(short)(random.Next(0, short.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[8]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 8])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt16", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(ushort)(random.Next(0, ushort.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[8]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 8])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(int)(random.Next(0, int.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[4]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 4])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[4]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 4])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(long)(random.Next(0, int.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 2])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i + 2])"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(float)(random.NextDouble())", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[4])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i + 4]))"}), + ("ExtractStoreTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(double)(random.NextDouble())", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[2])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i + 2]))"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(byte)(random.Next(0, byte.MaxValue))", ["NextValueOp2"] = "(byte)(random.Next(0, byte.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 15 ? result[i] != right[i - 16] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(sbyte)(random.Next(0, sbyte.MaxValue))", ["NextValueOp2"] = "(sbyte)(random.Next(0,sbyte.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 15 ? result[i] != right[i - 16] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(short)(random.Next(0, short.MaxValue))", ["NextValueOp2"] = "(short)(random.Next(0,short.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 7 ? result[i] != right[i - 8] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(ushort)(random.Next(0, ushort.MaxValue))", ["NextValueOp2"] = "(ushort)(random.Next(0,ushort.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 7 ? result[i] != right[i - 8] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(int)(random.Next(0, int.MaxValue))", ["NextValueOp2"] = "(int)(random.Next(0,int.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 3 ? result[i] != right[i - 4] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))", ["NextValueOp2"] = "(uint)(random.Next(0,int.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 3 ? result[i] != right[i - 4] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(long)(random.Next(0, int.MaxValue))", ["NextValueOp2"] = "(long)(random.Next(0,int.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 1 ? result[i] != right[i - 2] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))", ["NextValueOp2"] = "(ulong)(random.Next(0,int.MaxValue))", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "(i > 1 ? result[i] != right[i - 2] : result[i] != left[i])"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(float)(random.NextDouble())", ["NextValueOp2"] = "(float)(random.NextDouble())", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(left[0])", ["ValidateRemainingResults"] = "(i > 3 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(right[i - 4]) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(left[i]))"}), + ("InsertLoadTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "InsertVector128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Imm"] = "1", ["VectorSize"] = "32", ["NextValueOp1"] = "(double)(random.NextDouble())", ["NextValueOp2"] = "(double)(random.NextDouble())", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[0])", ["ValidateRemainingResults"] = "(i > 1 ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[i - 2]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i]))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Floor", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["VectorSize"] = "32", ["NextValueOp1"] = "(double)(random.NextDouble())", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Floor(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(Math.Floor(firstOp[i]))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Floor", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["VectorSize"] = "32", ["NextValueOp1"] = "(float)(random.NextDouble())", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Floor(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(MathF.Floor(firstOp[i]))"}), ("GenericUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "GetLowerHalf", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Byte", ["VectorSize"] = "32", ["NextValueOp1"] = "(byte)(random.Next(0, byte.MaxValue))", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != ((i < (Op1ElementCount / 2)) ? firstOp[i] : 0)"}), -- 2.7.4