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.
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 ******************************************************************************/
13 using System.Runtime.CompilerServices;
14 using System.Runtime.InteropServices;
15 using System.Runtime.Intrinsics;
16 using System.Runtime.Intrinsics.X86;
18 namespace JIT.HardwareIntrinsics.X86
20 public static partial class Program
22 private static void MaxScalarDouble()
24 var test = new SimpleBinaryOpTest__MaxScalarDouble();
28 // Validates basic functionality works, using Unsafe.Read
29 test.RunBasicScenario_UnsafeRead();
33 // Validates basic functionality works, using Load
34 test.RunBasicScenario_Load();
36 // Validates basic functionality works, using LoadAligned
37 test.RunBasicScenario_LoadAligned();
40 // Validates calling via reflection works, using Unsafe.Read
41 test.RunReflectionScenario_UnsafeRead();
45 // Validates calling via reflection works, using Load
46 test.RunReflectionScenario_Load();
48 // Validates calling via reflection works, using LoadAligned
49 test.RunReflectionScenario_LoadAligned();
52 // Validates passing a static member works
53 test.RunClsVarScenario();
55 // Validates passing a local works, using Unsafe.Read
56 test.RunLclVarScenario_UnsafeRead();
60 // Validates passing a local works, using Load
61 test.RunLclVarScenario_Load();
63 // Validates passing a local works, using LoadAligned
64 test.RunLclVarScenario_LoadAligned();
67 // Validates passing the field of a local class works
68 test.RunClassLclFldScenario();
70 // Validates passing an instance member of a class works
71 test.RunClassFldScenario();
73 // Validates passing the field of a local struct works
74 test.RunStructLclFldScenario();
76 // Validates passing an instance member of a struct works
77 test.RunStructFldScenario();
81 // Validates we throw on unsupported hardware
82 test.RunUnsupportedScenario();
87 throw new Exception("One or more scenarios did not complete as expected.");
92 public sealed unsafe class SimpleBinaryOpTest__MaxScalarDouble
94 private struct TestStruct
96 public Vector128<Double> _fld1;
97 public Vector128<Double> _fld2;
99 public static TestStruct Create()
101 var testStruct = new TestStruct();
102 var random = new Random();
104 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
105 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
106 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
107 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
112 public void RunStructFldScenario(SimpleBinaryOpTest__MaxScalarDouble testClass)
114 var result = Sse2.MaxScalar(_fld1, _fld2);
116 Unsafe.Write(testClass._dataTable.outArrayPtr, result);
117 testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
121 private static readonly int LargestVectorSize = 16;
123 private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
124 private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
125 private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
127 private static Double[] _data1 = new Double[Op1ElementCount];
128 private static Double[] _data2 = new Double[Op2ElementCount];
130 private static Vector128<Double> _clsVar1;
131 private static Vector128<Double> _clsVar2;
133 private Vector128<Double> _fld1;
134 private Vector128<Double> _fld2;
136 private SimpleBinaryOpTest__DataTable<Double, Double, Double> _dataTable;
138 static SimpleBinaryOpTest__MaxScalarDouble()
140 var random = new Random();
142 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
143 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
144 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
145 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
148 public SimpleBinaryOpTest__MaxScalarDouble()
152 var random = new Random();
154 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
155 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
156 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
157 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
159 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
160 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
161 _dataTable = new SimpleBinaryOpTest__DataTable<Double, Double, Double>(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
164 public bool IsSupported => Sse2.IsSupported;
166 public bool Succeeded { get; set; }
168 public void RunBasicScenario_UnsafeRead()
170 var result = Sse2.MaxScalar(
171 Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
172 Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
175 Unsafe.Write(_dataTable.outArrayPtr, result);
176 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
179 public void RunBasicScenario_Load()
181 var result = Sse2.MaxScalar(
182 Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
183 Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr))
186 Unsafe.Write(_dataTable.outArrayPtr, result);
187 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
190 public void RunBasicScenario_LoadAligned()
192 var result = Sse2.MaxScalar(
193 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)),
194 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr))
197 Unsafe.Write(_dataTable.outArrayPtr, result);
198 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
201 public void RunReflectionScenario_UnsafeRead()
203 var result = typeof(Sse2).GetMethod(nameof(Sse2.MaxScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
204 .Invoke(null, new object[] {
205 Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
206 Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
209 Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
210 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
213 public void RunReflectionScenario_Load()
215 var result = typeof(Sse2).GetMethod(nameof(Sse2.MaxScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
216 .Invoke(null, new object[] {
217 Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
218 Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr))
221 Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
222 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
225 public void RunReflectionScenario_LoadAligned()
227 var result = typeof(Sse2).GetMethod(nameof(Sse2.MaxScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
228 .Invoke(null, new object[] {
229 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)),
230 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr))
233 Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
234 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
237 public void RunClsVarScenario()
239 var result = Sse2.MaxScalar(
244 Unsafe.Write(_dataTable.outArrayPtr, result);
245 ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
248 public void RunLclVarScenario_UnsafeRead()
250 var left = Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr);
251 var right = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
252 var result = Sse2.MaxScalar(left, right);
254 Unsafe.Write(_dataTable.outArrayPtr, result);
255 ValidateResult(left, right, _dataTable.outArrayPtr);
258 public void RunLclVarScenario_Load()
260 var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr));
261 var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr));
262 var result = Sse2.MaxScalar(left, right);
264 Unsafe.Write(_dataTable.outArrayPtr, result);
265 ValidateResult(left, right, _dataTable.outArrayPtr);
268 public void RunLclVarScenario_LoadAligned()
270 var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr));
271 var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr));
272 var result = Sse2.MaxScalar(left, right);
274 Unsafe.Write(_dataTable.outArrayPtr, result);
275 ValidateResult(left, right, _dataTable.outArrayPtr);
278 public void RunClassLclFldScenario()
280 var test = new SimpleBinaryOpTest__MaxScalarDouble();
281 var result = Sse2.MaxScalar(test._fld1, test._fld2);
283 Unsafe.Write(_dataTable.outArrayPtr, result);
284 ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
287 public void RunClassFldScenario()
289 var result = Sse2.MaxScalar(_fld1, _fld2);
291 Unsafe.Write(_dataTable.outArrayPtr, result);
292 ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
295 public void RunStructLclFldScenario()
297 var test = TestStruct.Create();
298 var result = Sse2.MaxScalar(test._fld1, test._fld2);
300 Unsafe.Write(_dataTable.outArrayPtr, result);
301 ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
304 public void RunStructFldScenario()
306 var test = TestStruct.Create();
307 test.RunStructFldScenario(this);
310 public void RunUnsupportedScenario()
316 RunBasicScenario_UnsafeRead();
318 catch (PlatformNotSupportedException)
324 private void ValidateResult(Vector128<Double> left, Vector128<Double> right, void* result, [CallerMemberName] string method = "")
326 Double[] inArray1 = new Double[Op1ElementCount];
327 Double[] inArray2 = new Double[Op2ElementCount];
328 Double[] outArray = new Double[RetElementCount];
330 Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), left);
331 Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), right);
332 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
334 ValidateResult(inArray1, inArray2, outArray, method);
337 private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "")
339 Double[] inArray1 = new Double[Op1ElementCount];
340 Double[] inArray2 = new Double[Op2ElementCount];
341 Double[] outArray = new Double[RetElementCount];
343 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Double>>());
344 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Double>>());
345 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
347 ValidateResult(inArray1, inArray2, outArray, method);
350 private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
352 if (BitConverter.DoubleToInt64Bits(Math.Max(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0]))
358 for (var i = 1; i < RetElementCount; i++)
360 if (BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i]))
370 Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.MaxScalar)}<Double>(Vector128<Double>, Vector128<Double>): {method} failed:");
371 Console.WriteLine($" left: ({string.Join(", ", left)})");
372 Console.WriteLine($" right: ({string.Join(", ", right)})");
373 Console.WriteLine($" result: ({string.Join(", ", result)})");