Add test cases for some AVX/AVX2 intrinsics
authorFei Peng <fei.peng@intel.com>
Thu, 8 Feb 2018 23:03:22 +0000 (15:03 -0800)
committerTanner Gooding <tagoo@outlook.com>
Sat, 10 Feb 2018 11:10:39 +0000 (03:10 -0800)
33 files changed:
tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalSubtract.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalSubtract_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalSubtract_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh_ro.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow_ro.csproj [new file with mode: 0644]

diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd.cs
new file mode 100644 (file)
index 0000000..2e6eb87
--- /dev/null
@@ -0,0 +1,110 @@
+// 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] {22, -1, -50, 0, 22, -1, -50, 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.HorizontalAdd(vf1, vf2);
+                    Unsafe.Write(floatTable.outArrayPtr, vf3);
+
+                    if (!floatTable.CheckResult((left, right, result) => 
+                                                              (left[0] + left[1] == result[0]) && (right[0] + right[1]  == result[2]) &&
+                                                              (left[2] + left[3] == result[1]) && (right[2] + right[3]  == result[3]) &&
+                                                              (left[4] + left[5] == result[4]) && (right[4] + right[5]  == result[6]) &&
+                                                              (left[6] + left[7] == result[5]) && (right[6] + right[7]  == result[7])))
+                    {               
+                        Console.WriteLine("Avx HorizontalAdd failed 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.HorizontalAdd(vd1, vd2);
+                    Unsafe.Write(doubleTable.outArrayPtr, vd3);
+
+                    if (!doubleTable.CheckResult((left, right, result) => 
+                                                              (left[0] + left[1] == result[0]) && (right[0] + right[1]  == result[1]) &&
+                                                              (left[2] + left[3] == result[2]) && (right[2] + right[3]  == result[3])))
+                    {
+                        Console.WriteLine("Avx HorizontalAdd failed 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)
+            {
+                return check(inArray1, inArray2, outArray);
+            }
+
+            public void Dispose()
+            {
+                inHandle1.Free();
+                inHandle2.Free();
+                outHandle.Free();
+            }
+        }
+
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd_r.csproj
new file mode 100644 (file)
index 0000000..f1fe03f
--- /dev/null
@@ -0,0 +1,35 @@
+<?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="HorizontalAdd.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/HorizontalAdd_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalAdd_ro.csproj
new file mode 100644 (file)
index 0000000..56f3eda
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="HorizontalAdd.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/HorizontalSubtract.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalSubtract.cs
new file mode 100644 (file)
index 0000000..6bf84a6
--- /dev/null
@@ -0,0 +1,110 @@
+// 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] {22, -1, -50, 0, 22, -1, -50, 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.HorizontalSubtract(vf1, vf2);
+                    Unsafe.Write(floatTable.outArrayPtr, vf3);
+
+                    if (!floatTable.CheckResult((left, right, result) => 
+                                                              (left[0] - left[1] == result[0]) && (right[0] - right[1]  == result[2]) &&
+                                                              (left[2] - left[3] == result[1]) && (right[2] - right[3]  == result[3]) &&
+                                                              (left[4] - left[5] == result[4]) && (right[4] - right[5]  == result[6]) &&
+                                                              (left[6] - left[7] == result[5]) && (right[6] - right[7]  == result[7])))
+                    {               
+                        Console.WriteLine("Avx HorizontalAdd failed 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.HorizontalSubtract(vd1, vd2);
+                    Unsafe.Write(doubleTable.outArrayPtr, vd3);
+
+                    if (!doubleTable.CheckResult((left, right, result) => 
+                                                              (left[0] - left[1] == result[0]) && (right[0] - right[1]  == result[1]) &&
+                                                              (left[2] - left[3] == result[2]) && (right[2] - right[3]  == result[3])))
+                    {
+                        Console.WriteLine("Avx HorizontalAdd failed 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)
+            {
+                return check(inArray1, inArray2, outArray);
+            }
+
+            public void Dispose()
+            {
+                inHandle1.Free();
+                inHandle2.Free();
+                outHandle.Free();
+            }
+        }
+
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalSubtract_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalSubtract_r.csproj
new file mode 100644 (file)
index 0000000..8dccc36
--- /dev/null
@@ -0,0 +1,35 @@
+<?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="HorizontalSubtract.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/HorizontalSubtract_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/HorizontalSubtract_ro.csproj
new file mode 100644 (file)
index 0000000..2480b78
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="HorizontalSubtract.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/Sqrt.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt.cs
new file mode 100644 (file)
index 0000000..8171e8d
--- /dev/null
@@ -0,0 +1,111 @@
+// 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]))
+                using (TestTable<double> doubleTable = new TestTable<double>(new double[4] { 1, -5, 100, 0 }, new double[4]))
+                {
+
+                    var vf1 = Unsafe.Read<Vector256<float>>(floatTable.inArrayPtr);
+                    var vf2 = Avx.Sqrt(vf1);
+                    Unsafe.Write(floatTable.outArrayPtr, vf2);
+                    
+                    var vd1 = Unsafe.Read<Vector256<double>>(doubleTable.inArrayPtr);             
+                    var vd2 = Avx.Sqrt(vd1);
+                    Unsafe.Write(doubleTable.outArrayPtr, vd2);
+                    
+                    if (!floatTable.CheckResult((x, y) => {
+                        var expected = MathF.Sqrt(x);
+                        return (expected == y)
+                            || (float.IsNaN(expected) && float.IsNaN(y));
+                    }))
+                    {
+                        Console.WriteLine("Avx Sqrt failed on float:");
+                        foreach (var item in floatTable.outArray)
+                        {
+                            Console.Write(item + ", ");
+                        }
+                        Console.WriteLine();
+                        testResult = Fail;
+                    }
+                    
+                    if (!doubleTable.CheckResult((x, y) => {
+                        var expected = Math.Sqrt(x);
+                        return (expected == y)
+                            || (double.IsNaN(expected) && double.IsNaN(y));
+                    }))
+                    {
+                        Console.WriteLine("Avx Sqrt failed 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[] inArray;
+            public T[] outArray;
+
+            public void* inArrayPtr => inHandle.AddrOfPinnedObject().ToPointer();
+            public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
+
+            GCHandle inHandle;
+            GCHandle outHandle;
+            public TestTable(T[] a, T[] b)
+            {
+                this.inArray = a;
+                this.outArray = b;
+
+                inHandle = GCHandle.Alloc(inArray, GCHandleType.Pinned);
+                outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
+            }
+            public bool CheckResult(Func<T, T, bool> check)
+            {
+                for (int i = 0; i < inArray.Length; i++)
+                {
+                    if (!check(inArray[i], outArray[i]))
+                    {
+                        return false;
+                    }
+                }
+                return true;
+            }
+
+            public void Dispose()
+            {
+                inHandle.Free();
+                outHandle.Free();
+            }
+        }
+
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt_r.csproj
new file mode 100644 (file)
index 0000000..453d09d
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="Sqrt.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Sqrt_ro.csproj
new file mode 100644 (file)
index 0000000..0128297
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="Sqrt.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh.cs
new file mode 100644 (file)
index 0000000..dd34eb9
--- /dev/null
@@ -0,0 +1,110 @@
+// 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] {22, -1, -50, 0, 22, -1, -50, 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.UnpackHigh(vf1, vf2);
+                    Unsafe.Write(floatTable.outArrayPtr, vf3);
+
+                    if (!floatTable.CheckResult((left, right, result) => 
+                                                              (left[2] == result[0]) && (right[2] == result[1]) &&
+                                                              (left[3] == result[2]) && (right[3] == result[3]) &&
+                                                              (left[6] == result[4]) && (right[6] == result[5]) &&
+                                                              (left[7] == result[6]) && (right[7] == result[7])))
+                    {               
+                        Console.WriteLine("Avx UnpackHigh failed 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.UnpackHigh(vd1, vd2);
+                    Unsafe.Write(doubleTable.outArrayPtr, vd3);
+
+                    if (!doubleTable.CheckResult((left, right, result) => 
+                                                              (left[1] == result[0]) && (right[1] == result[1]) &&
+                                                              (left[3] == result[2]) && (right[3] == result[3])))
+                    {
+                        Console.WriteLine("Avx UnpackHigh failed 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)
+            {
+                return check(inArray1, inArray2, outArray);
+            }
+
+            public void Dispose()
+            {
+                inHandle1.Free();
+                inHandle2.Free();
+                outHandle.Free();
+            }
+        }
+
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh_r.csproj
new file mode 100644 (file)
index 0000000..16c6d2b
--- /dev/null
@@ -0,0 +1,35 @@
+<?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="UnpackHigh.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackHigh_ro.csproj
new file mode 100644 (file)
index 0000000..412d49b
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="UnpackHigh.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow.cs
new file mode 100644 (file)
index 0000000..013ce56
--- /dev/null
@@ -0,0 +1,110 @@
+// 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] {22, -1, -50, 0, 22, -1, -50, 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.UnpackLow(vf1, vf2);
+                    Unsafe.Write(floatTable.outArrayPtr, vf3);
+
+                    if (!floatTable.CheckResult((left, right, result) => 
+                                                              (left[0] == result[0]) && (right[0] == result[1]) &&
+                                                              (left[1] == result[2]) && (right[1] == result[3]) &&
+                                                              (left[4] == result[4]) && (right[4] == result[5]) &&
+                                                              (left[5] == result[6]) && (right[5] == result[7])))
+                    {               
+                        Console.WriteLine("Avx UnpackLow failed 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.UnpackLow(vd1, vd2);
+                    Unsafe.Write(doubleTable.outArrayPtr, vd3);
+
+                    if (!doubleTable.CheckResult((left, right, result) => 
+                                                              (left[0] == result[0]) && (right[0] == result[1]) &&
+                                                              (left[2] == result[2]) && (right[2] == result[3])))
+                    {
+                        Console.WriteLine("Avx UnpackLow failed 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)
+            {
+                return check(inArray1, inArray2, outArray);
+            }
+
+            public void Dispose()
+            {
+                inHandle1.Free();
+                inHandle2.Free();
+                outHandle.Free();
+            }
+        }
+
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow_r.csproj
new file mode 100644 (file)
index 0000000..1f2c258
--- /dev/null
@@ -0,0 +1,35 @@
+<?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="UnpackLow.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx/UnpackLow_ro.csproj
new file mode 100644 (file)
index 0000000..182821d
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="UnpackLow.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate.cs
new file mode 100644 (file)
index 0000000..95433b4
--- /dev/null
@@ -0,0 +1,161 @@
+// 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 (Avx2.IsSupported)
+            {
+                using (TestTable<byte, byte, byte> byteTable = new TestTable<byte, byte, byte>(new byte[32] { 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0 }, new byte[32] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new byte[32]))
+                using (TestTable<sbyte, sbyte, sbyte> sbyteTable = new TestTable<sbyte, sbyte, sbyte>(new sbyte[32] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new sbyte[32] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0 }, new sbyte[32]))
+                using (TestTable<short, short, short> shortTable = new TestTable<short, short, short>(new short[16] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new short[16] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0}, new short[16]))
+                using (TestTable<ushort, ushort, ushort> ushortTable = new TestTable<ushort, ushort, ushort>(new ushort[16] { 1, 5, 100, 0, 1, 5, 100, 0,  1, 5, 100, 0, 1, 5, 100, 0 }, new ushort[16] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new ushort[16]))
+                {
+
+                    var vb1 = Unsafe.Read<Vector256<byte>>(byteTable.inArray1Ptr);
+                    var vb2 = Unsafe.Read<Vector256<byte>>(byteTable.inArray2Ptr);
+                    var vb3 = Avx2.AddSaturate(vb1, vb2);
+                    Unsafe.Write(byteTable.outArrayPtr, vb3);
+
+                    var vsb1 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray1Ptr);
+                    var vsb2 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray2Ptr);
+                    var vsb3 = Avx2.AddSaturate(vsb1, vsb2);
+                    Unsafe.Write(sbyteTable.outArrayPtr, vsb3);
+
+                    var vs1 = Unsafe.Read<Vector256<short>>(shortTable.inArray1Ptr);
+                    var vs2 = Unsafe.Read<Vector256<short>>(shortTable.inArray2Ptr);
+                    var vs3 = Avx2.AddSaturate(vs1, vs2);
+                    Unsafe.Write(shortTable.outArrayPtr, vs3);
+
+                    var vus1 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray1Ptr);
+                    var vus2 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray2Ptr);
+                    var vus3 = Avx2.AddSaturate(vus1, vus2);
+                    Unsafe.Write(ushortTable.outArrayPtr, vus3);
+                    
+                    for (int i = 0; i < byteTable.outArray.Length; i++)
+                    {
+                        int value = byteTable.inArray1[i] + byteTable.inArray2[i];
+                        value = Math.Max(value, 0);                        
+                        value = Math.Min(value, byte.MaxValue);
+                        if ((byte)value != byteTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 AddSaturate failed on byte:");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+
+                    for (int i = 0; i < sbyteTable.outArray.Length; i++)
+                    {
+                        int value = sbyteTable.inArray1[i] + sbyteTable.inArray2[i];
+                        value = Math.Max(value, sbyte.MinValue);
+                        value = Math.Min(value, sbyte.MaxValue);
+                        if ((sbyte) value != sbyteTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 AddSaturate failed on sbyte:");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+                    
+                    
+                    for (int i = 0; i < shortTable.outArray.Length; i++)
+                    {
+                        int value = shortTable.inArray1[i] + shortTable.inArray2[i];
+                        value = Math.Max(value, short.MinValue);
+                        value = Math.Min(value, short.MaxValue);
+                        if ((short) value != shortTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 AddSaturate failed on short:");
+                            Console.WriteLine();
+                            
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+                    
+                    for (int i = 0; i < ushortTable.outArray.Length; i++)
+                    {
+                        int value = ushortTable.inArray1[i] + ushortTable.inArray2[i];
+                        value = Math.Max(value, 0);
+                        value = Math.Min(value, ushort.MaxValue);
+                        if ((ushort)value != ushortTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 AddSaturate failed on ushort:");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            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/Avx2/AddSaturate_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate_r.csproj
new file mode 100644 (file)
index 0000000..afe950f
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="AddSaturate.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/AddSaturate_ro.csproj
new file mode 100644 (file)
index 0000000..fc99217
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="AddSaturate.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd.cs
new file mode 100644 (file)
index 0000000..3abe47f
--- /dev/null
@@ -0,0 +1,128 @@
+// 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 (Avx2.IsSupported)
+            {
+                using (TestTable<short, short, short> shortTable = new TestTable<short, short, short>(new short[16] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new short[16] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0}, new short[16]))
+                using (TestTable<int, int, int> intTable = new TestTable<int, int, int>(new int[8] { 1, 5, 100, 0, 1, 5, 100, 0 }, new int[8] { 22, 1, 50, 0, 22, 1, 50, 0 }, new int[8]))
+                {
+                    var vs1 = Unsafe.Read<Vector256<short>>(shortTable.inArray1Ptr);
+                    var vs2 = Unsafe.Read<Vector256<short>>(shortTable.inArray2Ptr);
+                    var vs3 = Avx2.HorizontalAdd(vs1, vs2);
+                    Unsafe.Write(shortTable.outArrayPtr, vs3);
+
+                    var vi1 = Unsafe.Read<Vector256<int>>(intTable.inArray1Ptr);
+                    var vi2 = Unsafe.Read<Vector256<int>>(intTable.inArray2Ptr);
+                    var vi3 = Avx2.HorizontalAdd(vi1, vi2);
+                    Unsafe.Write(intTable.outArrayPtr, vi3);
+                    
+                    if ((shortTable.inArray1[1] + shortTable.inArray1[0] != shortTable.outArray[0]) || 
+                        (shortTable.inArray1[3] + shortTable.inArray1[2] != shortTable.outArray[1]) ||
+                        (shortTable.inArray1[5] + shortTable.inArray1[4] != shortTable.outArray[2]) ||
+                        (shortTable.inArray1[7] + shortTable.inArray1[6] != shortTable.outArray[3]) ||
+                        (shortTable.inArray2[1] + shortTable.inArray2[0] != shortTable.outArray[4]) || 
+                        (shortTable.inArray2[3] + shortTable.inArray2[2] != shortTable.outArray[5]) ||
+                        (shortTable.inArray2[5] + shortTable.inArray2[4] != shortTable.outArray[6]) ||
+                        (shortTable.inArray2[7] + shortTable.inArray2[6] != shortTable.outArray[7]) ||
+                        (shortTable.inArray1[9] + shortTable.inArray1[8] != shortTable.outArray[8]) || 
+                        (shortTable.inArray1[11] + shortTable.inArray1[10] !=shortTable.outArray[9]) ||
+                        (shortTable.inArray1[13] + shortTable.inArray1[12] !=shortTable.outArray[10]) ||
+                        (shortTable.inArray1[15] + shortTable.inArray1[14] !=shortTable.outArray[11]) ||
+                        (shortTable.inArray2[9] + shortTable.inArray2[8]   !=shortTable.outArray[12]) || 
+                        (shortTable.inArray2[11] + shortTable.inArray2[10] !=shortTable.outArray[13]) ||
+                        (shortTable.inArray2[13] + shortTable.inArray2[12] !=shortTable.outArray[14]) ||
+                        (shortTable.inArray2[15] + shortTable.inArray2[14] !=shortTable.outArray[15]))
+                        {
+                            Console.WriteLine("AVX2 HorizontalAdd failed on short:");
+           
+                            testResult = Fail;
+            
+                        }      
+                    
+                    if ((intTable.inArray1[1] + intTable.inArray1[0] != intTable.outArray[0]) || 
+                        (intTable.inArray1[3] + intTable.inArray1[2] != intTable.outArray[1]) ||
+                        (intTable.inArray2[1] + intTable.inArray2[0] != intTable.outArray[2]) ||
+                        (intTable.inArray2[3] + intTable.inArray2[2] != intTable.outArray[3]) ||
+                        (intTable.inArray1[5] + intTable.inArray1[4] != intTable.outArray[4]) || 
+                        (intTable.inArray1[7] + intTable.inArray1[6] != intTable.outArray[5]) ||
+                        (intTable.inArray2[5] + intTable.inArray2[4] != intTable.outArray[6]) ||
+                        (intTable.inArray2[7] + intTable.inArray2[6] != intTable.outArray[7])) 
+
+                        {
+                            Console.WriteLine("AVX2 HorizontalAdd failed on int:");
+           
+                            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/Avx2/HorizontalAdd_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd_r.csproj
new file mode 100644 (file)
index 0000000..553c09f
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="HorizontalAdd.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalAdd_ro.csproj
new file mode 100644 (file)
index 0000000..f7df780
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="HorizontalAdd.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract.cs
new file mode 100644 (file)
index 0000000..2f11be6
--- /dev/null
@@ -0,0 +1,128 @@
+// 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 (Avx2.IsSupported)
+            {
+                using (TestTable<short, short, short> shortTable = new TestTable<short, short, short>(new short[16] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new short[16] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0}, new short[16]))
+                using (TestTable<int, int, int> intTable = new TestTable<int, int, int>(new int[8] { 1, 5, 100, 0, 1, 5, 100, 0 }, new int[8] { 22, 1, 50, 0, 22, 1, 50, 0 }, new int[8]))
+                {
+                    var vs1 = Unsafe.Read<Vector256<short>>(shortTable.inArray1Ptr);
+                    var vs2 = Unsafe.Read<Vector256<short>>(shortTable.inArray2Ptr);
+                    var vs3 = Avx2.HorizontalSubtract(vs1, vs2);
+                    Unsafe.Write(shortTable.outArrayPtr, vs3);
+
+                    var vi1 = Unsafe.Read<Vector256<int>>(intTable.inArray1Ptr);
+                    var vi2 = Unsafe.Read<Vector256<int>>(intTable.inArray2Ptr);
+                    var vi3 = Avx2.HorizontalSubtract(vi1, vi2);
+                    Unsafe.Write(intTable.outArrayPtr, vi3);
+                    
+                    if ((shortTable.inArray1[0]  -  shortTable.inArray1[1]  != shortTable.outArray[0]) || 
+                        (shortTable.inArray1[2]  -  shortTable.inArray1[3]  != shortTable.outArray[1]) ||
+                        (shortTable.inArray1[4]  -  shortTable.inArray1[5]  != shortTable.outArray[2]) ||
+                        (shortTable.inArray1[6]  -  shortTable.inArray1[7]  != shortTable.outArray[3]) ||
+                        (shortTable.inArray2[0]  -  shortTable.inArray2[1]  != shortTable.outArray[4]) || 
+                        (shortTable.inArray2[2]  -  shortTable.inArray2[3]  != shortTable.outArray[5]) ||
+                        (shortTable.inArray2[4]  -  shortTable.inArray2[5]  != shortTable.outArray[6]) ||
+                        (shortTable.inArray2[6]  -  shortTable.inArray2[7]  != shortTable.outArray[7]) ||
+                        (shortTable.inArray1[8]  -  shortTable.inArray1[9]  != shortTable.outArray[8]) || 
+                        (shortTable.inArray1[10] -  shortTable.inArray1[11]  !=shortTable.outArray[9]) ||
+                        (shortTable.inArray1[12] -  shortTable.inArray1[13]  !=shortTable.outArray[10]) ||
+                        (shortTable.inArray1[14] -  shortTable.inArray1[15]  !=shortTable.outArray[11]) ||
+                        (shortTable.inArray2[8]  -  shortTable.inArray2[9]    !=shortTable.outArray[12]) || 
+                        (shortTable.inArray2[10] -  shortTable.inArray2[11]  !=shortTable.outArray[13]) ||
+                        (shortTable.inArray2[12] -  shortTable.inArray2[13]  !=shortTable.outArray[14]) ||
+                        (shortTable.inArray2[14] -  shortTable.inArray2[15]  !=shortTable.outArray[15]))
+                        {
+                            Console.WriteLine("AVX2 HorizontalSubtract failed on short:");
+           
+                            testResult = Fail;
+            
+                        }      
+                    
+                    if ((intTable.inArray1[0] - intTable.inArray1[1] != intTable.outArray[0]) || 
+                        (intTable.inArray1[2] - intTable.inArray1[3] != intTable.outArray[1]) ||
+                        (intTable.inArray2[0] - intTable.inArray2[1] != intTable.outArray[2]) ||
+                        (intTable.inArray2[2] - intTable.inArray2[3] != intTable.outArray[3]) ||
+                        (intTable.inArray1[4] - intTable.inArray1[5] != intTable.outArray[4]) || 
+                        (intTable.inArray1[6] - intTable.inArray1[7] != intTable.outArray[5]) ||
+                        (intTable.inArray2[4] - intTable.inArray2[5] != intTable.outArray[6]) ||
+                        (intTable.inArray2[6] - intTable.inArray2[7] != intTable.outArray[7])) 
+
+                        {
+                            Console.WriteLine("AVX2 HorizontalSubtract failed on int:");
+           
+                            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/Avx2/HorizontalSubtract_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract_r.csproj
new file mode 100644 (file)
index 0000000..5cafd23
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="HorizontalSubtract.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/HorizontalSubtract_ro.csproj
new file mode 100644 (file)
index 0000000..ddc405c
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="HorizontalSubtract.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate.cs
new file mode 100644 (file)
index 0000000..1d95920
--- /dev/null
@@ -0,0 +1,161 @@
+// 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 (Avx2.IsSupported)
+            {
+                using (TestTable<byte, byte, byte> byteTable = new TestTable<byte, byte, byte>(new byte[32] { 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0 }, new byte[32] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new byte[32]))
+                using (TestTable<sbyte, sbyte, sbyte> sbyteTable = new TestTable<sbyte, sbyte, sbyte>(new sbyte[32] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new sbyte[32] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0 }, new sbyte[32]))
+                using (TestTable<short, short, short> shortTable = new TestTable<short, short, short>(new short[16] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new short[16] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0}, new short[16]))
+                using (TestTable<ushort, ushort, ushort> ushortTable = new TestTable<ushort, ushort, ushort>(new ushort[16] { 1, 5, 100, 0, 1, 5, 100, 0,  1, 5, 100, 0, 1, 5, 100, 0 }, new ushort[16] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new ushort[16]))
+                {
+
+                    var vb1 = Unsafe.Read<Vector256<byte>>(byteTable.inArray1Ptr);
+                    var vb2 = Unsafe.Read<Vector256<byte>>(byteTable.inArray2Ptr);
+                    var vb3 = Avx2.SubtractSaturate(vb1, vb2);
+                    Unsafe.Write(byteTable.outArrayPtr, vb3);
+
+                    var vsb1 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray1Ptr);
+                    var vsb2 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray2Ptr);
+                    var vsb3 = Avx2.SubtractSaturate(vsb1, vsb2);
+                    Unsafe.Write(sbyteTable.outArrayPtr, vsb3);
+
+                    var vs1 = Unsafe.Read<Vector256<short>>(shortTable.inArray1Ptr);
+                    var vs2 = Unsafe.Read<Vector256<short>>(shortTable.inArray2Ptr);
+                    var vs3 = Avx2.SubtractSaturate(vs1, vs2);
+                    Unsafe.Write(shortTable.outArrayPtr, vs3);
+
+                    var vus1 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray1Ptr);
+                    var vus2 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray2Ptr);
+                    var vus3 = Avx2.SubtractSaturate(vus1, vus2);
+                    Unsafe.Write(ushortTable.outArrayPtr, vus3);
+                    
+                    for (int i = 0; i < byteTable.outArray.Length; i++)
+                    {
+                        int value = byteTable.inArray1[i] - byteTable.inArray2[i];
+                        value = Math.Max(value, 0);
+                        value = Math.Min(value, byte.MaxValue);
+                        if ((byte)value != byteTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 SubtractSaturate failed on byte:");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+
+                    for (int i = 0; i < sbyteTable.outArray.Length; i++)
+                    {
+                        int value = sbyteTable.inArray1[i] - sbyteTable.inArray2[i];
+                        value = Math.Max(value, sbyte.MinValue);
+                        value = Math.Min(value, sbyte.MaxValue);
+                        if ((sbyte)value != sbyteTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 SubtractSaturate failed on sbyte:");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+                    
+                    
+                    for (int i = 0; i < shortTable.outArray.Length; i++)
+                    {
+                        int value = shortTable.inArray1[i] - shortTable.inArray2[i];
+                        value = Math.Max(value, short.MinValue);
+                        value = Math.Min(value, short.MaxValue);
+                        if ((short)value != shortTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 SubtractSaturate failed on short:");
+                            Console.WriteLine();
+                            
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+                    
+                    for (int i = 0; i < ushortTable.outArray.Length; i++)
+                    {
+                        int value = ushortTable.inArray1[i] - ushortTable.inArray2[i];
+                        value = Math.Max(value, 0);
+                        value = Math.Min(value, ushort.MaxValue);
+                        if ((ushort)value != ushortTable.outArray[i])
+                        {
+                            Console.WriteLine("AVX2 SubtractSaturate failed on ushort:");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            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/Avx2/SubtractSaturate_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate_r.csproj
new file mode 100644 (file)
index 0000000..8256cc6
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="SubtractSaturate.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/SubtractSaturate_ro.csproj
new file mode 100644 (file)
index 0000000..7e4c6f8
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="SubtractSaturate.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh.cs
new file mode 100644 (file)
index 0000000..55e5d3b
--- /dev/null
@@ -0,0 +1,266 @@
+// 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 (Avx2.IsSupported)
+            {
+                using (TestTable<byte, byte, byte> byteTable = new TestTable<byte, byte, byte>(new byte[32] { 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0 }, new byte[32] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new byte[32]))
+                using (TestTable<sbyte, sbyte, sbyte> sbyteTable = new TestTable<sbyte, sbyte, sbyte>(new sbyte[32] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new sbyte[32] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0 }, new sbyte[32]))
+                using (TestTable<short, short, short> shortTable = new TestTable<short, short, short>(new short[16] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new short[16] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0}, new short[16]))
+                using (TestTable<ushort, ushort, ushort> ushortTable = new TestTable<ushort, ushort, ushort>(new ushort[16] { 1, 5, 100, 0, 1, 5, 100, 0,  1, 5, 100, 0, 1, 5, 100, 0 }, new ushort[16] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new ushort[16]))
+                using (TestTable<int, int, int> intTable = new TestTable<int, int, int>(new int[8] { 1, 5, 100, 0, 1, 5, 100, 0}, new int[8] { 22, 1, 50, 0, 22, 1, 50, 0 }, new int[8]))
+                using (TestTable<uint, uint, uint> uintTable = new TestTable<uint, uint, uint>(new uint[8] { 1, 5, 100, 0, 1, 5, 100, 0 }, new uint[8] { 22, 1, 50, 0, 22, 1, 50, 0 }, new uint[8]))
+                using (TestTable<long, long, long> longTable = new TestTable<long, long, long>(new long[4] { 1, -5, 100, 0 }, new long[4] { 22, -1, -50, 0}, new long[4]))
+                using (TestTable<ulong, ulong, ulong> ulongTable = new TestTable<ulong, ulong, ulong>(new ulong[4] { 1, 5, 100, 0 }, new ulong[4] { 22, 1, 50, 0 }, new ulong[4]))
+
+                {
+
+                    var vb1 = Unsafe.Read<Vector256<byte>>(byteTable.inArray1Ptr);
+                    var vb2 = Unsafe.Read<Vector256<byte>>(byteTable.inArray2Ptr);
+                    var vb3 = Avx2.UnpackHigh(vb1, vb2);
+                    Unsafe.Write(byteTable.outArrayPtr, vb3);
+
+                    var vsb1 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray1Ptr);
+                    var vsb2 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray2Ptr);
+                    var vsb3 = Avx2.UnpackHigh(vsb1, vsb2);
+                    Unsafe.Write(sbyteTable.outArrayPtr, vsb3);
+
+                    var vs1 = Unsafe.Read<Vector256<short>>(shortTable.inArray1Ptr);
+                    var vs2 = Unsafe.Read<Vector256<short>>(shortTable.inArray2Ptr);
+                    var vs3 = Avx2.UnpackHigh(vs1, vs2);
+                    Unsafe.Write(shortTable.outArrayPtr, vs3);
+
+                    var vus1 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray1Ptr);
+                    var vus2 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray2Ptr);
+                    var vus3 = Avx2.UnpackHigh(vus1, vus2);
+                    Unsafe.Write(ushortTable.outArrayPtr, vus3);
+                    
+                    var vi1 = Unsafe.Read<Vector256<int>>(intTable.inArray1Ptr);
+                    var vi2 = Unsafe.Read<Vector256<int>>(intTable.inArray2Ptr);
+                    var vi3 = Avx2.UnpackHigh(vi1, vi2);
+                    Unsafe.Write(intTable.outArrayPtr, vi3);
+
+                    var vui1 = Unsafe.Read<Vector256<uint>>(uintTable.inArray1Ptr);
+                    var vui2 = Unsafe.Read<Vector256<uint>>(uintTable.inArray2Ptr);
+                    var vui3 = Avx2.UnpackHigh(vui1, vui2);
+                    Unsafe.Write(uintTable.outArrayPtr, vui3);
+
+                    var vl1 = Unsafe.Read<Vector256<long>>(longTable.inArray1Ptr);
+                    var vl2 = Unsafe.Read<Vector256<long>>(longTable.inArray2Ptr);
+                    var vl3 = Avx2.UnpackHigh(vl1, vl2);
+                    Unsafe.Write(longTable.outArrayPtr, vl3);
+
+                    var vul1 = Unsafe.Read<Vector256<ulong>>(ulongTable.inArray1Ptr);
+                    var vul2 = Unsafe.Read<Vector256<ulong>>(ulongTable.inArray2Ptr);
+                    var vul3 = Avx2.UnpackHigh(vul1, vul2);
+                    Unsafe.Write(ulongTable.outArrayPtr, vul3);
+                    
+                    if((byteTable.inArray1[8] != byteTable.outArray[0]) || (byteTable.inArray2[8] != byteTable.outArray[1]) ||
+                        (byteTable.inArray1[9] != byteTable.outArray[2]) || (byteTable.inArray2[9] != byteTable.outArray[3]) ||
+                        (byteTable.inArray1[10] != byteTable.outArray[4]) || (byteTable.inArray2[10] != byteTable.outArray[5]) ||
+                        (byteTable.inArray1[11] != byteTable.outArray[6]) || (byteTable.inArray2[11] != byteTable.outArray[7]) ||
+                        (byteTable.inArray1[12] != byteTable.outArray[8]) || (byteTable.inArray2[12] != byteTable.outArray[9]) ||
+                        (byteTable.inArray1[13] != byteTable.outArray[10]) || (byteTable.inArray2[13] != byteTable.outArray[11]) ||
+                        (byteTable.inArray1[14] != byteTable.outArray[12]) || (byteTable.inArray2[14] != byteTable.outArray[13]) ||
+                        (byteTable.inArray1[15] != byteTable.outArray[14]) || (byteTable.inArray2[15] != byteTable.outArray[15]) ||
+                        (byteTable.inArray1[24] != byteTable.outArray[16]) || (byteTable.inArray2[24] != byteTable.outArray[17]) ||
+                        (byteTable.inArray1[25] != byteTable.outArray[18]) || (byteTable.inArray2[25] != byteTable.outArray[19]) ||
+                        (byteTable.inArray1[26] != byteTable.outArray[20]) || (byteTable.inArray2[26] != byteTable.outArray[21]) ||
+                        (byteTable.inArray1[27] != byteTable.outArray[22]) || (byteTable.inArray2[27] != byteTable.outArray[23]) ||
+                        (byteTable.inArray1[28] != byteTable.outArray[24]) || (byteTable.inArray2[28] != byteTable.outArray[25]) ||
+                        (byteTable.inArray1[29] != byteTable.outArray[26]) || (byteTable.inArray2[29] != byteTable.outArray[27]) ||
+                        (byteTable.inArray1[30] != byteTable.outArray[28]) || (byteTable.inArray2[30] != byteTable.outArray[29]) ||
+                        (byteTable.inArray1[31] != byteTable.outArray[30]) || (byteTable.inArray2[31] != byteTable.outArray[31]))
+                        {
+                            Console.WriteLine("AVX2 UnpackHigh failed on byte:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                         }
+                        
+                    if((sbyteTable.inArray1[8] != sbyteTable.outArray[0]) || (sbyteTable.inArray2[8] != sbyteTable.outArray[1]) ||
+                        (sbyteTable.inArray1[9] != sbyteTable.outArray[2]) || (sbyteTable.inArray2[9] != sbyteTable.outArray[3]) ||
+                        (sbyteTable.inArray1[10] != sbyteTable.outArray[4]) || (sbyteTable.inArray2[10] != sbyteTable.outArray[5]) ||
+                        (sbyteTable.inArray1[11] != sbyteTable.outArray[6]) || (sbyteTable.inArray2[11] != sbyteTable.outArray[7]) ||
+                        (sbyteTable.inArray1[12] != sbyteTable.outArray[8]) || (sbyteTable.inArray2[12] != sbyteTable.outArray[9]) ||
+                        (sbyteTable.inArray1[13] != sbyteTable.outArray[10]) || (sbyteTable.inArray2[13] != sbyteTable.outArray[11]) ||
+                        (sbyteTable.inArray1[14] != sbyteTable.outArray[12]) || (sbyteTable.inArray2[14] != sbyteTable.outArray[13]) ||
+                        (sbyteTable.inArray1[15] != sbyteTable.outArray[14]) || (sbyteTable.inArray2[15] != sbyteTable.outArray[15]) ||
+                        (sbyteTable.inArray1[24] != sbyteTable.outArray[16]) || (sbyteTable.inArray2[24] != sbyteTable.outArray[17]) ||
+                        (sbyteTable.inArray1[25] != sbyteTable.outArray[18]) || (sbyteTable.inArray2[25] != sbyteTable.outArray[19]) ||
+                        (sbyteTable.inArray1[26] != sbyteTable.outArray[20]) || (sbyteTable.inArray2[26] != sbyteTable.outArray[21]) ||
+                        (sbyteTable.inArray1[27] != sbyteTable.outArray[22]) || (sbyteTable.inArray2[27] != sbyteTable.outArray[23]) ||
+                        (sbyteTable.inArray1[28] != sbyteTable.outArray[24]) || (sbyteTable.inArray2[28] != sbyteTable.outArray[25]) ||
+                        (sbyteTable.inArray1[29] != sbyteTable.outArray[26]) || (sbyteTable.inArray2[29] != sbyteTable.outArray[27]) ||
+                        (sbyteTable.inArray1[30] != sbyteTable.outArray[28]) || (sbyteTable.inArray2[30] != sbyteTable.outArray[29]) ||
+                        (sbyteTable.inArray1[31] != sbyteTable.outArray[30]) || (sbyteTable.inArray2[31] != sbyteTable.outArray[31]))
+                        {
+                            Console.WriteLine("AVX2 UnpackHigh failed on sbyte:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                    
+                    if((shortTable.inArray1[4] != shortTable.outArray[0]) || (shortTable.inArray2[4] != shortTable.outArray[1]) ||
+                        (shortTable.inArray1[5] != shortTable.outArray[2]) || (shortTable.inArray2[5] != shortTable.outArray[3]) ||
+                        (shortTable.inArray1[6] != shortTable.outArray[4]) || (shortTable.inArray2[6] != shortTable.outArray[5]) ||
+                        (shortTable.inArray1[7] != shortTable.outArray[6]) || (shortTable.inArray2[7] != shortTable.outArray[7]) ||
+                        (shortTable.inArray1[12] != shortTable.outArray[8]) || (shortTable.inArray2[12] != shortTable.outArray[9]) ||
+                        (shortTable.inArray1[13] != shortTable.outArray[10]) || (shortTable.inArray2[13] != shortTable.outArray[11]) ||
+                        (shortTable.inArray1[14] != shortTable.outArray[12]) || (shortTable.inArray2[14] != shortTable.outArray[13]) ||
+                        (shortTable.inArray1[15] != shortTable.outArray[14]) || (shortTable.inArray2[15] != shortTable.outArray[15]))
+                       
+                        {
+                            Console.WriteLine("AVX2 UnpackHigh failed on short:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                    
+                    if((ushortTable.inArray1[4] !=   ushortTable.outArray[0]) || (ushortTable.inArray2[4] != ushortTable.outArray[1]) ||
+                        (ushortTable.inArray1[5] !=  ushortTable.outArray[2]) || (ushortTable.inArray2[5] != ushortTable.outArray[3]) ||
+                        (ushortTable.inArray1[6] !=  ushortTable.outArray[4]) || (ushortTable.inArray2[6] != ushortTable.outArray[5]) ||
+                        (ushortTable.inArray1[7] !=  ushortTable.outArray[6]) || (ushortTable.inArray2[7] != ushortTable.outArray[7]) ||
+                        (ushortTable.inArray1[12] != ushortTable.outArray[8]) || (ushortTable.inArray2[12] != ushortTable.outArray[9]) ||
+                        (ushortTable.inArray1[13] != ushortTable.outArray[10]) || (ushortTable.inArray2[13] != ushortTable.outArray[11]) ||
+                        (ushortTable.inArray1[14] != ushortTable.outArray[12]) || (ushortTable.inArray2[14] != ushortTable.outArray[13]) ||
+                        (ushortTable.inArray1[15] != ushortTable.outArray[14]) || (ushortTable.inArray2[15] != ushortTable.outArray[15]))
+                        {
+                            Console.WriteLine("AVX2 UnpackHigh failed on ushort:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((intTable.inArray1[2] != intTable.outArray[0]) || (intTable.inArray2[2] != intTable.outArray[1]) ||
+                        (intTable.inArray1[3] != intTable.outArray[2]) || (intTable.inArray2[3] != intTable.outArray[3]) ||
+                        (intTable.inArray1[6] != intTable.outArray[4]) || (intTable.inArray2[6] != intTable.outArray[5]) ||
+                        (intTable.inArray1[7] != intTable.outArray[6]) || (intTable.inArray2[7] != intTable.outArray[7]))
+                        {
+                            Console.WriteLine("AVX2 UnpackHigh failed on int:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((uintTable.inArray1[2] != uintTable.outArray[0]) || (uintTable.inArray2[2] != uintTable.outArray[1]) ||
+                        (uintTable.inArray1[3] != uintTable.outArray[2]) || (uintTable.inArray2[3] != uintTable.outArray[3]) ||
+                        (uintTable.inArray1[6] != uintTable.outArray[4]) || (uintTable.inArray2[6] != uintTable.outArray[5]) ||
+                        (uintTable.inArray1[7] != uintTable.outArray[6]) || (uintTable.inArray2[7] != uintTable.outArray[7]))   
+                        {
+                            Console.WriteLine("AVX2 UnpackHigh failed on uint:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((longTable.inArray1[1] != longTable.outArray[0]) || (longTable.inArray2[1] != longTable.outArray[1]) ||
+                        (longTable.inArray1[3] != longTable.outArray[2]) || (longTable.inArray2[3] != longTable.outArray[3]) )
+                         {
+                            Console.WriteLine("AVX2 UnpackHigh failed on long:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((ulongTable.inArray1[1] != ulongTable.outArray[0]) || (ulongTable.inArray2[1] != ulongTable.outArray[1]) ||
+                        (ulongTable.inArray1[3] != ulongTable.outArray[2]) || (ulongTable.inArray2[3] != ulongTable.outArray[3]) )
+                        {
+                            Console.WriteLine("AVX2 UnpackHigh failed on ulong:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            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/Avx2/UnpackHigh_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh_r.csproj
new file mode 100644 (file)
index 0000000..cea0ce8
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="UnpackHigh.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackHigh_ro.csproj
new file mode 100644 (file)
index 0000000..871c3a5
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="UnpackHigh.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow.cs
new file mode 100644 (file)
index 0000000..20e4b41
--- /dev/null
@@ -0,0 +1,266 @@
+// 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 (Avx2.IsSupported)
+            {
+                using (TestTable<byte, byte, byte> byteTable = new TestTable<byte, byte, byte>(new byte[32] { 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0 }, new byte[32] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new byte[32]))
+                using (TestTable<sbyte, sbyte, sbyte> sbyteTable = new TestTable<sbyte, sbyte, sbyte>(new sbyte[32] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new sbyte[32] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0 }, new sbyte[32]))
+                using (TestTable<short, short, short> shortTable = new TestTable<short, short, short>(new short[16] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new short[16] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0}, new short[16]))
+                using (TestTable<ushort, ushort, ushort> ushortTable = new TestTable<ushort, ushort, ushort>(new ushort[16] { 1, 5, 100, 0, 1, 5, 100, 0,  1, 5, 100, 0, 1, 5, 100, 0 }, new ushort[16] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new ushort[16]))
+                using (TestTable<int, int, int> intTable = new TestTable<int, int, int>(new int[8] { 1, 5, 100, 0, 1, 5, 100, 0}, new int[8] { 22, 1, 50, 0, 22, 1, 50, 0 }, new int[8]))
+                using (TestTable<uint, uint, uint> uintTable = new TestTable<uint, uint, uint>(new uint[8] { 1, 5, 100, 0, 1, 5, 100, 0 }, new uint[8] { 22, 1, 50, 0, 22, 1, 50, 0 }, new uint[8]))
+                using (TestTable<long, long, long> longTable = new TestTable<long, long, long>(new long[4] { 1, -5, 100, 0 }, new long[4] { 22, -1, -50, 0}, new long[4]))
+                using (TestTable<ulong, ulong, ulong> ulongTable = new TestTable<ulong, ulong, ulong>(new ulong[4] { 1, 5, 100, 0 }, new ulong[4] { 22, 1, 50, 0 }, new ulong[4]))
+
+                {
+
+                    var vb1 = Unsafe.Read<Vector256<byte>>(byteTable.inArray1Ptr);
+                    var vb2 = Unsafe.Read<Vector256<byte>>(byteTable.inArray2Ptr);
+                    var vb3 = Avx2.UnpackLow(vb1, vb2);
+                    Unsafe.Write(byteTable.outArrayPtr, vb3);
+
+                    var vsb1 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray1Ptr);
+                    var vsb2 = Unsafe.Read<Vector256<sbyte>>(sbyteTable.inArray2Ptr);
+                    var vsb3 = Avx2.UnpackLow(vsb1, vsb2);
+                    Unsafe.Write(sbyteTable.outArrayPtr, vsb3);
+
+                    var vs1 = Unsafe.Read<Vector256<short>>(shortTable.inArray1Ptr);
+                    var vs2 = Unsafe.Read<Vector256<short>>(shortTable.inArray2Ptr);
+                    var vs3 = Avx2.UnpackLow(vs1, vs2);
+                    Unsafe.Write(shortTable.outArrayPtr, vs3);
+
+                    var vus1 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray1Ptr);
+                    var vus2 = Unsafe.Read<Vector256<ushort>>(ushortTable.inArray2Ptr);
+                    var vus3 = Avx2.UnpackLow(vus1, vus2);
+                    Unsafe.Write(ushortTable.outArrayPtr, vus3);
+                    
+                    var vi1 = Unsafe.Read<Vector256<int>>(intTable.inArray1Ptr);
+                    var vi2 = Unsafe.Read<Vector256<int>>(intTable.inArray2Ptr);
+                    var vi3 = Avx2.UnpackLow(vi1, vi2);
+                    Unsafe.Write(intTable.outArrayPtr, vi3);
+
+                    var vui1 = Unsafe.Read<Vector256<uint>>(uintTable.inArray1Ptr);
+                    var vui2 = Unsafe.Read<Vector256<uint>>(uintTable.inArray2Ptr);
+                    var vui3 = Avx2.UnpackLow(vui1, vui2);
+                    Unsafe.Write(uintTable.outArrayPtr, vui3);
+
+                    var vl1 = Unsafe.Read<Vector256<long>>(longTable.inArray1Ptr);
+                    var vl2 = Unsafe.Read<Vector256<long>>(longTable.inArray2Ptr);
+                    var vl3 = Avx2.UnpackLow(vl1, vl2);
+                    Unsafe.Write(longTable.outArrayPtr, vl3);
+
+                    var vul1 = Unsafe.Read<Vector256<ulong>>(ulongTable.inArray1Ptr);
+                    var vul2 = Unsafe.Read<Vector256<ulong>>(ulongTable.inArray2Ptr);
+                    var vul3 = Avx2.UnpackLow(vul1, vul2);
+                    Unsafe.Write(ulongTable.outArrayPtr, vul3);
+                    
+                    if((byteTable.inArray1[0] != byteTable.outArray[0]) || (byteTable.inArray2[0] != byteTable.outArray[1]) ||
+                        (byteTable.inArray1[1] != byteTable.outArray[2]) || (byteTable.inArray2[1] != byteTable.outArray[3]) ||
+                        (byteTable.inArray1[2] != byteTable.outArray[4]) || (byteTable.inArray2[2] != byteTable.outArray[5]) ||
+                        (byteTable.inArray1[3] != byteTable.outArray[6]) || (byteTable.inArray2[3] != byteTable.outArray[7]) ||
+                        (byteTable.inArray1[4] != byteTable.outArray[8]) || (byteTable.inArray2[4] != byteTable.outArray[9]) ||
+                        (byteTable.inArray1[5] != byteTable.outArray[10]) || (byteTable.inArray2[5] != byteTable.outArray[11]) ||
+                        (byteTable.inArray1[6] != byteTable.outArray[12]) || (byteTable.inArray2[6] != byteTable.outArray[13]) ||
+                        (byteTable.inArray1[7] != byteTable.outArray[14]) || (byteTable.inArray2[7] != byteTable.outArray[15]) ||
+                        (byteTable.inArray1[16] != byteTable.outArray[16]) || (byteTable.inArray2[16] != byteTable.outArray[17]) ||
+                        (byteTable.inArray1[17] != byteTable.outArray[18]) || (byteTable.inArray2[17] != byteTable.outArray[19]) ||
+                        (byteTable.inArray1[18] != byteTable.outArray[20]) || (byteTable.inArray2[18] != byteTable.outArray[21]) ||
+                        (byteTable.inArray1[19] != byteTable.outArray[22]) || (byteTable.inArray2[19] != byteTable.outArray[23]) ||
+                        (byteTable.inArray1[20] != byteTable.outArray[24]) || (byteTable.inArray2[20] != byteTable.outArray[25]) ||
+                        (byteTable.inArray1[21] != byteTable.outArray[26]) || (byteTable.inArray2[21] != byteTable.outArray[27]) ||
+                        (byteTable.inArray1[22] != byteTable.outArray[28]) || (byteTable.inArray2[22] != byteTable.outArray[29]) ||
+                        (byteTable.inArray1[23] != byteTable.outArray[30]) || (byteTable.inArray2[23] != byteTable.outArray[31]))
+                        {
+                            Console.WriteLine("AVX2 UnpackLow failed on byte:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if((sbyteTable.inArray1[0] != sbyteTable.outArray[0]) || (sbyteTable.inArray2[0] != sbyteTable.outArray[1]) ||
+                        (sbyteTable.inArray1[1] != sbyteTable.outArray[2]) || (sbyteTable.inArray2[1] != sbyteTable.outArray[3]) ||
+                        (sbyteTable.inArray1[2] != sbyteTable.outArray[4]) || (sbyteTable.inArray2[2] != sbyteTable.outArray[5]) ||
+                        (sbyteTable.inArray1[3] != sbyteTable.outArray[6]) || (sbyteTable.inArray2[3] != sbyteTable.outArray[7]) ||
+                        (sbyteTable.inArray1[4] != sbyteTable.outArray[8]) || (sbyteTable.inArray2[4] != sbyteTable.outArray[9]) ||
+                        (sbyteTable.inArray1[5] != sbyteTable.outArray[10]) || (sbyteTable.inArray2[5] != sbyteTable.outArray[11]) ||
+                        (sbyteTable.inArray1[6] != sbyteTable.outArray[12]) || (sbyteTable.inArray2[6] != sbyteTable.outArray[13]) ||
+                        (sbyteTable.inArray1[7] != sbyteTable.outArray[14]) || (sbyteTable.inArray2[7] != sbyteTable.outArray[15]) ||
+                        (sbyteTable.inArray1[16] != sbyteTable.outArray[16]) || (sbyteTable.inArray2[16] != sbyteTable.outArray[17]) ||
+                        (sbyteTable.inArray1[17] != sbyteTable.outArray[18]) || (sbyteTable.inArray2[17] != sbyteTable.outArray[19]) ||
+                        (sbyteTable.inArray1[18] != sbyteTable.outArray[20]) || (sbyteTable.inArray2[18] != sbyteTable.outArray[21]) ||
+                        (sbyteTable.inArray1[19] != sbyteTable.outArray[22]) || (sbyteTable.inArray2[19] != sbyteTable.outArray[23]) ||
+                        (sbyteTable.inArray1[20] != sbyteTable.outArray[24]) || (sbyteTable.inArray2[20] != sbyteTable.outArray[25]) ||
+                        (sbyteTable.inArray1[21] != sbyteTable.outArray[26]) || (sbyteTable.inArray2[21] != sbyteTable.outArray[27]) ||
+                        (sbyteTable.inArray1[22] != sbyteTable.outArray[28]) || (sbyteTable.inArray2[22] != sbyteTable.outArray[29]) ||
+                        (sbyteTable.inArray1[23] != sbyteTable.outArray[30]) || (sbyteTable.inArray2[23] != sbyteTable.outArray[31]))
+                        {
+                            Console.WriteLine("AVX2 UnpackLow failed on sbyte:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                    
+                    if((shortTable.inArray1[0] != shortTable.outArray[0]) || (shortTable.inArray2[0] != shortTable.outArray[1]) ||
+                        (shortTable.inArray1[1] != shortTable.outArray[2]) || (shortTable.inArray2[1] != shortTable.outArray[3]) ||
+                        (shortTable.inArray1[2] != shortTable.outArray[4]) || (shortTable.inArray2[2] != shortTable.outArray[5]) ||
+                        (shortTable.inArray1[3] != shortTable.outArray[6]) || (shortTable.inArray2[3] != shortTable.outArray[7]) ||
+                        (shortTable.inArray1[8] != shortTable.outArray[8]) || (shortTable.inArray2[8] != shortTable.outArray[9]) ||
+                        (shortTable.inArray1[9] != shortTable.outArray[10]) || (shortTable.inArray2[9] != shortTable.outArray[11]) ||
+                        (shortTable.inArray1[10] != shortTable.outArray[12]) || (shortTable.inArray2[10] != shortTable.outArray[13]) ||
+                        (shortTable.inArray1[11] != shortTable.outArray[14]) || (shortTable.inArray2[11] != shortTable.outArray[15]))
+                       
+                        {
+                            Console.WriteLine("AVX2 UnpackLow failed on short:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                    
+                    if((ushortTable.inArray1[0] !=   ushortTable.outArray[0]) || (ushortTable.inArray2[0] != ushortTable.outArray[1]) ||
+                        (ushortTable.inArray1[1] !=  ushortTable.outArray[2]) || (ushortTable.inArray2[1] != ushortTable.outArray[3]) ||
+                        (ushortTable.inArray1[2] !=  ushortTable.outArray[4]) || (ushortTable.inArray2[2] != ushortTable.outArray[5]) ||
+                        (ushortTable.inArray1[3] !=  ushortTable.outArray[6]) || (ushortTable.inArray2[3] != ushortTable.outArray[7]) ||
+                        (ushortTable.inArray1[8] != ushortTable.outArray[8]) || (ushortTable.inArray2[8] != ushortTable.outArray[9]) ||
+                        (ushortTable.inArray1[9] != ushortTable.outArray[10]) || (ushortTable.inArray2[9] != ushortTable.outArray[11]) ||
+                        (ushortTable.inArray1[10] != ushortTable.outArray[12]) || (ushortTable.inArray2[10] != ushortTable.outArray[13]) ||
+                        (ushortTable.inArray1[11] != ushortTable.outArray[14]) || (ushortTable.inArray2[11] != ushortTable.outArray[15]))
+                        {
+                            Console.WriteLine("AVX2 UnpackLow failed on ushort:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((intTable.inArray1[0] != intTable.outArray[0]) || (intTable.inArray2[0] != intTable.outArray[1]) ||
+                        (intTable.inArray1[1] != intTable.outArray[2]) || (intTable.inArray2[1] != intTable.outArray[3]) ||
+                        (intTable.inArray1[4] != intTable.outArray[4]) || (intTable.inArray2[4] != intTable.outArray[5]) ||
+                        (intTable.inArray1[5] != intTable.outArray[6]) || (intTable.inArray2[5] != intTable.outArray[7]))
+                        {
+                            Console.WriteLine("AVX2 UnpackLow failed on int:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((uintTable.inArray1[0] != uintTable.outArray[0]) || (uintTable.inArray2[0] != uintTable.outArray[1]) ||
+                        (uintTable.inArray1[1] != uintTable.outArray[2]) || (uintTable.inArray2[1] != uintTable.outArray[3]) ||
+                        (uintTable.inArray1[4] != uintTable.outArray[4]) || (uintTable.inArray2[4] != uintTable.outArray[5]) ||
+                        (uintTable.inArray1[5] != uintTable.outArray[6]) || (uintTable.inArray2[5] != uintTable.outArray[7]))   
+                        {
+                            Console.WriteLine("AVX2 UnpackLow failed on uint:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((longTable.inArray1[0] != longTable.outArray[0]) || (longTable.inArray2[0] != longTable.outArray[1]) ||
+                        (longTable.inArray1[2] != longTable.outArray[2]) || (longTable.inArray2[2] != longTable.outArray[3]) )
+                         {
+                            Console.WriteLine("AVX2 UnpackLow failed on long:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            Console.WriteLine();
+
+                            testResult = Fail;
+                        }
+                        
+                    if ((ulongTable.inArray1[0] != ulongTable.outArray[0]) || (ulongTable.inArray2[0] != ulongTable.outArray[1]) ||
+                        (ulongTable.inArray1[2] != ulongTable.outArray[2]) || (ulongTable.inArray2[2] != ulongTable.outArray[3]) )
+                        {
+                            Console.WriteLine("AVX2 UnpackLow failed on ulong:");
+                            Console.WriteLine($"    left: ({string.Join(", ", byteTable.inArray1)})");
+                            Console.WriteLine($"   right: ({string.Join(", ", byteTable.inArray2)})");
+                            Console.WriteLine($"  result: ({string.Join(", ", byteTable.outArray)})");
+                            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/Avx2/UnpackLow_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow_r.csproj
new file mode 100644 (file)
index 0000000..473d350
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="UnpackLow.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/UnpackLow_ro.csproj
new file mode 100644 (file)
index 0000000..5df62dd
--- /dev/null
@@ -0,0 +1,34 @@
+<?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="UnpackLow.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>