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

Commit 04d9414

Browse files
committed
Implement AVX SetVector256
1 parent 496a721 commit 04d9414

File tree

4 files changed

+372
-0
lines changed

4 files changed

+372
-0
lines changed

src/jit/hwintrinsicxarch.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,55 @@ GenTree* Compiler::impAvxOrAvx2Intrinsic(NamedIntrinsic intrinsic,
11481148
break;
11491149
}
11501150

1151+
case NI_AVX_SetVector256:
1152+
{
1153+
// TODO-XARCH: support long/ulong on 32-bit platfroms (remove HW_Flag_SecondArgMaybe64Bit)
1154+
int numArgs = sig->numArgs;
1155+
assert(numArgs >= 4);
1156+
assert(numArgs <= 32);
1157+
baseType = getBaseTypeOfSIMDType(sig->retTypeSigClass);
1158+
GenTree* higherHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, NI_SSE_SetZeroVector128, TYP_FLOAT, 16);
1159+
GenTree* lowerHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, NI_SSE_SetZeroVector128, TYP_FLOAT, 16);
1160+
NamedIntrinsic insertIntrinsic = varTypeIsShort(baseType) ? NI_SSE2_Insert : NI_SSE41_Insert;
1161+
int ival = 0;
1162+
1163+
if (baseType != TYP_DOUBLE)
1164+
{
1165+
assert(varTypeIsIntegral(baseType) || baseType == TYP_FLOAT);
1166+
1167+
for (int i = 0; i < numArgs / 2; i++)
1168+
{
1169+
GenTree* arg = impPopStack().val;
1170+
// SSE4.1 insertps has different semantics from integral insert
1171+
ival = baseType == TYP_FLOAT ? i * 16 : i;
1172+
lowerHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, lowerHalfVector, arg, gtNewIconNode(ival),
1173+
insertIntrinsic, baseType, 16);
1174+
}
1175+
1176+
for (int i = 0; i < numArgs / 2; i++)
1177+
{
1178+
GenTree* arg = impPopStack().val;
1179+
// SSE4.1 insertps has different semantics from integral insert
1180+
ival = baseType == TYP_FLOAT ? i * 16 : i;
1181+
higherHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, higherHalfVector, arg, gtNewIconNode(ival),
1182+
insertIntrinsic, baseType, 16);
1183+
}
1184+
}
1185+
else
1186+
{
1187+
GenTree* op4 = impPopStack().val;
1188+
GenTree* op3 = impPopStack().val;
1189+
GenTree* op2 = impPopStack().val;
1190+
GenTree* op1 = impPopStack().val;
1191+
lowerHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op4, op3, NI_SSE2_UnpackLow, TYP_DOUBLE, 16);
1192+
higherHalfVector = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, op1, NI_SSE2_UnpackLow, TYP_DOUBLE, 16);
1193+
}
1194+
1195+
retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD32, lowerHalfVector, higherHalfVector, gtNewIconNode(1),
1196+
NI_AVX_InsertVector128, baseType, 32);
1197+
break;
1198+
}
1199+
11511200
case NI_AVX_ExtractVector128:
11521201
case NI_AVX2_ExtractVector128:
11531202
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
//
5+
6+
using System;
7+
using System.Runtime.CompilerServices;
8+
using System.Runtime.InteropServices;
9+
using System.Runtime.Intrinsics.X86;
10+
using System.Runtime.Intrinsics;
11+
12+
namespace IntelHardwareIntrinsicTest
13+
{
14+
class Program
15+
{
16+
const int Pass = 100;
17+
const int Fail = 0;
18+
19+
static unsafe int Main(string[] args)
20+
{
21+
int testResult = Pass;
22+
23+
if (Avx.IsSupported)
24+
{
25+
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 }))
26+
{
27+
var vf1 = Avx.SetVector256((float)1, -5, 100, 0, 1, 2, 3, 4);
28+
Unsafe.Write(floatTable.outArrayPtr, vf1);
29+
30+
if (!floatTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
31+
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1)))
32+
{
33+
Console.WriteLine("AVX SetVector256 failed on float:");
34+
foreach (var item in floatTable.outArray)
35+
{
36+
Console.Write(item + ", ");
37+
}
38+
Console.WriteLine();
39+
testResult = Fail;
40+
}
41+
}
42+
43+
using (TestTable<double> doubleTable = new TestTable<double>(new double[4] { double.NaN, double.NaN, double.NaN, double.NaN }))
44+
{
45+
var vf1 = Avx.SetVector256((double)1, 2, 3, 4);
46+
Unsafe.Write(doubleTable.outArrayPtr, vf1);
47+
48+
if (!doubleTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1)))
49+
{
50+
Console.WriteLine("AVX SetVector256 failed on double:");
51+
foreach (var item in doubleTable.outArray)
52+
{
53+
Console.Write(item + ", ");
54+
}
55+
Console.WriteLine();
56+
testResult = Fail;
57+
}
58+
}
59+
60+
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,
61+
sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue,
62+
sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue,
63+
sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue, sbyte.MaxValue }))
64+
{
65+
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);
66+
Unsafe.Write(sbyteTable.outArrayPtr, vf1);
67+
68+
if (!sbyteTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
69+
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1) &&
70+
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
71+
(x[12] == 0) && (x[13] == 100) && (x[14] == -5) && (x[15] == 1) &&
72+
(x[16] == 4) && (x[17] == 3) && (x[18] == 2) && (x[19] == 1) &&
73+
(x[20] == 0) && (x[21] == 100) && (x[22] == -5) && (x[23] == 1) &&
74+
(x[24] == 4) && (x[25] == 3) && (x[26] == 2) && (x[27] == 1) &&
75+
(x[28] == 0) && (x[29] == 100) && (x[30] == -5) && (x[31] == 1)))
76+
{
77+
Console.WriteLine("AVX SetVector256 failed on sbyte:");
78+
foreach (var item in sbyteTable.outArray)
79+
{
80+
Console.Write(item + ", ");
81+
}
82+
Console.WriteLine();
83+
testResult = Fail;
84+
}
85+
}
86+
87+
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,
88+
byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue,
89+
byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue,
90+
byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue }))
91+
{
92+
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);
93+
Unsafe.Write(byteTable.outArrayPtr, vf1);
94+
95+
if (!byteTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
96+
(x[4] == 0) && (x[5] == 100) && (x[6] == 5) && (x[7] == 1) &&
97+
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
98+
(x[12] == 0) && (x[13] == 100) && (x[14] == 5) && (x[15] == 1) &&
99+
(x[16] == 4) && (x[17] == 3) && (x[18] == 2) && (x[19] == 1) &&
100+
(x[20] == 0) && (x[21] == 100) && (x[22] == 5) && (x[23] == 1) &&
101+
(x[24] == 4) && (x[25] == 3) && (x[26] == 2) && (x[27] == 1) &&
102+
(x[28] == 0) && (x[29] == 100) && (x[30] == 5) && (x[31] == 1)))
103+
{
104+
Console.WriteLine("AVX SetVector256 failed on byte:");
105+
foreach (var item in byteTable.outArray)
106+
{
107+
Console.Write(item + ", ");
108+
}
109+
Console.WriteLine();
110+
testResult = Fail;
111+
}
112+
}
113+
114+
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,
115+
short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue, short.MaxValue }))
116+
{
117+
var vf1 = Avx.SetVector256(1, -5, 100, 0, 1, 2, 3, 4, 1, -5, 100, 0, 1, 2, 3, 4);
118+
Unsafe.Write(shortTable.outArrayPtr, vf1);
119+
120+
if (!shortTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
121+
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1) &&
122+
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
123+
(x[12] == 0) && (x[13] == 100) && (x[14] == -5) && (x[15] == 1)))
124+
{
125+
Console.WriteLine("AVX SetVector256 failed on short:");
126+
foreach (var item in shortTable.outArray)
127+
{
128+
Console.Write(item + ", ");
129+
}
130+
Console.WriteLine();
131+
testResult = Fail;
132+
}
133+
}
134+
135+
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,
136+
ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue }))
137+
{
138+
Vector256<ushort> vf1 = Avx.SetVector256((ushort)1, 5, 100, 0, 1, 2, 3, 4, 1, 5, 100, 0, 1, 2, 3, 4);
139+
Unsafe.Write(ushortTable.outArrayPtr, vf1);
140+
141+
if (!ushortTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
142+
(x[4] == 0) && (x[5] == 100) && (x[6] == 5) && (x[7] == 1) &&
143+
(x[8] == 4) && (x[9] == 3) && (x[10] == 2) && (x[11] == 1) &&
144+
(x[12] == 0) && (x[13] == 100) && (x[14] == 5) && (x[15] == 1)))
145+
{
146+
Console.WriteLine("AVX SetVector256 failed on ushort:");
147+
foreach (var item in ushortTable.outArray)
148+
{
149+
Console.Write(item + ", ");
150+
}
151+
Console.WriteLine();
152+
testResult = Fail;
153+
}
154+
}
155+
156+
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 }))
157+
{
158+
var vf1 = Avx.SetVector256(1, -5, 100, 0, 1, 2, 3, 4);
159+
Unsafe.Write(intTable.outArrayPtr, vf1);
160+
161+
if (!intTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
162+
(x[4] == 0) && (x[5] == 100) && (x[6] == -5) && (x[7] == 1)))
163+
{
164+
Console.WriteLine("AVX SetVector256 failed on int:");
165+
foreach (var item in intTable.outArray)
166+
{
167+
Console.Write(item + ", ");
168+
}
169+
Console.WriteLine();
170+
testResult = Fail;
171+
}
172+
}
173+
174+
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 }))
175+
{
176+
Vector256<uint> vf1 = Avx.SetVector256((uint)1, 5, 100, 0, 1, 2, 3, 4);
177+
Unsafe.Write(uintTable.outArrayPtr, vf1);
178+
179+
if (!uintTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1) &&
180+
(x[4] == 0) && (x[5] == 100) && (x[6] == 5) && (x[7] == 1)))
181+
{
182+
Console.WriteLine("AVX SetVector256 failed on uint:");
183+
foreach (var item in uintTable.outArray)
184+
{
185+
Console.Write(item + ", ");
186+
}
187+
Console.WriteLine();
188+
testResult = Fail;
189+
}
190+
}
191+
192+
using (TestTable<long> longTable = new TestTable<long>(new long[4] { long.MaxValue, long.MaxValue, long.MaxValue, long.MaxValue }))
193+
{
194+
var vf1 = Avx.SetVector256(1, 2, 3, 4);
195+
Unsafe.Write(longTable.outArrayPtr, vf1);
196+
197+
if (!longTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1)))
198+
{
199+
Console.WriteLine("AVX SetVector256 failed on long:");
200+
foreach (var item in longTable.outArray)
201+
{
202+
Console.Write(item + ", ");
203+
}
204+
Console.WriteLine();
205+
testResult = Fail;
206+
}
207+
}
208+
209+
using (TestTable<ulong> ulongTable = new TestTable<ulong>(new ulong[4] { ulong.MaxValue, ulong.MaxValue, ulong.MaxValue, ulong.MaxValue }))
210+
{
211+
Vector256<ulong> vf1 = Avx.SetVector256((ulong)1, 2, 3, 4);
212+
Unsafe.Write(ulongTable.outArrayPtr, vf1);
213+
214+
if (!ulongTable.CheckResult((x) => (x[0] == 4) && (x[1] == 3) && (x[2] == 2) && (x[3] == 1)))
215+
{
216+
Console.WriteLine("AVX SetVector256 failed on ulong:");
217+
foreach (var item in ulongTable.outArray)
218+
{
219+
Console.Write(item + ", ");
220+
}
221+
Console.WriteLine();
222+
testResult = Fail;
223+
}
224+
}
225+
}
226+
227+
return testResult;
228+
}
229+
230+
public unsafe struct TestTable<T> : IDisposable where T : struct
231+
{
232+
public T[] outArray;
233+
234+
public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
235+
236+
GCHandle outHandle;
237+
public TestTable(T[] a)
238+
{
239+
this.outArray = a;
240+
241+
outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
242+
}
243+
public bool CheckResult(Func<T[], bool> check)
244+
{
245+
return check(outArray);
246+
}
247+
248+
public void Dispose()
249+
{
250+
outHandle.Free();
251+
}
252+
}
253+
254+
}
255+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<SchemaVersion>2.0</SchemaVersion>
8+
<ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
9+
<OutputType>Exe</OutputType>
10+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
11+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
12+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
13+
</PropertyGroup>
14+
<!-- Default configurations to help VS understand the configurations -->
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
16+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
17+
<ItemGroup>
18+
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
19+
<Visible>False</Visible>
20+
</CodeAnalysisDependentAssemblyPaths>
21+
</ItemGroup>
22+
<PropertyGroup>
23+
<DebugType>None</DebugType>
24+
<Optimize></Optimize>
25+
</PropertyGroup>
26+
<ItemGroup>
27+
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
28+
</ItemGroup>
29+
<ItemGroup>
30+
<Compile Include="SetVector256.cs" />
31+
</ItemGroup>
32+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
33+
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
34+
</Project>

0 commit comments

Comments
 (0)