Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Implement AVX SetVector256
Browse files Browse the repository at this point in the history
  • Loading branch information
FeiPengIntel committed Mar 19, 2018
1 parent 496a721 commit 04d9414
Show file tree
Hide file tree
Showing 4 changed files with 372 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/jit/hwintrinsicxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,55 @@ GenTree* Compiler::impAvxOrAvx2Intrinsic(NamedIntrinsic intrinsic,
break;
}

case NI_AVX_SetVector256:
{
// TODO-XARCH: support long/ulong on 32-bit platfroms (remove HW_Flag_SecondArgMaybe64Bit)
int numArgs = sig->numArgs;
assert(numArgs >= 4);
assert(numArgs <= 32);
baseType = getBaseTypeOfSIMDType(sig->retTypeSigClass);
GenTree* higherHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, NI_SSE_SetZeroVector128, TYP_FLOAT, 16);
GenTree* lowerHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, NI_SSE_SetZeroVector128, TYP_FLOAT, 16);
NamedIntrinsic insertIntrinsic = varTypeIsShort(baseType) ? NI_SSE2_Insert : NI_SSE41_Insert;
int ival = 0;

if (baseType != TYP_DOUBLE)
{
assert(varTypeIsIntegral(baseType) || baseType == TYP_FLOAT);

for (int i = 0; i < numArgs / 2; i++)
{
GenTree* arg = impPopStack().val;
// SSE4.1 insertps has different semantics from integral insert
ival = baseType == TYP_FLOAT ? i * 16 : i;
lowerHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, lowerHalfVector, arg, gtNewIconNode(ival),
insertIntrinsic, baseType, 16);
}

for (int i = 0; i < numArgs / 2; i++)
{
GenTree* arg = impPopStack().val;
// SSE4.1 insertps has different semantics from integral insert
ival = baseType == TYP_FLOAT ? i * 16 : i;
higherHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, higherHalfVector, arg, gtNewIconNode(ival),
insertIntrinsic, baseType, 16);
}
}
else
{
GenTree* op4 = impPopStack().val;
GenTree* op3 = impPopStack().val;
GenTree* op2 = impPopStack().val;
GenTree* op1 = impPopStack().val;
lowerHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op4, op3, NI_SSE2_UnpackLow, TYP_DOUBLE, 16);
higherHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, op1, NI_SSE2_UnpackLow, TYP_DOUBLE, 16);
}

retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD32, lowerHalfVector, higherHalfVector, gtNewIconNode(1),
NI_AVX_InsertVector128, baseType, 32);
break;
}

case NI_AVX_ExtractVector128:
case NI_AVX2_ExtractVector128:
{
Expand Down
255 changes: 255 additions & 0 deletions tests/src/JIT/HardwareIntrinsics/X86/Avx/SetVector256.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
// 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] { float.NaN, float.NaN, float.NaN, float.NaN, float.NaN, float.NaN, float.NaN, float.NaN }))
{
var vf1 = Avx.SetVector256((float)1, -5, 100, 0, 1, 2, 3, 4);
Unsafe.Write(floatTable.outArrayPtr, vf1);

if (!floatTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on float:");
foreach (var item in floatTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<double> doubleTable = new TestTable<double>(new double[4] { double.NaN, double.NaN, double.NaN, double.NaN }))
{
var vf1 = Avx.SetVector256((double)1, 2, 3, 4);
Unsafe.Write(doubleTable.outArrayPtr, vf1);

if (!doubleTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on double:");
foreach (var item in doubleTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<sbyte> sbyteTable = new TestTable<sbyte>(new sbyte[32] { sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue,
sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue,
sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue,
sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue }))
{
var vf1 = Avx.SetVector256(1, -5, 100, 0, 1, 2, 3, 4, 1, -5, 100, 0, 1, 2, 3, 4, 1, -5, 100, 0, 1, 2, 3, 4, 1, -5, 100, 0, 1, 2, 3, 4);
Unsafe.Write(sbyteTable.outArrayPtr, vf1);

if (!sbyteTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1) &&
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
(x[12] == 0) && (x[13] == 100) && (x[14] == -5) && (x[15] == 1) &&
(x[16] == 4) && (x[17] == 3) && (x[18] == 2) && (x[19] == 1) &&
(x[20] == 0) && (x[21] == 100) && (x[22] == -5) && (x[23] == 1) &&
(x[24] == 4) && (x[25] == 3) && (x[26] == 2) && (x[27] == 1) &&
(x[28] == 0) && (x[29] == 100) && (x[30] == -5) && (x[31] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on sbyte:");
foreach (var item in sbyteTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<byte> byteTable = new TestTable<byte>(new byte[32] { byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue,
byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue,
byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue,
byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue }))
{
Vector256<byte> vf1 = Avx.SetVector256((byte)1, 5, 100, 0, 1, 2, 3, 4, 1, 5, 100, 0, 1, 2, 3, 4, 1, 5, 100, 0, 1, 2, 3, 4, 1, 5, 100, 0, 1, 2, 3, 4);
Unsafe.Write(byteTable.outArrayPtr, vf1);

if (!byteTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
(x[4] == 0) && (x[5] == 100) && (x[6] == 5) && (x[7] == 1) &&
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
(x[12] == 0) && (x[13] == 100) && (x[14] == 5) && (x[15] == 1) &&
(x[16] == 4) && (x[17] == 3) && (x[18] == 2) && (x[19] == 1) &&
(x[20] == 0) && (x[21] == 100) && (x[22] == 5) && (x[23] == 1) &&
(x[24] == 4) && (x[25] == 3) && (x[26] == 2) && (x[27] == 1) &&
(x[28] == 0) && (x[29] == 100) && (x[30] == 5) && (x[31] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on byte:");
foreach (var item in byteTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<short> shortTable = new TestTable<short>(new short[16] { short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue,
short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue }))
{
var vf1 = Avx.SetVector256(1, -5, 100, 0, 1, 2, 3, 4, 1, -5, 100, 0, 1, 2, 3, 4);
Unsafe.Write(shortTable.outArrayPtr, vf1);

if (!shortTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1) &&
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
(x[12] == 0) && (x[13] == 100) && (x[14] == -5) && (x[15] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on short:");
foreach (var item in shortTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<ushort> ushortTable = new TestTable<ushort>(new ushort[16] { ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue,
ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue }))
{
Vector256<ushort> vf1 = Avx.SetVector256((ushort)1, 5, 100, 0, 1, 2, 3, 4, 1, 5, 100, 0, 1, 2, 3, 4);
Unsafe.Write(ushortTable.outArrayPtr, vf1);

if (!ushortTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
(x[4] == 0) && (x[5] == 100) && (x[6] == 5) && (x[7] == 1) &&
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
(x[12] == 0) && (x[13] == 100) && (x[14] == 5) && (x[15] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on ushort:");
foreach (var item in ushortTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<int> intTable = new TestTable<int>(new int[8] { int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue }))
{
var vf1 = Avx.SetVector256(1, -5, 100, 0, 1, 2, 3, 4);
Unsafe.Write(intTable.outArrayPtr, vf1);

if (!intTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on int:");
foreach (var item in intTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<uint> uintTable = new TestTable<uint>(new uint[8] { uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue }))
{
Vector256<uint> vf1 = Avx.SetVector256((uint)1, 5, 100, 0, 1, 2, 3, 4);
Unsafe.Write(uintTable.outArrayPtr, vf1);

if (!uintTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
(x[4] == 0) && (x[5] == 100) && (x[6] == 5) && (x[7] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on uint:");
foreach (var item in uintTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<long> longTable = new TestTable<long>(new long[4] { long.MaxValue, long.MaxValue, long.MaxValue, long.MaxValue }))
{
var vf1 = Avx.SetVector256(1, 2, 3, 4);
Unsafe.Write(longTable.outArrayPtr, vf1);

if (!longTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on long:");
foreach (var item in longTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}

using (TestTable<ulong> ulongTable = new TestTable<ulong>(new ulong[4] { ulong.MaxValue, ulong.MaxValue, ulong.MaxValue, ulong.MaxValue }))
{
Vector256<ulong> vf1 = Avx.SetVector256((ulong)1, 2, 3, 4);
Unsafe.Write(ulongTable.outArrayPtr, vf1);

if (!ulongTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1)))
{
Console.WriteLine("AVX SetVector256 failed on ulong:");
foreach (var item in ulongTable.outArray)
{
Console.Write(item + ", ");
}
Console.WriteLine();
testResult = Fail;
}
}
}

return testResult;
}

public unsafe struct TestTable<T> : IDisposable where T : struct
{
public T[] outArray;

public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();

GCHandle outHandle;
public TestTable(T[] a)
{
this.outArray = a;

outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
}
public bool CheckResult(Func<T[], bool> check)
{
return check(outArray);
}

public void Dispose()
{
outHandle.Free();
}
}

}
}
34 changes: 34 additions & 0 deletions tests/src/JIT/HardwareIntrinsics/X86/Avx/SetVector256_r.csproj
Original file line number Diff line number Diff line change
@@ -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="SetVector256.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
</Project>
Loading

0 comments on commit 04d9414

Please sign in to comment.