Adding tests for the AndNot, ExtractLowestSetBit, GetMaskUpToLowestSetBit, and ResetL...
authorTanner Gooding <tagoo@outlook.com>
Fri, 6 Jul 2018 06:36:30 +0000 (23:36 -0700)
committerTanner Gooding <tagoo@outlook.com>
Mon, 9 Jul 2018 23:21:18 +0000 (16:21 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/a1a58001acecb3779f06087d93470bcf515c2cf6

13 files changed:
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/AndNot.UInt32.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/AndNot.UInt64.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ExtractLowestSetBit.UInt32.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ExtractLowestSetBit.UInt64.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/GetMaskUpToLowestSetBit.UInt32.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/GetMaskUpToLowestSetBit.UInt64.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ResetLowestSetBit.UInt32.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ResetLowestSetBit.UInt64.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template [new file with mode: 0644]

diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/AndNot.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/AndNot.UInt32.cs
new file mode 100644 (file)
index 0000000..d91124d
--- /dev/null
@@ -0,0 +1,178 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void AndNotUInt32()
+        {
+            var test = new ScalarBinaryOpTest__AndNotUInt32();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarBinaryOpTest__AndNotUInt32
+    {
+        private static UInt32 _data1;
+        private static UInt32 _data2;
+
+        private static UInt32 _clsVar1;
+        private static UInt32 _clsVar2;
+
+        private UInt32 _fld1;
+        private UInt32 _fld2;
+
+        static ScalarBinaryOpTest__AndNotUInt32()
+        {
+            var random = new Random();
+            _clsVar1 = (uint)(random.Next(0, int.MaxValue));
+            _clsVar2 = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarBinaryOpTest__AndNotUInt32()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld1 = (uint)(random.Next(0, int.MaxValue));
+            _fld2 = (uint)(random.Next(0, int.MaxValue));
+
+            _data1 = (uint)(random.Next(0, int.MaxValue));
+            _data2 = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt32) != typeof(long)) && (typeof(UInt32) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.AndNot(
+                Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+                Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2))
+            );
+
+            ValidateResult(_data1, _data2, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.AndNot), new Type[] { typeof(UInt32), typeof(UInt32) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+                                        Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2))
+                                     });
+
+            ValidateResult(_data1, _data2, (UInt32)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.AndNot(
+                _clsVar1,
+                _clsVar2
+            );
+
+            ValidateResult(_clsVar1, _clsVar2, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data1 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1));
+            var data2 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2));
+            var result = Bmi1.AndNot(data1, data2);
+
+            ValidateResult(data1, data2, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarBinaryOpTest__AndNotUInt32();
+            var result = Bmi1.AndNot(test._fld1, test._fld2);
+
+            ValidateResult(test._fld1, test._fld2, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.AndNot(_fld1, _fld2);
+            ValidateResult(_fld1, _fld2, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt32 left, UInt32 right, UInt32 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = ((~left & right) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.AndNot)}<UInt32>(UInt32, UInt32): AndNot failed:");
+                Console.WriteLine($"    left: {left}");
+                Console.WriteLine($"   right: {right}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/AndNot.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/AndNot.UInt64.cs
new file mode 100644 (file)
index 0000000..eac6861
--- /dev/null
@@ -0,0 +1,178 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void AndNotUInt64()
+        {
+            var test = new ScalarBinaryOpTest__AndNotUInt64();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarBinaryOpTest__AndNotUInt64
+    {
+        private static UInt64 _data1;
+        private static UInt64 _data2;
+
+        private static UInt64 _clsVar1;
+        private static UInt64 _clsVar2;
+
+        private UInt64 _fld1;
+        private UInt64 _fld2;
+
+        static ScalarBinaryOpTest__AndNotUInt64()
+        {
+            var random = new Random();
+            _clsVar1 = (ulong)(random.Next(0, int.MaxValue));
+            _clsVar2 = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarBinaryOpTest__AndNotUInt64()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld1 = (ulong)(random.Next(0, int.MaxValue));
+            _fld2 = (ulong)(random.Next(0, int.MaxValue));
+
+            _data1 = (ulong)(random.Next(0, int.MaxValue));
+            _data2 = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt64) != typeof(long)) && (typeof(UInt64) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.AndNot(
+                Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+                Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2))
+            );
+
+            ValidateResult(_data1, _data2, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.AndNot), new Type[] { typeof(UInt64), typeof(UInt64) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+                                        Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2))
+                                     });
+
+            ValidateResult(_data1, _data2, (UInt64)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.AndNot(
+                _clsVar1,
+                _clsVar2
+            );
+
+            ValidateResult(_clsVar1, _clsVar2, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data1 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1));
+            var data2 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2));
+            var result = Bmi1.AndNot(data1, data2);
+
+            ValidateResult(data1, data2, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarBinaryOpTest__AndNotUInt64();
+            var result = Bmi1.AndNot(test._fld1, test._fld2);
+
+            ValidateResult(test._fld1, test._fld2, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.AndNot(_fld1, _fld2);
+            ValidateResult(_fld1, _fld2, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt64 left, UInt64 right, UInt64 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = ((~left & right) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.AndNot)}<UInt64>(UInt64, UInt64): AndNot failed:");
+                Console.WriteLine($"    left: {left}");
+                Console.WriteLine($"   right: {right}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
index 0037227..39dfd67 100644 (file)
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AndNot.UInt32.cs" />
+    <Compile Include="AndNot.UInt64.cs" />
+    <Compile Include="ExtractLowestSetBit.UInt32.cs" />
+    <Compile Include="ExtractLowestSetBit.UInt64.cs" />
+    <Compile Include="GetMaskUpToLowestSetBit.UInt32.cs" />
+    <Compile Include="GetMaskUpToLowestSetBit.UInt64.cs" />
+    <Compile Include="ResetLowestSetBit.UInt32.cs" />
+    <Compile Include="ResetLowestSetBit.UInt64.cs" />
     <Compile Include="TrailingZeroCount.UInt32.cs" />
     <Compile Include="TrailingZeroCount.UInt64.cs" />
     <Compile Include="Program.Bmi1.cs" />
index 5145895..5ef9723 100644 (file)
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AndNot.UInt32.cs" />
+    <Compile Include="AndNot.UInt64.cs" />
+    <Compile Include="ExtractLowestSetBit.UInt32.cs" />
+    <Compile Include="ExtractLowestSetBit.UInt64.cs" />
+    <Compile Include="GetMaskUpToLowestSetBit.UInt32.cs" />
+    <Compile Include="GetMaskUpToLowestSetBit.UInt64.cs" />
+    <Compile Include="ResetLowestSetBit.UInt32.cs" />
+    <Compile Include="ResetLowestSetBit.UInt64.cs" />
     <Compile Include="TrailingZeroCount.UInt32.cs" />
     <Compile Include="TrailingZeroCount.UInt64.cs" />
     <Compile Include="Program.Bmi1.cs" />
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ExtractLowestSetBit.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ExtractLowestSetBit.UInt32.cs
new file mode 100644 (file)
index 0000000..c912b70
--- /dev/null
@@ -0,0 +1,166 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void ExtractLowestSetBitUInt32()
+        {
+            var test = new ScalarUnaryOpTest__ExtractLowestSetBitUInt32();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarUnaryOpTest__ExtractLowestSetBitUInt32
+    {
+        private static UInt32 _data;
+
+        private static UInt32 _clsVar;
+
+        private UInt32 _fld;
+
+        static ScalarUnaryOpTest__ExtractLowestSetBitUInt32()
+        {
+            var random = new Random();
+            _clsVar = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarUnaryOpTest__ExtractLowestSetBitUInt32()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld = (uint)(random.Next(0, int.MaxValue));
+            _data = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt32) != typeof(long)) && (typeof(UInt32) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.ExtractLowestSetBit(
+                Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data))
+            );
+
+            ValidateResult(_data, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.ExtractLowestSetBit), new Type[] { typeof(UInt32) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data))
+                                     });
+
+            ValidateResult(_data, (UInt32)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.ExtractLowestSetBit(
+                _clsVar
+            );
+
+            ValidateResult(_clsVar, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data));
+            var result = Bmi1.ExtractLowestSetBit(data);
+
+            ValidateResult(data, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarUnaryOpTest__ExtractLowestSetBitUInt32();
+            var result = Bmi1.ExtractLowestSetBit(test._fld);
+
+            ValidateResult(test._fld, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.ExtractLowestSetBit(_fld);
+            ValidateResult(_fld, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt32 data, UInt32 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = ((unchecked((uint)(-(int)data)) & data) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.ExtractLowestSetBit)}<UInt32>(UInt32): ExtractLowestSetBit failed:");
+                Console.WriteLine($"    data: {data}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ExtractLowestSetBit.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ExtractLowestSetBit.UInt64.cs
new file mode 100644 (file)
index 0000000..27fbd0e
--- /dev/null
@@ -0,0 +1,166 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void ExtractLowestSetBitUInt64()
+        {
+            var test = new ScalarUnaryOpTest__ExtractLowestSetBitUInt64();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarUnaryOpTest__ExtractLowestSetBitUInt64
+    {
+        private static UInt64 _data;
+
+        private static UInt64 _clsVar;
+
+        private UInt64 _fld;
+
+        static ScalarUnaryOpTest__ExtractLowestSetBitUInt64()
+        {
+            var random = new Random();
+            _clsVar = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarUnaryOpTest__ExtractLowestSetBitUInt64()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld = (ulong)(random.Next(0, int.MaxValue));
+            _data = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt64) != typeof(long)) && (typeof(UInt64) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.ExtractLowestSetBit(
+                Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data))
+            );
+
+            ValidateResult(_data, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.ExtractLowestSetBit), new Type[] { typeof(UInt64) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data))
+                                     });
+
+            ValidateResult(_data, (UInt64)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.ExtractLowestSetBit(
+                _clsVar
+            );
+
+            ValidateResult(_clsVar, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data));
+            var result = Bmi1.ExtractLowestSetBit(data);
+
+            ValidateResult(data, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarUnaryOpTest__ExtractLowestSetBitUInt64();
+            var result = Bmi1.ExtractLowestSetBit(test._fld);
+
+            ValidateResult(test._fld, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.ExtractLowestSetBit(_fld);
+            ValidateResult(_fld, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt64 data, UInt64 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = ((unchecked((ulong)(-(long)data)) & data) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.ExtractLowestSetBit)}<UInt64>(UInt64): ExtractLowestSetBit failed:");
+                Console.WriteLine($"    data: {data}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/GetMaskUpToLowestSetBit.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/GetMaskUpToLowestSetBit.UInt32.cs
new file mode 100644 (file)
index 0000000..dbef6f7
--- /dev/null
@@ -0,0 +1,166 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void GetMaskUpToLowestSetBitUInt32()
+        {
+            var test = new ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt32();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt32
+    {
+        private static UInt32 _data;
+
+        private static UInt32 _clsVar;
+
+        private UInt32 _fld;
+
+        static ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt32()
+        {
+            var random = new Random();
+            _clsVar = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt32()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld = (uint)(random.Next(0, int.MaxValue));
+            _data = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt32) != typeof(long)) && (typeof(UInt32) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.GetMaskUpToLowestSetBit(
+                Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data))
+            );
+
+            ValidateResult(_data, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.GetMaskUpToLowestSetBit), new Type[] { typeof(UInt32) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data))
+                                     });
+
+            ValidateResult(_data, (UInt32)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.GetMaskUpToLowestSetBit(
+                _clsVar
+            );
+
+            ValidateResult(_clsVar, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data));
+            var result = Bmi1.GetMaskUpToLowestSetBit(data);
+
+            ValidateResult(data, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt32();
+            var result = Bmi1.GetMaskUpToLowestSetBit(test._fld);
+
+            ValidateResult(test._fld, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.GetMaskUpToLowestSetBit(_fld);
+            ValidateResult(_fld, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt32 data, UInt32 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = (((data - 1) ^ data) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.GetMaskUpToLowestSetBit)}<UInt32>(UInt32): GetMaskUpToLowestSetBit failed:");
+                Console.WriteLine($"    data: {data}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/GetMaskUpToLowestSetBit.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/GetMaskUpToLowestSetBit.UInt64.cs
new file mode 100644 (file)
index 0000000..9fa4932
--- /dev/null
@@ -0,0 +1,166 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void GetMaskUpToLowestSetBitUInt64()
+        {
+            var test = new ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt64();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt64
+    {
+        private static UInt64 _data;
+
+        private static UInt64 _clsVar;
+
+        private UInt64 _fld;
+
+        static ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt64()
+        {
+            var random = new Random();
+            _clsVar = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt64()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld = (ulong)(random.Next(0, int.MaxValue));
+            _data = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt64) != typeof(long)) && (typeof(UInt64) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.GetMaskUpToLowestSetBit(
+                Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data))
+            );
+
+            ValidateResult(_data, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.GetMaskUpToLowestSetBit), new Type[] { typeof(UInt64) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data))
+                                     });
+
+            ValidateResult(_data, (UInt64)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.GetMaskUpToLowestSetBit(
+                _clsVar
+            );
+
+            ValidateResult(_clsVar, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data));
+            var result = Bmi1.GetMaskUpToLowestSetBit(data);
+
+            ValidateResult(data, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarUnaryOpTest__GetMaskUpToLowestSetBitUInt64();
+            var result = Bmi1.GetMaskUpToLowestSetBit(test._fld);
+
+            ValidateResult(test._fld, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.GetMaskUpToLowestSetBit(_fld);
+            ValidateResult(_fld, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt64 data, UInt64 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = (((data - 1) ^ data) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.GetMaskUpToLowestSetBit)}<UInt64>(UInt64): GetMaskUpToLowestSetBit failed:");
+                Console.WriteLine($"    data: {data}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
index a49fdcb..5760453 100644 (file)
@@ -12,6 +12,14 @@ namespace JIT.HardwareIntrinsics.X86
         static Program()
         {
             TestList = new Dictionary<string, Action>() {
+                ["AndNot.UInt32"] = AndNotUInt32,
+                ["AndNot.UInt64"] = AndNotUInt64,
+                ["ExtractLowestSetBit.UInt32"] = ExtractLowestSetBitUInt32,
+                ["ExtractLowestSetBit.UInt64"] = ExtractLowestSetBitUInt64,
+                ["GetMaskUpToLowestSetBit.UInt32"] = GetMaskUpToLowestSetBitUInt32,
+                ["GetMaskUpToLowestSetBit.UInt64"] = GetMaskUpToLowestSetBitUInt64,
+                ["ResetLowestSetBit.UInt32"] = ResetLowestSetBitUInt32,
+                ["ResetLowestSetBit.UInt64"] = ResetLowestSetBitUInt64,
                 ["TrailingZeroCount.UInt32"] = TrailingZeroCountUInt32,
                 ["TrailingZeroCount.UInt64"] = TrailingZeroCountUInt64,
             };
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ResetLowestSetBit.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ResetLowestSetBit.UInt32.cs
new file mode 100644 (file)
index 0000000..d42e481
--- /dev/null
@@ -0,0 +1,166 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void ResetLowestSetBitUInt32()
+        {
+            var test = new ScalarUnaryOpTest__ResetLowestSetBitUInt32();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarUnaryOpTest__ResetLowestSetBitUInt32
+    {
+        private static UInt32 _data;
+
+        private static UInt32 _clsVar;
+
+        private UInt32 _fld;
+
+        static ScalarUnaryOpTest__ResetLowestSetBitUInt32()
+        {
+            var random = new Random();
+            _clsVar = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarUnaryOpTest__ResetLowestSetBitUInt32()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld = (uint)(random.Next(0, int.MaxValue));
+            _data = (uint)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt32) != typeof(long)) && (typeof(UInt32) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.ResetLowestSetBit(
+                Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data))
+            );
+
+            ValidateResult(_data, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.ResetLowestSetBit), new Type[] { typeof(UInt32) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data))
+                                     });
+
+            ValidateResult(_data, (UInt32)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.ResetLowestSetBit(
+                _clsVar
+            );
+
+            ValidateResult(_clsVar, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data));
+            var result = Bmi1.ResetLowestSetBit(data);
+
+            ValidateResult(data, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarUnaryOpTest__ResetLowestSetBitUInt32();
+            var result = Bmi1.ResetLowestSetBit(test._fld);
+
+            ValidateResult(test._fld, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.ResetLowestSetBit(_fld);
+            ValidateResult(_fld, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt32 data, UInt32 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = (((data - 1) & data) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.ResetLowestSetBit)}<UInt32>(UInt32): ResetLowestSetBit failed:");
+                Console.WriteLine($"    data: {data}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ResetLowestSetBit.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/ResetLowestSetBit.UInt64.cs
new file mode 100644 (file)
index 0000000..4ca1c8a
--- /dev/null
@@ -0,0 +1,166 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void ResetLowestSetBitUInt64()
+        {
+            var test = new ScalarUnaryOpTest__ResetLowestSetBitUInt64();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarUnaryOpTest__ResetLowestSetBitUInt64
+    {
+        private static UInt64 _data;
+
+        private static UInt64 _clsVar;
+
+        private UInt64 _fld;
+
+        static ScalarUnaryOpTest__ResetLowestSetBitUInt64()
+        {
+            var random = new Random();
+            _clsVar = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public ScalarUnaryOpTest__ResetLowestSetBitUInt64()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld = (ulong)(random.Next(0, int.MaxValue));
+            _data = (ulong)(random.Next(0, int.MaxValue));
+        }
+
+        public bool IsSupported => Bmi1.IsSupported && (Environment.Is64BitProcess || ((typeof(UInt64) != typeof(long)) && (typeof(UInt64) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = Bmi1.ResetLowestSetBit(
+                Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data))
+            );
+
+            ValidateResult(_data, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof(Bmi1).GetMethod(nameof(Bmi1.ResetLowestSetBit), new Type[] { typeof(UInt64) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data))
+                                     });
+
+            ValidateResult(_data, (UInt64)result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = Bmi1.ResetLowestSetBit(
+                _clsVar
+            );
+
+            ValidateResult(_clsVar, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data));
+            var result = Bmi1.ResetLowestSetBit(data);
+
+            ValidateResult(data, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarUnaryOpTest__ResetLowestSetBitUInt64();
+            var result = Bmi1.ResetLowestSetBit(test._fld);
+
+            ValidateResult(test._fld, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = Bmi1.ResetLowestSetBit(_fld);
+            ValidateResult(_fld, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult(UInt64 data, UInt64 result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            isUnexpectedResult = (((data - 1) & data) != result);
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.ResetLowestSetBit)}<UInt64>(UInt64): ResetLowestSetBit failed:");
+                Console.WriteLine($"    data: {data}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}
index 383f135..54e3328 100644 (file)
@@ -788,8 +788,16 @@ private static readonly (string templateFileName, Dictionary<string, string> tem
 
 private static readonly (string templateFileName, Dictionary<string, string> templateData)[] Bmi1Inputs = new []
 {
-    ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "TrailingZeroCount", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))", ["ValidateResult"] = "uint expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
-    ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "TrailingZeroCount", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))", ["ValidateResult"] = "ulong expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
+    ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "AndNot",                  ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))",  ["NextValueOp2"] = "(uint)(random.Next(0, int.MaxValue))",  ["ValidateResult"] = "isUnexpectedResult = ((~left & right) != result);" }),
+    ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "AndNot",                  ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))", ["NextValueOp2"] = "(ulong)(random.Next(0, int.MaxValue))", ["ValidateResult"] = "isUnexpectedResult = ((~left & right) != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ExtractLowestSetBit",     ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32",                             ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))",                                                              ["ValidateResult"] = "isUnexpectedResult = ((unchecked((uint)(-(int)data)) & data) != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ExtractLowestSetBit",     ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64",                             ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))",                                                             ["ValidateResult"] = "isUnexpectedResult = ((unchecked((ulong)(-(long)data)) & data) != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "GetMaskUpToLowestSetBit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32",                             ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))",                                                              ["ValidateResult"] = "isUnexpectedResult = (((data - 1) ^ data) != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "GetMaskUpToLowestSetBit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64",                             ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))",                                                             ["ValidateResult"] = "isUnexpectedResult = (((data - 1) ^ data) != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ResetLowestSetBit",       ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32",                             ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))",                                                              ["ValidateResult"] = "isUnexpectedResult = (((data - 1) & data) != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ResetLowestSetBit",       ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64",                             ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))",                                                             ["ValidateResult"] = "isUnexpectedResult = (((data - 1) & data) != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "TrailingZeroCount",       ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32",                             ["NextValueOp1"] = "(uint)(random.Next(0, int.MaxValue))",                                                              ["ValidateResult"] = "uint expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
+    ("ScalarUnOpTest.template",  new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "TrailingZeroCount",       ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64",                             ["NextValueOp1"] = "(ulong)(random.Next(0, int.MaxValue))",                                                             ["ValidateResult"] = "ulong expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
 };
 
 private static void ProcessInputs(string groupName, (string templateFileName, Dictionary<string, string> templateData)[] inputs)
diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template
new file mode 100644 (file)
index 0000000..572a18f
--- /dev/null
@@ -0,0 +1,178 @@
+// 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.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx  *
+ * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file.                                             *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void {Method}{RetBaseType}()
+        {
+            var test = new ScalarBinaryOpTest__{Method}{RetBaseType}();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.ReadUnaligned
+                test.RunBasicScenario_UnsafeRead();
+
+                // Validates calling via reflection works, using Unsafe.ReadUnaligned
+                test.RunReflectionScenario_UnsafeRead();
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                // Validates passing a local works, using Unsafe.ReadUnaligned
+                test.RunLclVarScenario_UnsafeRead();
+
+                // Validates passing the field of a local works
+                test.RunLclFldScenario();
+
+                // Validates passing an instance member works
+                test.RunFldScenario();
+            }
+            else
+            {
+                // Validates we throw on unsupported hardware
+                test.RunUnsupportedScenario();
+            }
+
+            if (!test.Succeeded)
+            {
+                throw new Exception("One or more scenarios did not complete as expected.");
+            }
+        }
+    }
+
+    public sealed unsafe class ScalarBinaryOpTest__{Method}{RetBaseType}
+    {
+        private static {Op1BaseType} _data1;
+        private static {Op1BaseType} _data2;
+
+        private static {Op1BaseType} _clsVar1;
+        private static {Op1BaseType} _clsVar2;
+
+        private {Op1BaseType} _fld1;
+        private {Op1BaseType} _fld2;
+
+        static ScalarBinaryOpTest__{Method}{RetBaseType}()
+        {
+            var random = new Random();
+            _clsVar1 = {NextValueOp1};
+            _clsVar2 = {NextValueOp2};
+        }
+
+        public ScalarBinaryOpTest__{Method}{RetBaseType}()
+        {
+            Succeeded = true;
+
+            var random = new Random();
+            
+            _fld1 = {NextValueOp1};
+            _fld2 = {NextValueOp2};
+
+            _data1 = {NextValueOp1};
+            _data2 = {NextValueOp2};
+        }
+
+        public bool IsSupported => {Isa}.IsSupported && (Environment.Is64BitProcess || ((typeof({RetBaseType}) != typeof(long)) && (typeof({RetBaseType}) != typeof(ulong))));
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            var result = {Isa}.{Method}(
+                Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)),
+                Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2))
+            );
+
+            ValidateResult(_data1, _data2, result);
+        }
+
+        public void RunReflectionScenario_UnsafeRead()
+        {
+            var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}), typeof({Op2BaseType}) })
+                                     .Invoke(null, new object[] {
+                                        Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)),
+                                        Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2))
+                                     });
+
+            ValidateResult(_data1, _data2, ({RetBaseType})result);
+        }
+
+        public void RunClsVarScenario()
+        {
+            var result = {Isa}.{Method}(
+                _clsVar1,
+                _clsVar2
+            );
+
+            ValidateResult(_clsVar1, _clsVar2, result);
+        }
+
+        public void RunLclVarScenario_UnsafeRead()
+        {
+            var data1 = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1));
+            var data2 = Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data2));
+            var result = {Isa}.{Method}(data1, data2);
+
+            ValidateResult(data1, data2, result);
+        }
+
+        public void RunLclFldScenario()
+        {
+            var test = new ScalarBinaryOpTest__{Method}{RetBaseType}();
+            var result = {Isa}.{Method}(test._fld1, test._fld2);
+
+            ValidateResult(test._fld1, test._fld2, result);
+        }
+
+        public void RunFldScenario()
+        {
+            var result = {Isa}.{Method}(_fld1, _fld2);
+            ValidateResult(_fld1, _fld2, result);
+        }
+
+        public void RunUnsupportedScenario()
+        {
+            Succeeded = false;
+
+            try
+            {
+                RunBasicScenario_UnsafeRead();
+            }
+            catch (PlatformNotSupportedException)
+            {
+                Succeeded = true;
+            }
+        }
+
+        private void ValidateResult({Op1BaseType} left, {Op2BaseType} right, {RetBaseType} result, [CallerMemberName] string method = "")
+        {
+            var isUnexpectedResult = false;
+
+            {ValidateResult}
+
+            if (isUnexpectedResult)
+            {
+                Console.WriteLine($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}, {Op2BaseType}): {Method} failed:");
+                Console.WriteLine($"    left: {left}");
+                Console.WriteLine($"   right: {right}");
+                Console.WriteLine($"  result: {result}");
+                Console.WriteLine();
+            }
+        }
+    }
+}