Updating the Avx HardwareIntrinsic tests to be generated from a template.
authorTanner Gooding <tagoo@outlook.com>
Sat, 27 Jan 2018 23:14:22 +0000 (15:14 -0800)
committerTanner Gooding <tagoo@outlook.com>
Sun, 28 Jan 2018 01:56:38 +0000 (17:56 -0800)
12 files changed:
tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.Double.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.Single.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.cs [deleted file]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_r.csproj [moved from tests/src/JIT/HardwareIntrinsics/X86/Avx/Add_r.csproj with 84% similarity]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Avx_ro.csproj [moved from tests/src/JIT/HardwareIntrinsics/X86/Avx/Add_ro.csproj with 84% similarity]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.Double.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.Single.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.cs [deleted file]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply_r.csproj [deleted file]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply_ro.csproj [deleted file]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx

diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.Double.cs
new file mode 100644 (file)
index 0000000..ea22687
--- /dev/null
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.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 AddDouble()
+        {
+            var test = new SimpleBinaryOpTest__AddDouble();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works
+                test.RunBasicScenario();
+
+                // Validates calling via reflection works
+                test.RunReflectionScenario();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works
+                test.RunLclVarScenario();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class SimpleBinaryOpTest__AddDouble
+    {
+        private const int VectorSize = 32;
+        private const int ElementCount = VectorSize / sizeof(Double);
+
+        private static Double[] _data1 = new Double[ElementCount];
+        private static Double[] _data2 = new Double[ElementCount];
+
+        private static Vector256<Double> _clsVar1;
+        private static Vector256<Double> _clsVar2;
+
+        private Vector256<Double> _fld1;
+        private Vector256<Double> _fld2;
+
+        private SimpleBinaryOpTest__DataTable<Double> _dataTable;
+
+        static SimpleBinaryOpTest__AddDouble()
+        {
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+        }
+
+        public SimpleBinaryOpTest__AddDouble()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+            _dataTable = new SimpleBinaryOpTest__DataTable<Double>(_data1, _data2, new Double[ElementCount]);
+        }
+
+        public bool IsSupported => Avx.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario()
+        {
+            var result = Avx.Add(
+                Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+                Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunReflectionScenario()
+        {
+            var result = typeof(Avx).GetMethod(nameof(Avx.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Avx.Add(
+                _clsVar1,
+                _clsVar2
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+        }
+
+        public void RunLclVarScenario()
+        {
+            var left = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+            var right = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+            var result = Avx.Add(left, right);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(left, right, _dataTable.outArray);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new SimpleBinaryOpTest__AddDouble();
+            var result = Avx.Add(test._fld1, test._fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Avx.Add(_fld1, _fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_fld1, _fld2, _dataTable.outArray);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(Vector256<Double> left, Vector256<Double> right, Double[] result, [CallerMemberName] string method = "")
+        {
+            Double[] inArray1 = new Double[ElementCount];
+            Double[] inArray2 = new Double[ElementCount];
+
+            Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+            Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+            ValidateResult(inArray1, inArray2, result, method);
+        }
+
+        private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+        {
+            if (BitConverter.DoubleToInt64Bits(left[0] + right[0]) != BitConverter.DoubleToInt64Bits(result[0]))
+            {
+                Succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < left.Length; i++)
+                {
+                    if (BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i]))
+                    {
+                        Succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!Succeeded)
+            {
+                Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Add)}<Double>: {method} failed:");
+                Console.WriteLine($"    left: ({string.Join(", ", left)})");
+                Console.WriteLine($"   right: ({string.Join(", ", right)})");
+                Console.WriteLine($"  result: ({string.Join(", ", result)})");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.Single.cs
new file mode 100644 (file)
index 0000000..1534cbb
--- /dev/null
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.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 AddSingle()
+        {
+            var test = new SimpleBinaryOpTest__AddSingle();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works
+                test.RunBasicScenario();
+
+                // Validates calling via reflection works
+                test.RunReflectionScenario();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works
+                test.RunLclVarScenario();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class SimpleBinaryOpTest__AddSingle
+    {
+        private const int VectorSize = 32;
+        private const int ElementCount = VectorSize / sizeof(Single);
+
+        private static Single[] _data1 = new Single[ElementCount];
+        private static Single[] _data2 = new Single[ElementCount];
+
+        private static Vector256<Single> _clsVar1;
+        private static Vector256<Single> _clsVar2;
+
+        private Vector256<Single> _fld1;
+        private Vector256<Single> _fld2;
+
+        private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+        static SimpleBinaryOpTest__AddSingle()
+        {
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+        }
+
+        public SimpleBinaryOpTest__AddSingle()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+            _dataTable = new SimpleBinaryOpTest__DataTable<Single>(_data1, _data2, new Single[ElementCount]);
+        }
+
+        public bool IsSupported => Avx.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario()
+        {
+            var result = Avx.Add(
+                Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+                Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunReflectionScenario()
+        {
+            var result = typeof(Avx).GetMethod(nameof(Avx.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Avx.Add(
+                _clsVar1,
+                _clsVar2
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+        }
+
+        public void RunLclVarScenario()
+        {
+            var left = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+            var right = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+            var result = Avx.Add(left, right);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(left, right, _dataTable.outArray);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new SimpleBinaryOpTest__AddSingle();
+            var result = Avx.Add(test._fld1, test._fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Avx.Add(_fld1, _fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_fld1, _fld2, _dataTable.outArray);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(Vector256<Single> left, Vector256<Single> right, Single[] result, [CallerMemberName] string method = "")
+        {
+            Single[] inArray1 = new Single[ElementCount];
+            Single[] inArray2 = new Single[ElementCount];
+
+            Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+            Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+            ValidateResult(inArray1, inArray2, result, method);
+        }
+
+        private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+        {
+            if (BitConverter.SingleToInt32Bits(left[0] + right[0]) != BitConverter.SingleToInt32Bits(result[0]))
+            {
+                Succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < left.Length; i++)
+                {
+                    if (BitConverter.SingleToInt32Bits(left[i] + right[i]) != BitConverter.SingleToInt32Bits(result[i]))
+                    {
+                        Succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!Succeeded)
+            {
+                Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Add)}<Single>: {method} failed:");
+                Console.WriteLine($"    left: ({string.Join(", ", left)})");
+                Console.WriteLine($"   right: ({string.Join(", ", right)})");
+                Console.WriteLine($"  result: ({string.Join(", ", result)})");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Add.cs
deleted file mode 100644 (file)
index 47624a0..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-//
-
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics.X86;
-using System.Runtime.Intrinsics;
-
-namespace IntelHardwareIntrinsicTest
-{
-    class Program
-    {
-        const int Pass = 100;
-        const int Fail = 0;
-
-        static unsafe int Main(string[] args)
-        {
-            int testResult = Pass;
-
-            if (Avx.IsSupported)
-            {
-                using (TestTable<float> floatTable = new TestTable<float>(new float[8] { 1, -5, 100, 0, 1, -5, 100, 0 }, new float[8] { 22, -1, -50, 0, 22, -1, -50, 0 }, new float[8]))
-                using (TestTable<double> doubleTable = new TestTable<double>(new double[4] { 1, -5, 100, 0 }, new double[4] { 22, -1, -50, 0 }, new double[4]))
-                {
-                    var vf1 = Unsafe.Read<Vector256<float>>(floatTable.inArray1Ptr);
-                    var vf2 = Unsafe.Read<Vector256<float>>(floatTable.inArray2Ptr);
-                    var vf3 = Avx.Add(vf1, vf2);
-                    Unsafe.Write(floatTable.outArrayPtr, vf3);
-
-                    if (!floatTable.CheckResult((x, y, z) => x + y == z))
-                    {
-                        Console.WriteLine("AVX Add failed on float:");
-                        foreach (var item in floatTable.outArray)
-                        {
-                            Console.Write(item + ", ");
-                        }
-                        Console.WriteLine();
-                        testResult = Fail;
-                    }
-
-                    vf3 = (Vector256<float>)typeof(Avx).GetMethod(nameof(Avx.Add), new Type[] { vf1.GetType(), vf2.GetType() }).Invoke(null, new object[] { vf1, vf2 });
-                    Unsafe.Write(floatTable.outArrayPtr, vf3);
-
-                    if (!floatTable.CheckResult((x, y, z) => x + y == z))
-                    {
-                        Console.WriteLine("AVX Add failed via reflection on float:");
-                        foreach (var item in floatTable.outArray)
-                        {
-                            Console.Write(item + ", ");
-                        }
-                        Console.WriteLine();
-                        testResult = Fail;
-                    }
-
-                    var vd1 = Unsafe.Read<Vector256<double>>(doubleTable.inArray1Ptr);
-                    var vd2 = Unsafe.Read<Vector256<double>>(doubleTable.inArray2Ptr);
-                    var vd3 = Avx.Add(vd1, vd2);
-                    Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
-                    if (!doubleTable.CheckResult((x, y, z) => x + y == z))
-                    {
-                        Console.WriteLine("AVX Add failed on double:");
-                        foreach (var item in doubleTable.outArray)
-                        {
-                            Console.Write(item + ", ");
-                        }
-                        Console.WriteLine();
-                        testResult = Fail;
-                    }
-
-                    vd3 = (Vector256<double>)typeof(Avx).GetMethod(nameof(Avx.Add), new Type[] { vd1.GetType(), vd2.GetType() }).Invoke(null, new object[] { vd1, vd2 });
-                    Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
-                    if (!doubleTable.CheckResult((x, y, z) => x + y == z))
-                    {
-                        Console.WriteLine("AVX Add failed via reflection on double:");
-                        foreach (var item in doubleTable.outArray)
-                        {
-                            Console.Write(item + ", ");
-                        }
-                        Console.WriteLine();
-                        testResult = Fail;
-                    }
-                }
-            }
-
-            return testResult;
-        }
-
-        public unsafe struct TestTable<T> : IDisposable where T : struct
-        {
-            public T[] inArray1;
-            public T[] inArray2;
-            public T[] outArray;
-
-            public void* inArray1Ptr => inHandle1.AddrOfPinnedObject().ToPointer();
-            public void* inArray2Ptr => inHandle2.AddrOfPinnedObject().ToPointer();
-            public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
-
-            GCHandle inHandle1;
-            GCHandle inHandle2;
-            GCHandle outHandle;
-            public TestTable(T[] a, T[] b, T[] c)
-            {
-                this.inArray1 = a;
-                this.inArray2 = b;
-                this.outArray = c;
-
-                inHandle1 = GCHandle.Alloc(inArray1, GCHandleType.Pinned);
-                inHandle2 = GCHandle.Alloc(inArray2, GCHandleType.Pinned);
-                outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
-            }
-            public bool CheckResult(Func<T, T, T, bool> check)
-            {
-                for (int i = 0; i < inArray1.Length; i++)
-                {
-                    if (!check(inArray1[i], inArray2[i], outArray[i]))
-                    {
-                        return false;
-                    }
-                }
-                return true;
-            }
-
-            public void Dispose()
-            {
-                inHandle1.Free();
-                inHandle2.Free();
-                outHandle.Free();
-            }
-        }
-
-    }
-}
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="Add.cs" />
+    <Compile Include="Add.Double.cs" />
+    <Compile Include="Add.Single.cs" />
+    <Compile Include="Multiply.Double.cs" />
+    <Compile Include="Multiply.Single.cs" />
+    <Compile Include="Program.Avx.cs" />
+    <Compile Include="..\Shared\Program.cs" />
+    <Compile Include="..\Shared\SimpleBinOpTest_DataTable.cs" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
   <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="Add.cs" />
+    <Compile Include="Add.Double.cs" />
+    <Compile Include="Add.Single.cs" />
+    <Compile Include="Multiply.Double.cs" />
+    <Compile Include="Multiply.Single.cs" />
+    <Compile Include="Program.Avx.cs" />
+    <Compile Include="..\Shared\Program.cs" />
+    <Compile Include="..\Shared\SimpleBinOpTest_DataTable.cs" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
   <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.Double.cs
new file mode 100644 (file)
index 0000000..6da0feb
--- /dev/null
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.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 MultiplyDouble()
+        {
+            var test = new SimpleBinaryOpTest__MultiplyDouble();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works
+                test.RunBasicScenario();
+
+                // Validates calling via reflection works
+                test.RunReflectionScenario();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works
+                test.RunLclVarScenario();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class SimpleBinaryOpTest__MultiplyDouble
+    {
+        private const int VectorSize = 32;
+        private const int ElementCount = VectorSize / sizeof(Double);
+
+        private static Double[] _data1 = new Double[ElementCount];
+        private static Double[] _data2 = new Double[ElementCount];
+
+        private static Vector256<Double> _clsVar1;
+        private static Vector256<Double> _clsVar2;
+
+        private Vector256<Double> _fld1;
+        private Vector256<Double> _fld2;
+
+        private SimpleBinaryOpTest__DataTable<Double> _dataTable;
+
+        static SimpleBinaryOpTest__MultiplyDouble()
+        {
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+        }
+
+        public SimpleBinaryOpTest__MultiplyDouble()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+            _dataTable = new SimpleBinaryOpTest__DataTable<Double>(_data1, _data2, new Double[ElementCount]);
+        }
+
+        public bool IsSupported => Avx.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario()
+        {
+            var result = Avx.Multiply(
+                Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
+                Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr)
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunReflectionScenario()
+        {
+            var result = typeof(Avx).GetMethod(nameof(Avx.Multiply), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Avx.Multiply(
+                _clsVar1,
+                _clsVar2
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+        }
+
+        public void RunLclVarScenario()
+        {
+            var left = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
+            var right = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
+            var result = Avx.Multiply(left, right);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(left, right, _dataTable.outArray);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new SimpleBinaryOpTest__MultiplyDouble();
+            var result = Avx.Multiply(test._fld1, test._fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Avx.Multiply(_fld1, _fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_fld1, _fld2, _dataTable.outArray);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(Vector256<Double> left, Vector256<Double> right, Double[] result, [CallerMemberName] string method = "")
+        {
+            Double[] inArray1 = new Double[ElementCount];
+            Double[] inArray2 = new Double[ElementCount];
+
+            Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+            Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+            ValidateResult(inArray1, inArray2, result, method);
+        }
+
+        private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+        {
+            if (BitConverter.DoubleToInt64Bits(left[0] * right[0]) != BitConverter.DoubleToInt64Bits(result[0]))
+            {
+                Succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < left.Length; i++)
+                {
+                    if (BitConverter.DoubleToInt64Bits(left[i] * right[i]) != BitConverter.DoubleToInt64Bits(result[i]))
+                    {
+                        Succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!Succeeded)
+            {
+                Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Multiply)}<Double>: {method} failed:");
+                Console.WriteLine($"    left: ({string.Join(", ", left)})");
+                Console.WriteLine($"   right: ({string.Join(", ", right)})");
+                Console.WriteLine($"  result: ({string.Join(", ", result)})");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.Single.cs
new file mode 100644 (file)
index 0000000..167f3e7
--- /dev/null
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.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 MultiplySingle()
+        {
+            var test = new SimpleBinaryOpTest__MultiplySingle();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works
+                test.RunBasicScenario();
+
+                // Validates calling via reflection works
+                test.RunReflectionScenario();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works
+                test.RunLclVarScenario();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class SimpleBinaryOpTest__MultiplySingle
+    {
+        private const int VectorSize = 32;
+        private const int ElementCount = VectorSize / sizeof(Single);
+
+        private static Single[] _data1 = new Single[ElementCount];
+        private static Single[] _data2 = new Single[ElementCount];
+
+        private static Vector256<Single> _clsVar1;
+        private static Vector256<Single> _clsVar2;
+
+        private Vector256<Single> _fld1;
+        private Vector256<Single> _fld2;
+
+        private SimpleBinaryOpTest__DataTable<Single> _dataTable;
+
+        static SimpleBinaryOpTest__MultiplySingle()
+        {
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+        }
+
+        public SimpleBinaryOpTest__MultiplySingle()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), VectorSize);
+            Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), VectorSize);
+
+            for (var i = 0; i < ElementCount; i++) { _data1[i] = (float)(random.NextDouble()); _data2[i] = (float)(random.NextDouble()); }
+            _dataTable = new SimpleBinaryOpTest__DataTable<Single>(_data1, _data2, new Single[ElementCount]);
+        }
+
+        public bool IsSupported => Avx.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario()
+        {
+            var result = Avx.Multiply(
+                Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
+                Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr)
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunReflectionScenario()
+        {
+            var result = typeof(Avx).GetMethod(nameof(Avx.Multiply), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Avx.Multiply(
+                _clsVar1,
+                _clsVar2
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+        }
+
+        public void RunLclVarScenario()
+        {
+            var left = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
+            var right = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
+            var result = Avx.Multiply(left, right);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(left, right, _dataTable.outArray);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new SimpleBinaryOpTest__MultiplySingle();
+            var result = Avx.Multiply(test._fld1, test._fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Avx.Multiply(_fld1, _fld2);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_fld1, _fld2, _dataTable.outArray);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(Vector256<Single> left, Vector256<Single> right, Single[] result, [CallerMemberName] string method = "")
+        {
+            Single[] inArray1 = new Single[ElementCount];
+            Single[] inArray2 = new Single[ElementCount];
+
+            Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+            Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+            ValidateResult(inArray1, inArray2, result, method);
+        }
+
+        private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+        {
+            if (BitConverter.SingleToInt32Bits(left[0] * right[0]) != BitConverter.SingleToInt32Bits(result[0]))
+            {
+                Succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < left.Length; i++)
+                {
+                    if (BitConverter.SingleToInt32Bits(left[i] * right[i]) != BitConverter.SingleToInt32Bits(result[i]))
+                    {
+                        Succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!Succeeded)
+            {
+                Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Multiply)}<Single>: {method} failed:");
+                Console.WriteLine($"    left: ({string.Join(", ", left)})");
+                Console.WriteLine($"   right: ({string.Join(", ", right)})");
+                Console.WriteLine($"  result: ({string.Join(", ", result)})");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply.cs
deleted file mode 100644 (file)
index 2c7bf21..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-//
-
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics.X86;
-using System.Runtime.Intrinsics;
-
-namespace IntelHardwareIntrinsicTest
-{
-    class Program
-    {
-        const int Pass = 100;
-        const int Fail = 0;
-
-        static unsafe int Main(string[] args)
-        {
-            int testResult = Pass;
-
-            if (Avx.IsSupported)
-            {
-                using (TestTable<float, float, float> floatTable = new TestTable<float, float, float>(new float[8] { 1, -5, 100, 0, 1, -5, 100, 0 }, new float[8] { 22, -1, -50, 0, 22, -1, -50, 0 }, new float[8]))
-                using (TestTable<double, double, double> doubleTable = new TestTable<double, double, double>(new double[4] { 1, -5, 100, 0 }, new double[4] { 22, -1, -50, 0 }, new double[4]))
-                {
-                    var vf1 = Unsafe.Read<Vector256<float>>(floatTable.inArray1Ptr);
-                    var vf2 = Unsafe.Read<Vector256<float>>(floatTable.inArray2Ptr);
-                    var vf3 = Avx.Multiply(vf1, vf2);
-                    Unsafe.Write(floatTable.outArrayPtr, vf3);
-
-                    var vd1 = Unsafe.Read<Vector256<double>>(doubleTable.inArray1Ptr);
-                    var vd2 = Unsafe.Read<Vector256<double>>(doubleTable.inArray2Ptr);
-                    var vd3 = Avx.Multiply(vd1, vd2);
-                    Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
-                    if (!floatTable.CheckResult((x, y, z) => x * y == z))
-                    {
-                        Console.WriteLine("AVX Multiply failed on float:");
-                        foreach (var item in floatTable.outArray)
-                        {
-                            Console.Write(item + ", ");
-                        }
-                        Console.WriteLine();
-                        testResult = Fail;
-                    }
-
-                    if (!doubleTable.CheckResult((x, y, z) => x * y == z))
-                    {
-                        Console.WriteLine("AVX Multiply failed on double:");
-                        foreach (var item in doubleTable.outArray)
-                        {
-                            Console.Write(item + ", ");
-                        }
-                        Console.WriteLine();
-                        testResult = Fail;
-                    }
-                }
-            }
-            return testResult;
-        }
-
-        public unsafe struct TestTable<T1, T2, T3> : IDisposable where T1 : struct where T2 : struct where T3 : struct
-        {
-            public T1[] inArray1;
-            public T2[] inArray2;
-            public T3[] outArray;
-
-            public void* inArray1Ptr => inHandle1.AddrOfPinnedObject().ToPointer();
-            public void* inArray2Ptr => inHandle2.AddrOfPinnedObject().ToPointer();
-            public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
-
-            GCHandle inHandle1;
-            GCHandle inHandle2;
-            GCHandle outHandle;
-            public TestTable(T1[] a, T2[] b, T3[] c)
-            {
-                this.inArray1 = a;
-                this.inArray2 = b;
-                this.outArray = c;
-
-                inHandle1 = GCHandle.Alloc(inArray1, GCHandleType.Pinned);
-                inHandle2 = GCHandle.Alloc(inArray2, GCHandleType.Pinned);
-                outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
-            }
-            public bool CheckResult(Func<T1, T2, T3, bool> check)
-            {
-                for (int i = 0; i < inArray1.Length; i++)
-                {
-                    if (!check(inArray1[i], inArray2[i], outArray[i]))
-                    {
-                        return false;
-                    }
-                }
-                return true;
-            }
-
-            public void Dispose()
-            {
-                inHandle1.Free();
-                inHandle2.Free();
-                outHandle.Free();
-            }
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply_r.csproj
deleted file mode 100644 (file)
index 7c151fe..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
-    <OutputType>Exe</OutputType>
-    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
-    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <!-- Default configurations to help VS understand the configurations -->
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
-  <ItemGroup>
-    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
-      <Visible>False</Visible>
-    </CodeAnalysisDependentAssemblyPaths>
-  </ItemGroup>
-  <PropertyGroup>
-    <DebugType>None</DebugType>
-    <Optimize></Optimize>
-  </PropertyGroup>
-  <ItemGroup>
-    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Multiply.cs" />
-  </ItemGroup>
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Multiply_ro.csproj
deleted file mode 100644 (file)
index b6fbea2..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
-    <OutputType>Exe</OutputType>
-    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
-    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <!-- Default configurations to help VS understand the configurations -->
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
-  <ItemGroup>
-    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
-      <Visible>False</Visible>
-    </CodeAnalysisDependentAssemblyPaths>
-  </ItemGroup>
-  <PropertyGroup>
-    <DebugType>None</DebugType>
-    <Optimize>true</Optimize>
-  </PropertyGroup>
-  <ItemGroup>
-    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Multiply.cs" />
-  </ItemGroup>
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Program.Avx.cs
new file mode 100644 (file)
index 0000000..40b6bf2
--- /dev/null
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        static Program()
+        {
+            TestList = new Dictionary<string, Action>() {
+                ["Add.Double"] = AddDouble,
+                ["Add.Single"] = AddSingle,
+                ["Multiply.Double"] = MultiplyDouble,
+                ["Multiply.Single"] = MultiplySingle,
+            };
+        }
+    }
+}
index ea4545a..ab60f27 100644 (file)
@@ -22,6 +22,15 @@ private static readonly (string templateFileName, string[] templateData)[] Sse2I
     ("SimpleBinOpTest.template", new string[] { "Sse2", "Add",  "UInt64", "Vector128", "16",       "(ulong)(random.Next(0, int.MaxValue))",                "(ulong)(left[0] + right[0]) != result[0]",                                                        "(ulong)(left[i] + right[i]) != result[i]"}),
 };
 
+private static readonly (string templateFileName, string[] templateData)[] AvxInputs = new []
+{
+    // TemplateName                             Isa,    Method,     BaseType, VectorType,  VectorSize, NextValue,                      ValidateFirstResult,                                                                               ValidateRemainingResults
+    ("SimpleBinOpTest.template", new string[] { "Avx", "Add",      "Double", "Vector256", "32",       "(double)(random.NextDouble())", "BitConverter.DoubleToInt64Bits(left[0] + right[0]) != BitConverter.DoubleToInt64Bits(result[0])", "BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}),
+    ("SimpleBinOpTest.template", new string[] { "Avx", "Add",      "Single", "Vector256", "32",       "(float)(random.NextDouble())",  "BitConverter.SingleToInt32Bits(left[0] + right[0]) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i] + right[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
+    ("SimpleBinOpTest.template", new string[] { "Avx", "Multiply", "Double", "Vector256", "32",       "(double)(random.NextDouble())", "BitConverter.DoubleToInt64Bits(left[0] * right[0]) != BitConverter.DoubleToInt64Bits(result[0])", "BitConverter.DoubleToInt64Bits(left[i] * right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}),
+    ("SimpleBinOpTest.template", new string[] { "Avx", "Multiply", "Single", "Vector256", "32",       "(float)(random.NextDouble())",  "BitConverter.SingleToInt32Bits(left[0] * right[0]) != BitConverter.SingleToInt32Bits(result[0])", "BitConverter.SingleToInt32Bits(left[i] * right[i]) != BitConverter.SingleToInt32Bits(result[i])"}),
+};
+
 private static void ProcessInputs(string isa, (string templateFileName, string[] templateData)[] inputs)
 {
     var testListFileName = Path.Combine("..", isa, $"Program.{isa}.cs");
@@ -74,3 +83,4 @@ private static void ProcessInput(StreamWriter testListFile, (string templateFile
 }
 
 ProcessInputs("Sse2", Sse2Inputs);
+ProcessInputs("Avx", AvxInputs);