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.
6 using System.Runtime.CompilerServices;
7 using System.Runtime.InteropServices;
8 using System.Runtime.Intrinsics;
9 using System.Runtime.Intrinsics.X86;
11 namespace JIT.HardwareIntrinsics.X86
13 public static partial class Program
15 private static void AddInt64()
17 var test = new SimpleBinaryOpTest__AddInt64();
21 // Validates basic functionality works
22 test.RunBasicScenario();
24 // Validates calling via reflection works
25 test.RunReflectionScenario();
27 // Validates passing a static member works
28 test.RunClsVarScenario();
30 // Validates passing a local works
31 test.RunLclVarScenario();
33 // Validates passing the field of a local works
34 test.RunLclFldScenario();
36 // Validates passing an instance member works
37 test.RunFldScenario();
41 // Validates we throw on unsupported hardware
42 test.RunUnsupportedScenario();
47 throw new Exception("One or more scenarios did not complete as expected.");
52 public sealed unsafe class SimpleBinaryOpTest__AddInt64
54 private const int VectorSize = 32;
55 private const int ElementCount = VectorSize / sizeof(Int64);
57 private static Int64[] _data1 = new Int64[ElementCount];
58 private static Int64[] _data2 = new Int64[ElementCount];
60 private static Vector256<Int64> _clsVar1;
61 private static Vector256<Int64> _clsVar2;
63 private Vector256<Int64> _fld1;
64 private Vector256<Int64> _fld2;
66 private SimpleBinaryOpTest__DataTable<Int64> _dataTable;
68 static SimpleBinaryOpTest__AddInt64()
70 var random = new Random();
72 for (var i = 0; i < ElementCount; i++) { _data1[i] = (long)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (long)(random.Next(int.MinValue, int.MaxValue)); }
73 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data2[0]), VectorSize);
74 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data1[0]), VectorSize);
77 public SimpleBinaryOpTest__AddInt64()
81 var random = new Random();
83 for (var i = 0; i < ElementCount; i++) { _data1[i] = (long)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (long)(random.Next(int.MinValue, int.MaxValue)); }
84 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), VectorSize);
85 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), VectorSize);
87 for (var i = 0; i < ElementCount; i++) { _data1[i] = (long)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (long)(random.Next(int.MinValue, int.MaxValue)); }
88 _dataTable = new SimpleBinaryOpTest__DataTable<Int64>(_data1, _data2, new Int64[ElementCount]);
91 public bool IsSupported => Avx2.IsSupported;
93 public bool Succeeded { get; set; }
95 public void RunBasicScenario()
97 var result = Avx2.Add(
98 Unsafe.Read<Vector256<Int64>>(_dataTable.inArray1Ptr),
99 Unsafe.Read<Vector256<Int64>>(_dataTable.inArray2Ptr)
102 Unsafe.Write(_dataTable.outArrayPtr, result);
103 ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
106 public void RunReflectionScenario()
108 var result = typeof(Avx2).GetMethod(nameof(Avx2.Add), new Type[] { typeof(Vector256<Int64>), typeof(Vector256<Int64>) })
109 .Invoke(null, new object[] {
110 Unsafe.Read<Vector256<Int64>>(_dataTable.inArray1Ptr),
111 Unsafe.Read<Vector256<Int64>>(_dataTable.inArray2Ptr)
114 Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Int64>)(result));
115 ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
118 public void RunClsVarScenario()
120 var result = Avx2.Add(
125 Unsafe.Write(_dataTable.outArrayPtr, result);
126 ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
129 public void RunLclVarScenario()
131 var left = Unsafe.Read<Vector256<Int64>>(_dataTable.inArray1Ptr);
132 var right = Unsafe.Read<Vector256<Int64>>(_dataTable.inArray2Ptr);
133 var result = Avx2.Add(left, right);
135 Unsafe.Write(_dataTable.outArrayPtr, result);
136 ValidateResult(left, right, _dataTable.outArray);
139 public void RunLclFldScenario()
141 var test = new SimpleBinaryOpTest__AddInt64();
142 var result = Avx2.Add(test._fld1, test._fld2);
144 Unsafe.Write(_dataTable.outArrayPtr, result);
145 ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
148 public void RunFldScenario()
150 var result = Avx2.Add(_fld1, _fld2);
152 Unsafe.Write(_dataTable.outArrayPtr, result);
153 ValidateResult(_fld1, _fld2, _dataTable.outArray);
156 public void RunUnsupportedScenario()
164 catch (PlatformNotSupportedException)
170 private void ValidateResult(Vector256<Int64> left, Vector256<Int64> right, Int64[] result, [CallerMemberName] string method = "")
172 Int64[] inArray1 = new Int64[ElementCount];
173 Int64[] inArray2 = new Int64[ElementCount];
175 Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
176 Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
178 ValidateResult(inArray1, inArray2, result, method);
181 private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
183 if ((long)(left[0] + right[0]) != result[0])
189 for (var i = 1; i < left.Length; i++)
191 if ((long)(left[i] + right[i]) != result[i])
201 Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.Add)}<Int64>: {method} failed:");
202 Console.WriteLine($" left: ({string.Join(", ", left)})");
203 Console.WriteLine($" right: ({string.Join(", ", right)})");
204 Console.WriteLine($" result: ({string.Join(", ", result)})");