<Compile Include="BlendVariable.Single.cs" />
<Compile Include="Ceiling.Double.cs" />
<Compile Include="Ceiling.Single.cs" />
+ <Compile Include="CompareEqual.Single.cs" />
+ <Compile Include="CompareEqual.Double.cs" />
+ <Compile Include="CompareGreaterThan.Single.cs" />
+ <Compile Include="CompareGreaterThan.Double.cs" />
+ <Compile Include="CompareGreaterThanOrEqual.Single.cs" />
+ <Compile Include="CompareGreaterThanOrEqual.Double.cs" />
+ <Compile Include="CompareLessThan.Single.cs" />
+ <Compile Include="CompareLessThan.Double.cs" />
+ <Compile Include="CompareLessThanOrEqual.Single.cs" />
+ <Compile Include="CompareLessThanOrEqual.Double.cs" />
+ <Compile Include="CompareNotEqual.Single.cs" />
+ <Compile Include="CompareNotEqual.Double.cs" />
+ <Compile Include="CompareNotGreaterThan.Single.cs" />
+ <Compile Include="CompareNotGreaterThan.Double.cs" />
+ <Compile Include="CompareNotGreaterThanOrEqual.Single.cs" />
+ <Compile Include="CompareNotGreaterThanOrEqual.Double.cs" />
+ <Compile Include="CompareNotLessThan.Single.cs" />
+ <Compile Include="CompareNotLessThan.Double.cs" />
+ <Compile Include="CompareNotLessThanOrEqual.Single.cs" />
+ <Compile Include="CompareNotLessThanOrEqual.Double.cs" />
+ <Compile Include="CompareOrdered.Single.cs" />
+ <Compile Include="CompareOrdered.Double.cs" />
+ <Compile Include="CompareUnordered.Single.cs" />
+ <Compile Include="CompareUnordered.Double.cs" />
<Compile Include="Divide.Double.cs" />
<Compile Include="Divide.Single.cs" />
<Compile Include="DuplicateEvenIndexed.Double.cs" />
<Compile Include="BlendVariable.Single.cs" />
<Compile Include="Ceiling.Double.cs" />
<Compile Include="Ceiling.Single.cs" />
+ <Compile Include="CompareEqual.Single.cs" />
+ <Compile Include="CompareEqual.Double.cs" />
+ <Compile Include="CompareGreaterThan.Single.cs" />
+ <Compile Include="CompareGreaterThan.Double.cs" />
+ <Compile Include="CompareGreaterThanOrEqual.Single.cs" />
+ <Compile Include="CompareGreaterThanOrEqual.Double.cs" />
+ <Compile Include="CompareLessThan.Single.cs" />
+ <Compile Include="CompareLessThan.Double.cs" />
+ <Compile Include="CompareLessThanOrEqual.Single.cs" />
+ <Compile Include="CompareLessThanOrEqual.Double.cs" />
+ <Compile Include="CompareNotEqual.Single.cs" />
+ <Compile Include="CompareNotEqual.Double.cs" />
+ <Compile Include="CompareNotGreaterThan.Single.cs" />
+ <Compile Include="CompareNotGreaterThan.Double.cs" />
+ <Compile Include="CompareNotGreaterThanOrEqual.Single.cs" />
+ <Compile Include="CompareNotGreaterThanOrEqual.Double.cs" />
+ <Compile Include="CompareNotLessThan.Single.cs" />
+ <Compile Include="CompareNotLessThan.Double.cs" />
+ <Compile Include="CompareNotLessThanOrEqual.Single.cs" />
+ <Compile Include="CompareNotLessThanOrEqual.Double.cs" />
+ <Compile Include="CompareOrdered.Single.cs" />
+ <Compile Include="CompareOrdered.Double.cs" />
+ <Compile Include="CompareUnordered.Single.cs" />
+ <Compile Include="CompareUnordered.Double.cs" />
<Compile Include="Divide.Double.cs" />
<Compile Include="Divide.Single.cs" />
<Compile Include="DuplicateEvenIndexed.Double.cs" />
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareEqualDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareEqualDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareEqualDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareEqualDouble testClass)
+ {
+ var result = Avx.CompareEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareEqualDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareEqualDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareEqualDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareEqual(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareEqual(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareEqualDouble();
+ var result = Avx.CompareEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareEqualDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] == right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareEqual)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareEqualSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareEqualSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareEqualSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareEqualSingle testClass)
+ {
+ var result = Avx.CompareEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareEqualSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareEqualSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareEqualSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareEqual(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareEqual(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareEqualSingle();
+ var result = Avx.CompareEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareEqualSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareEqual(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((left[i] == right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareEqual)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareGreaterThanDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareGreaterThanDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareGreaterThanDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanDouble testClass)
+ {
+ var result = Avx.CompareGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareGreaterThanDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareGreaterThanDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareGreaterThan(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareGreaterThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanDouble();
+ var result = Avx.CompareGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] > right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareGreaterThan)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareGreaterThanSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareGreaterThanSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareGreaterThanSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanSingle testClass)
+ {
+ var result = Avx.CompareGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareGreaterThanSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareGreaterThanSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareGreaterThan(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareGreaterThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanSingle();
+ var result = Avx.CompareGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThan(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((left[i] > right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareGreaterThan)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareGreaterThanOrEqualDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareGreaterThanOrEqualDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanOrEqualDouble testClass)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanOrEqualDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareGreaterThanOrEqualDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareGreaterThanOrEqualDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualDouble();
+ var result = Avx.CompareGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] >= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareGreaterThanOrEqual)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareGreaterThanOrEqualSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareGreaterThanOrEqualSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanOrEqualSingle testClass)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanOrEqualSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareGreaterThanOrEqualSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareGreaterThanOrEqualSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareGreaterThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareGreaterThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualSingle();
+ var result = Avx.CompareGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((left[i] >= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareGreaterThanOrEqual)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareLessThanDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareLessThanDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareLessThanDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanDouble testClass)
+ {
+ var result = Avx.CompareLessThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareLessThanDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareLessThanDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareLessThan(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareLessThan(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareLessThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanDouble();
+ var result = Avx.CompareLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareLessThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] < right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareLessThan)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareLessThanSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareLessThanSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareLessThanSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanSingle testClass)
+ {
+ var result = Avx.CompareLessThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareLessThanSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareLessThanSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareLessThan(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareLessThan(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareLessThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanSingle();
+ var result = Avx.CompareLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareLessThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThan(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((left[i] < right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareLessThan)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareLessThanOrEqualDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareLessThanOrEqualDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareLessThanOrEqualDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanOrEqualDouble testClass)
+ {
+ var result = Avx.CompareLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanOrEqualDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareLessThanOrEqualDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareLessThanOrEqualDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareLessThanOrEqual(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareLessThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanOrEqualDouble();
+ var result = Avx.CompareLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanOrEqualDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] <= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareLessThanOrEqual)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareLessThanOrEqualSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareLessThanOrEqualSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareLessThanOrEqualSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanOrEqualSingle testClass)
+ {
+ var result = Avx.CompareLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanOrEqualSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareLessThanOrEqualSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareLessThanOrEqualSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareLessThanOrEqual(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareLessThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareLessThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanOrEqualSingle();
+ var result = Avx.CompareLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareLessThanOrEqualSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareLessThanOrEqual(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((left[i] <= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareLessThanOrEqual)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotEqualDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotEqualDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotEqualDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotEqualDouble testClass)
+ {
+ var result = Avx.CompareNotEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotEqualDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotEqualDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotEqualDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotEqual(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotEqual(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotEqualDouble();
+ var result = Avx.CompareNotEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotEqualDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] != right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotEqual)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotEqualSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotEqualSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotEqualSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotEqualSingle testClass)
+ {
+ var result = Avx.CompareNotEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotEqualSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotEqualSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotEqualSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotEqual(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotEqual(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotEqualSingle();
+ var result = Avx.CompareNotEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotEqualSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotEqual(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((left[i] != right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotEqual)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotGreaterThanDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotGreaterThanDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanDouble testClass)
+ {
+ var result = Avx.CompareNotGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotGreaterThanDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotGreaterThanDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotGreaterThan(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotGreaterThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanDouble();
+ var result = Avx.CompareNotGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] > right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotGreaterThan)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotGreaterThanSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotGreaterThanSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanSingle testClass)
+ {
+ var result = Avx.CompareNotGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotGreaterThanSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotGreaterThanSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotGreaterThan(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotGreaterThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanSingle();
+ var result = Avx.CompareNotGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotGreaterThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThan(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] > right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotGreaterThan)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotGreaterThanOrEqualDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotGreaterThanOrEqualDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualDouble testClass)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotGreaterThanOrEqualDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotGreaterThanOrEqualDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualDouble();
+ var result = Avx.CompareNotGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] >= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotGreaterThanOrEqual)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotGreaterThanOrEqualSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotGreaterThanOrEqualSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualSingle testClass)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotGreaterThanOrEqualSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotGreaterThanOrEqualSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotGreaterThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotGreaterThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualSingle();
+ var result = Avx.CompareNotGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotGreaterThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotGreaterThanOrEqual(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] >= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotGreaterThanOrEqual)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotLessThanDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotLessThanDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotLessThanDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanDouble testClass)
+ {
+ var result = Avx.CompareNotLessThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotLessThanDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotLessThanDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotLessThan(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThan), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotLessThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanDouble();
+ var result = Avx.CompareNotLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotLessThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] < right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotLessThan)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotLessThanSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotLessThanSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotLessThanSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanSingle testClass)
+ {
+ var result = Avx.CompareNotLessThan(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotLessThanSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotLessThanSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotLessThan(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThan), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotLessThan(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThan(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanSingle();
+ var result = Avx.CompareNotLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotLessThan(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThan(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThan(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] < right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotLessThan)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotLessThanOrEqualDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotLessThanOrEqualDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanOrEqualDouble testClass)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanOrEqualDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotLessThanOrEqualDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotLessThanOrEqualDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThanOrEqual), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualDouble();
+ var result = Avx.CompareNotLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] <= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotLessThanOrEqual)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareNotLessThanOrEqualSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareNotLessThanOrEqualSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanOrEqualSingle testClass)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanOrEqualSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareNotLessThanOrEqualSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareNotLessThanOrEqualSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareNotLessThanOrEqual), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareNotLessThanOrEqual(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareNotLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareNotLessThanOrEqual(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualSingle();
+ var result = Avx.CompareNotLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareNotLessThanOrEqual(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThanOrEqual(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareNotLessThanOrEqual(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] <= right[i]) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareNotLessThanOrEqual)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareOrderedDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareOrderedDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareOrderedDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareOrderedDouble testClass)
+ {
+ var result = Avx.CompareOrdered(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareOrderedDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareOrderedDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareOrderedDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareOrdered(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareOrdered(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareOrdered), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareOrdered), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareOrdered), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareOrdered(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareOrdered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareOrdered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareOrdered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareOrderedDouble();
+ var result = Avx.CompareOrdered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareOrderedDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareOrdered(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareOrdered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((!double.IsNaN(left[0]) && !double.IsNaN(right[0])) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((!double.IsNaN(left[i]) && !double.IsNaN(right[i])) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareOrdered)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareOrderedSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareOrderedSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareOrderedSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareOrderedSingle testClass)
+ {
+ var result = Avx.CompareOrdered(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareOrderedSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareOrderedSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareOrderedSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareOrdered(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareOrdered(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareOrdered), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareOrdered), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareOrdered), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareOrdered(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareOrdered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareOrdered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareOrdered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareOrderedSingle();
+ var result = Avx.CompareOrdered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareOrderedSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareOrdered(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareOrdered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareOrdered(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((!float.IsNaN(left[0]) && !float.IsNaN(right[0])) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((!float.IsNaN(left[i]) && !float.IsNaN(right[i])) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareOrdered)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareUnorderedDouble()
+ {
+ var test = new SimpleBinaryOpTest__CompareUnorderedDouble();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareUnorderedDouble
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Double> _fld1;
+ public Vector256<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareUnorderedDouble testClass)
+ {
+ var result = Avx.CompareUnordered(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareUnorderedDouble testClass)
+ {
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector256<Double> _clsVar1;
+ private static Vector256<Double> _clsVar2;
+
+ private Vector256<Double> _fld1;
+ private Vector256<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareUnorderedDouble()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ }
+
+ public SimpleBinaryOpTest__CompareUnorderedDouble()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareUnordered(
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareUnordered(
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareUnordered), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareUnordered), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareUnordered), new Type[] { typeof(Vector256<Double>), typeof(Vector256<Double>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareUnordered(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Double*)(pClsVar1)),
+ Avx.LoadVector256((Double*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareUnordered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareUnordered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareUnordered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareUnorderedDouble();
+ var result = Avx.CompareUnordered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareUnorderedDouble();
+
+ fixed (Vector256<Double>* pFld1 = &test._fld1)
+ fixed (Vector256<Double>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareUnordered(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Double>* pFld1 = &_fld1)
+ fixed (Vector256<Double>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Double*)(pFld1)),
+ Avx.LoadVector256((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareUnordered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Double*)(&test._fld1)),
+ Avx.LoadVector256((Double*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Double> op1, Vector256<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(result[0]) != ((double.IsNaN(left[0]) || double.IsNaN(right[0])) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != ((double.IsNaN(left[i]) || double.IsNaN(right[i])) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareUnordered)}<Double>(Vector256<Double>, Vector256<Double>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void CompareUnorderedSingle()
+ {
+ var test = new SimpleBinaryOpTest__CompareUnorderedSingle();
+
+ 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();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // 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 class works
+ test.RunClassLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (Avx.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ 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__CompareUnorderedSingle
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ if ((alignment != 32 && alignment != 16) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector256<Single> _fld1;
+ public Vector256<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__CompareUnorderedSingle testClass)
+ {
+ var result = Avx.CompareUnordered(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareUnorderedSingle testClass)
+ {
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 32;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector256<Single> _clsVar1;
+ private static Vector256<Single> _clsVar2;
+
+ private Vector256<Single> _fld1;
+ private Vector256<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__CompareUnorderedSingle()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ }
+
+ public SimpleBinaryOpTest__CompareUnorderedSingle()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => Avx.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Avx.CompareUnordered(
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+ var result = Avx.CompareUnordered(
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareUnordered), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareUnordered), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+ var result = typeof(Avx).GetMethod(nameof(Avx.CompareUnordered), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>) })
+ .Invoke(null, new object[] {
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
+ Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Avx.CompareUnordered(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector256<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector256<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Single*)(pClsVar1)),
+ Avx.LoadVector256((Single*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+ var result = Avx.CompareUnordered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareUnordered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+ var op1 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
+ var op2 = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
+ var result = Avx.CompareUnordered(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__CompareUnorderedSingle();
+ var result = Avx.CompareUnordered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__CompareUnorderedSingle();
+
+ fixed (Vector256<Single>* pFld1 = &test._fld1)
+ fixed (Vector256<Single>* pFld2 = &test._fld2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Avx.CompareUnordered(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector256<Single>* pFld1 = &_fld1)
+ fixed (Vector256<Single>* pFld2 = &_fld2)
+ {
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Single*)(pFld1)),
+ Avx.LoadVector256((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareUnordered(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = Avx.CompareUnordered(
+ Avx.LoadVector256((Single*)(&test._fld1)),
+ Avx.LoadVector256((Single*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector256<Single> op1, Vector256<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, 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<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector256<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(result[0]) != ((float.IsNaN(left[0]) || float.IsNaN(right[0])) ? -1 : 0))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != ((float.IsNaN(left[i]) || float.IsNaN(right[i])) ? -1 : 0))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Avx)}.{nameof(Avx.CompareUnordered)}<Single>(Vector256<Single>, Vector256<Single>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
["BroadcastScalarToVector256.Double"] = BroadcastScalarToVector256Double,
["BroadcastVector128ToVector256.Single"] = BroadcastVector128ToVector256Single,
["BroadcastVector128ToVector256.Double"] = BroadcastVector128ToVector256Double,
+ ["CompareEqual.Single"] = CompareEqualSingle,
+ ["CompareEqual.Double"] = CompareEqualDouble,
+ ["CompareGreaterThan.Single"] = CompareGreaterThanSingle,
+ ["CompareGreaterThan.Double"] = CompareGreaterThanDouble,
+ ["CompareGreaterThanOrEqual.Single"] = CompareGreaterThanOrEqualSingle,
+ ["CompareGreaterThanOrEqual.Double"] = CompareGreaterThanOrEqualDouble,
+ ["CompareLessThan.Single"] = CompareLessThanSingle,
+ ["CompareLessThan.Double"] = CompareLessThanDouble,
+ ["CompareLessThanOrEqual.Single"] = CompareLessThanOrEqualSingle,
+ ["CompareLessThanOrEqual.Double"] = CompareLessThanOrEqualDouble,
+ ["CompareNotEqual.Single"] = CompareNotEqualSingle,
+ ["CompareNotEqual.Double"] = CompareNotEqualDouble,
+ ["CompareNotGreaterThan.Single"] = CompareNotGreaterThanSingle,
+ ["CompareNotGreaterThan.Double"] = CompareNotGreaterThanDouble,
+ ["CompareNotGreaterThanOrEqual.Single"] = CompareNotGreaterThanOrEqualSingle,
+ ["CompareNotGreaterThanOrEqual.Double"] = CompareNotGreaterThanOrEqualDouble,
+ ["CompareNotLessThan.Single"] = CompareNotLessThanSingle,
+ ["CompareNotLessThan.Double"] = CompareNotLessThanDouble,
+ ["CompareNotLessThanOrEqual.Single"] = CompareNotLessThanOrEqualSingle,
+ ["CompareNotLessThanOrEqual.Double"] = CompareNotLessThanOrEqualDouble,
+ ["CompareOrdered.Single"] = CompareOrderedSingle,
+ ["CompareOrdered.Double"] = CompareOrderedDouble,
+ ["CompareUnordered.Single"] = CompareUnorderedSingle,
+ ["CompareUnordered.Double"] = CompareUnorderedDouble,
["Ceiling.Double"] = CeilingDouble,
["Ceiling.Single"] = CeilingSingle,
["Divide.Double"] = DivideDouble,
("LoadUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["Method"] = "BroadcastVector128ToVector256",["RetVectorType"]="Vector256",["RetBaseType"]= "Double",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (i < 2 ? BitConverter.DoubleToInt64Bits(firstOp[i]) : BitConverter.DoubleToInt64Bits(firstOp[i-2]))"}),
("SimpleUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Ceiling", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Ceiling(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(Math.Ceiling(firstOp[i]))"}),
("SimpleUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Ceiling", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Ceiling(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(MathF.Ceiling(firstOp[i]))"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] == right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] == right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] > right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] > right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] >= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] >= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] < right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] < right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] <= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] <= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] != right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] != right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotGreaterThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] > right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotGreaterThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] > right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotGreaterThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] >= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotGreaterThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] >= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotLessThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] < right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotLessThan", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] < right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotLessThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] <= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareNotLessThanOrEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] <= right[i]) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareOrdered", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((!float.IsNaN(left[0]) && !float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((!float.IsNaN(left[i]) && !float.IsNaN(right[i])) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareOrdered", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((!double.IsNaN(left[0]) && !double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((!double.IsNaN(left[i]) && !double.IsNaN(right[i])) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareUnordered", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((float.IsNaN(left[0]) || float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((float.IsNaN(left[i]) || float.IsNaN(right[i])) ? -1 : 0)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "CompareUnordered", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((double.IsNaN(left[0]) || double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((double.IsNaN(left[i]) || double.IsNaN(right[i])) ? -1 : 0)"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Divide", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0] / right[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i] / right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Divide", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[0] / right[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i] / right[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
("SimpleUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(i % 2 == 0) ? (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) : (BitConverter.DoubleToInt64Bits(firstOp[i - 1]) != BitConverter.DoubleToInt64Bits(result[i]))"}),
/// </summary>
public static Vector256<double> Compare(Vector256<double> left, Vector256<double> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_cmpeq_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(0)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareEqual(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpeq_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(0)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareEqual(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpgt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(14)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareGreaterThan(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpgt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(14)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareGreaterThan(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpge_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(13)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareGreaterThanOrEqual(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpge_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(13)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareGreaterThanOrEqual(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmplt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(1)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareLessThan(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmplt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(1)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareLessThan(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmple_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(2)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareLessThanOrEqual(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmple_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(2)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareLessThanOrEqual(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpneq_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotEqual(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpneq_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotEqual(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpngt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotGreaterThan(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpngt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotGreaterThan(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpnge_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotGreaterThanOrEqual(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpnge_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotGreaterThanOrEqual(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpnlt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(5)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotLessThan(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpnlt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(5)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotLessThan(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpnle_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(6)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotLessThanOrEqual(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpnle_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(6)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotLessThanOrEqual(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_cmpord_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(7)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareOrdered(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpord_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(7)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareOrdered(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
/// <summary>
/// __m128d _mm_cmp_sd (__m128d a, __m128d b, const int imm8)
/// VCMPSS xmm, xmm, xmm/m32, imm8
/// </summary>
public static Vector128<float> CompareScalar(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_cmpunord_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(3)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareUnordered(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmpunord_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(3)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareUnordered(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
/// <summary>
/// __m128i _mm256_cvtpd_epi32 (__m256d a)
/// VCVTPD2DQ xmm, ymm/m256
/// </summary>
public static Vector256<double> Compare(Vector256<double> left, Vector256<double> right, FloatComparisonMode mode) => Compare(left, right, mode);
+ /// <summary>
+ /// __m256 _mm256_cmpeq_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(0)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareEqual(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.OrderedEqualNonSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpeq_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(0)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareEqual(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.OrderedEqualNonSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpgt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(14)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareGreaterThan(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.OrderedGreaterThanSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpgt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(14)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareGreaterThan(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.OrderedGreaterThanSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpge_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(13)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareGreaterThanOrEqual(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.OrderedGreaterThanOrEqualSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpge_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(13)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareGreaterThanOrEqual(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.OrderedGreaterThanOrEqualSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmplt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(1)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareLessThan(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.OrderedLessThanSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmplt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(1)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareLessThan(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.OrderedLessThanSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmple_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(2)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareLessThanOrEqual(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.OrderedLessThanOrEqualSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmple_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(2)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareLessThanOrEqual(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.OrderedLessThanOrEqualSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpneq_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotEqual(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.UnorderedNotEqualNonSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpneq_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotEqual(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.UnorderedNotEqualNonSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpngt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotGreaterThan(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.UnorderedNotGreaterThanSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpngt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotGreaterThan(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.UnorderedNotGreaterThanSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpnge_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotGreaterThanOrEqual(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.UnorderedNotGreaterThanOrEqualSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpnge_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotGreaterThanOrEqual(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.UnorderedNotGreaterThanOrEqualSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpnlt_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(5)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotLessThan(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.UnorderedNotLessThanSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpnlt_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(5)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotLessThan(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.UnorderedNotLessThanSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpnle_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(6)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareNotLessThanOrEqual(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.UnorderedNotLessThanOrEqualSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpnle_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(6)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareNotLessThanOrEqual(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.UnorderedNotLessThanOrEqualSignaling);
+
+ /// <summary>
+ /// __m256 _mm256_cmpord_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(7)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareOrdered(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.OrderedNonSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpord_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(7)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareOrdered(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.OrderedNonSignaling);
+
/// <summary>
/// __m128d _mm_cmp_sd (__m128d a, __m128d b, const int imm8)
/// VCMPSS xmm, xmm, xmm/m32, imm8
/// </summary>
public static Vector128<float> CompareScalar(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) => CompareScalar(left, right, mode);
+ /// <summary>
+ /// __m256 _mm256_cmpunord_ps (__m256 a, __m256 b)
+ /// CMPPS ymm, ymm/m256, imm8(3)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<float> CompareUnordered(Vector256<float> left, Vector256<float> right) => Compare(left, right, FloatComparisonMode.UnorderedNonSignaling);
+ /// <summary>
+ /// __m256d _mm256_cmpunord_pd (__m256d a, __m256d b)
+ /// CMPPD ymm, ymm/m256, imm8(3)
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static Vector256<double> CompareUnordered(Vector256<double> left, Vector256<double> right) => Compare(left, right, FloatComparisonMode.UnorderedNonSignaling);
+
/// <summary>
/// __m128i _mm256_cvtpd_epi32 (__m256d a)
/// VCVTPD2DQ xmm, ymm/m256
public static System.Runtime.Intrinsics.Vector128<float> Compare(System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right, System.Runtime.Intrinsics.X86.FloatComparisonMode mode) { throw null; }
public static System.Runtime.Intrinsics.Vector256<double> Compare(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right, System.Runtime.Intrinsics.X86.FloatComparisonMode mode) { throw null; }
public static System.Runtime.Intrinsics.Vector256<float> Compare(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right, System.Runtime.Intrinsics.X86.FloatComparisonMode mode) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareEqual(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareEqual(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareGreaterThan(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareGreaterThan(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareGreaterThanOrEqual(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareGreaterThanOrEqual(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareLessThan(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareLessThan(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareLessThanOrEqual(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareLessThanOrEqual(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareNotEqual(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareNotEqual(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareNotGreaterThan(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareNotGreaterThan(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareNotGreaterThanOrEqual(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareNotGreaterThanOrEqual(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareNotLessThan(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareNotLessThan(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareNotLessThanOrEqual(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareNotLessThanOrEqual(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareOrdered(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareOrdered(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> CompareScalar(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right, System.Runtime.Intrinsics.X86.FloatComparisonMode mode) { throw null; }
public static System.Runtime.Intrinsics.Vector128<float> CompareScalar(System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right, System.Runtime.Intrinsics.X86.FloatComparisonMode mode) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<double> CompareUnordered(System.Runtime.Intrinsics.Vector256<double> left, System.Runtime.Intrinsics.Vector256<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector256<float> CompareUnordered(System.Runtime.Intrinsics.Vector256<float> left, System.Runtime.Intrinsics.Vector256<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<int> ConvertToVector128Int32(System.Runtime.Intrinsics.Vector256<double> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<int> ConvertToVector128Int32WithTruncation(System.Runtime.Intrinsics.Vector256<double> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<float> ConvertToVector128Single(System.Runtime.Intrinsics.Vector256<double> value) { throw null; }