25ac20670f623b2867a12c25c96b7e5b9004f0c6
[platform/upstream/coreclr.git] / tests / src / JIT / HardwareIntrinsics / X86 / Sse2 / Add.Int16.cs
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  * This file is auto-generated from a template file by the GenerateTests.csx  *
7  * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
8  * changes, please update the corresponding template and run according to the *
9  * directions listed in the file.                                             *
10  ******************************************************************************/
11
12 using System;
13 using System.Runtime.CompilerServices;
14 using System.Runtime.InteropServices;
15 using System.Runtime.Intrinsics;
16 using System.Runtime.Intrinsics.X86;
17
18 namespace JIT.HardwareIntrinsics.X86
19 {
20     public static partial class Program
21     {
22         private static void AddInt16()
23         {
24             var test = new SimpleBinaryOpTest__AddInt16();
25
26             if (test.IsSupported)
27             {
28                 // Validates basic functionality works, using Unsafe.Read
29                 test.RunBasicScenario_UnsafeRead();
30
31                 if (Sse2.IsSupported)
32                 {
33                     // Validates basic functionality works, using Load
34                     test.RunBasicScenario_Load();
35
36                     // Validates basic functionality works, using LoadAligned
37                     test.RunBasicScenario_LoadAligned();
38                 }
39
40                 // Validates calling via reflection works, using Unsafe.Read
41                 test.RunReflectionScenario_UnsafeRead();
42
43                 if (Sse2.IsSupported)
44                 {
45                     // Validates calling via reflection works, using Load
46                     test.RunReflectionScenario_Load();
47
48                     // Validates calling via reflection works, using LoadAligned
49                     test.RunReflectionScenario_LoadAligned();
50                 }
51
52                 // Validates passing a static member works
53                 test.RunClsVarScenario();
54
55                 // Validates passing a local works, using Unsafe.Read
56                 test.RunLclVarScenario_UnsafeRead();
57
58                 if (Sse2.IsSupported)
59                 {
60                     // Validates passing a local works, using Load
61                     test.RunLclVarScenario_Load();
62
63                     // Validates passing a local works, using LoadAligned
64                     test.RunLclVarScenario_LoadAligned();
65                 }
66
67                 // Validates passing the field of a local works
68                 test.RunLclFldScenario();
69
70                 // Validates passing an instance member works
71                 test.RunFldScenario();
72             }
73             else
74             {
75                 // Validates we throw on unsupported hardware
76                 test.RunUnsupportedScenario();
77             }
78
79             if (!test.Succeeded)
80             {
81                 throw new Exception("One or more scenarios did not complete as expected.");
82             }
83         }
84     }
85
86     public sealed unsafe class SimpleBinaryOpTest__AddInt16
87     {
88         private const int VectorSize = 16;
89
90         private const int Op1ElementCount = VectorSize / sizeof(Int16);
91         private const int Op2ElementCount = VectorSize / sizeof(Int16);
92         private const int RetElementCount = VectorSize / sizeof(Int16);
93
94         private static Int16[] _data1 = new Int16[Op1ElementCount];
95         private static Int16[] _data2 = new Int16[Op2ElementCount];
96
97         private static Vector128<Int16> _clsVar1;
98         private static Vector128<Int16> _clsVar2;
99
100         private Vector128<Int16> _fld1;
101         private Vector128<Int16> _fld2;
102
103         private SimpleBinaryOpTest__DataTable<Int16, Int16, Int16> _dataTable;
104
105         static SimpleBinaryOpTest__AddInt16()
106         {
107             var random = new Random();
108
109             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
110             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data1[0]), VectorSize);
111             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
112             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), VectorSize);
113         }
114
115         public SimpleBinaryOpTest__AddInt16()
116         {
117             Succeeded = true;
118
119             var random = new Random();
120
121             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
122             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), VectorSize);
123             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
124             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), VectorSize);
125
126             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
127             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
128             _dataTable = new SimpleBinaryOpTest__DataTable<Int16, Int16, Int16>(_data1, _data2, new Int16[RetElementCount], VectorSize);
129         }
130
131         public bool IsSupported => Sse2.IsSupported;
132
133         public bool Succeeded { get; set; }
134
135         public void RunBasicScenario_UnsafeRead()
136         {
137             var result = Sse2.Add(
138                 Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
139                 Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr)
140             );
141
142             Unsafe.Write(_dataTable.outArrayPtr, result);
143             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
144         }
145
146         public void RunBasicScenario_Load()
147         {
148             var result = Sse2.Add(
149                 Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
150                 Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr))
151             );
152
153             Unsafe.Write(_dataTable.outArrayPtr, result);
154             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
155         }
156
157         public void RunBasicScenario_LoadAligned()
158         {
159             var result = Sse2.Add(
160                 Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)),
161                 Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr))
162             );
163
164             Unsafe.Write(_dataTable.outArrayPtr, result);
165             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
166         }
167
168         public void RunReflectionScenario_UnsafeRead()
169         {
170             var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
171                                      .Invoke(null, new object[] {
172                                         Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
173                                         Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr)
174                                      });
175
176             Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
177             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
178         }
179
180         public void RunReflectionScenario_Load()
181         {
182             var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
183                                      .Invoke(null, new object[] {
184                                         Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
185                                         Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr))
186                                      });
187
188             Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
189             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
190         }
191
192         public void RunReflectionScenario_LoadAligned()
193         {
194             var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
195                                      .Invoke(null, new object[] {
196                                         Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr)),
197                                         Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr))
198                                      });
199
200             Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
201             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
202         }
203
204         public void RunClsVarScenario()
205         {
206             var result = Sse2.Add(
207                 _clsVar1,
208                 _clsVar2
209             );
210
211             Unsafe.Write(_dataTable.outArrayPtr, result);
212             ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
213         }
214
215         public void RunLclVarScenario_UnsafeRead()
216         {
217             var left = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr);
218             var right = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
219             var result = Sse2.Add(left, right);
220
221             Unsafe.Write(_dataTable.outArrayPtr, result);
222             ValidateResult(left, right, _dataTable.outArrayPtr);
223         }
224
225         public void RunLclVarScenario_Load()
226         {
227             var left = Sse2.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
228             var right = Sse2.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
229             var result = Sse2.Add(left, right);
230
231             Unsafe.Write(_dataTable.outArrayPtr, result);
232             ValidateResult(left, right, _dataTable.outArrayPtr);
233         }
234
235         public void RunLclVarScenario_LoadAligned()
236         {
237             var left = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray1Ptr));
238             var right = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArray2Ptr));
239             var result = Sse2.Add(left, right);
240
241             Unsafe.Write(_dataTable.outArrayPtr, result);
242             ValidateResult(left, right, _dataTable.outArrayPtr);
243         }
244
245         public void RunLclFldScenario()
246         {
247             var test = new SimpleBinaryOpTest__AddInt16();
248             var result = Sse2.Add(test._fld1, test._fld2);
249
250             Unsafe.Write(_dataTable.outArrayPtr, result);
251             ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
252         }
253
254         public void RunFldScenario()
255         {
256             var result = Sse2.Add(_fld1, _fld2);
257
258             Unsafe.Write(_dataTable.outArrayPtr, result);
259             ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
260         }
261
262         public void RunUnsupportedScenario()
263         {
264             Succeeded = false;
265
266             try
267             {
268                 RunBasicScenario_UnsafeRead();
269             }
270             catch (PlatformNotSupportedException)
271             {
272                 Succeeded = true;
273             }
274         }
275
276         private void ValidateResult(Vector128<Int16> left, Vector128<Int16> right, void* result, [CallerMemberName] string method = "")
277         {
278             Int16[] inArray1 = new Int16[Op1ElementCount];
279             Int16[] inArray2 = new Int16[Op2ElementCount];
280             Int16[] outArray = new Int16[RetElementCount];
281
282             Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
283             Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
284             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
285
286             ValidateResult(inArray1, inArray2, outArray, method);
287         }
288
289         private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "")
290         {
291             Int16[] inArray1 = new Int16[Op1ElementCount];
292             Int16[] inArray2 = new Int16[Op2ElementCount];
293             Int16[] outArray = new Int16[RetElementCount];
294
295             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), VectorSize);
296             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), VectorSize);
297             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
298
299             ValidateResult(inArray1, inArray2, outArray, method);
300         }
301
302         private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
303         {
304             if ((short)(left[0] + right[0]) != result[0])
305             {
306                 Succeeded = false;
307             }
308             else
309             {
310                 for (var i = 1; i < RetElementCount; i++)
311                 {
312                     if ((short)(left[i] + right[i]) != result[i])
313                     {
314                         Succeeded = false;
315                         break;
316                     }
317                 }
318             }
319
320             if (!Succeeded)
321             {
322                 Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<Int16>(Vector128<Int16>, Vector128<Int16>): {method} failed:");
323                 Console.WriteLine($"    left: ({string.Join(", ", left)})");
324                 Console.WriteLine($"   right: ({string.Join(", ", right)})");
325                 Console.WriteLine($"  result: ({string.Join(", ", result)})");
326                 Console.WriteLine();
327             }
328         }
329     }
330 }