From: Tanner Gooding Date: Wed, 4 Jul 2018 23:32:55 +0000 (-0700) Subject: Adding tests for the x86 TrailingZeroCount HWintrinsic X-Git-Tag: accepted/tizen/unified/20190422.045933~1722 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e60ad4d0db2a899fc52c30382deac063cef0a942;p=platform%2Fupstream%2Fcoreclr.git Adding tests for the x86 TrailingZeroCount HWintrinsic --- diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj new file mode 100644 index 0000000..0037227 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj @@ -0,0 +1,37 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + None + + + + + + + + + + + + + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj new file mode 100644 index 0000000..5145895 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj @@ -0,0 +1,37 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + None + True + + + + + + + + + + + + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs new file mode 100644 index 0000000..a49fdcb --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs @@ -0,0 +1,20 @@ +// 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. + +using System; +using System.Collections.Generic; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + static Program() + { + TestList = new Dictionary() { + ["TrailingZeroCount.UInt32"] = TrailingZeroCountUInt32, + ["TrailingZeroCount.UInt64"] = TrailingZeroCountUInt64, + }; + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/TrailingZeroCount.UInt32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/TrailingZeroCount.UInt32.cs new file mode 100644 index 0000000..8dc9706 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/TrailingZeroCount.UInt32.cs @@ -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 TrailingZeroCountUInt32() + { + var test = new ScalarUnaryOpTest__TrailingZeroCountUInt32(); + + 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__TrailingZeroCountUInt32 + { + private static UInt32 _data; + + private static UInt32 _clsVar; + + private UInt32 _fld; + + static ScalarUnaryOpTest__TrailingZeroCountUInt32() + { + var random = new Random(); + _clsVar = (uint)(random.Next(0, int.MaxValue)); + } + + public ScalarUnaryOpTest__TrailingZeroCountUInt32() + { + 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.TrailingZeroCount( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + ValidateResult(_data, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Bmi1).GetMethod(nameof(Bmi1.TrailingZeroCount), new Type[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + ValidateResult(_data, (UInt32)result); + } + + public void RunClsVarScenario() + { + var result = Bmi1.TrailingZeroCount( + _clsVar + ); + + ValidateResult(_clsVar, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = Bmi1.TrailingZeroCount(data); + + ValidateResult(data, result); + } + + public void RunLclFldScenario() + { + var test = new ScalarUnaryOpTest__TrailingZeroCountUInt32(); + var result = Bmi1.TrailingZeroCount(test._fld); + + ValidateResult(test._fld, result); + } + + public void RunFldScenario() + { + var result = Bmi1.TrailingZeroCount(_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; + + uint expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.TrailingZeroCount)}(UInt32): TrailingZeroCount failed:"); + Console.WriteLine($" data: {data}"); + Console.WriteLine($" result: {result}"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/TrailingZeroCount.UInt64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/TrailingZeroCount.UInt64.cs new file mode 100644 index 0000000..9de8e87 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/TrailingZeroCount.UInt64.cs @@ -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 TrailingZeroCountUInt64() + { + var test = new ScalarUnaryOpTest__TrailingZeroCountUInt64(); + + 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__TrailingZeroCountUInt64 + { + private static UInt64 _data; + + private static UInt64 _clsVar; + + private UInt64 _fld; + + static ScalarUnaryOpTest__TrailingZeroCountUInt64() + { + var random = new Random(); + _clsVar = (ulong)(random.Next(0, int.MaxValue)); + } + + public ScalarUnaryOpTest__TrailingZeroCountUInt64() + { + 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.TrailingZeroCount( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + ValidateResult(_data, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof(Bmi1).GetMethod(nameof(Bmi1.TrailingZeroCount), new Type[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + ValidateResult(_data, (UInt64)result); + } + + public void RunClsVarScenario() + { + var result = Bmi1.TrailingZeroCount( + _clsVar + ); + + ValidateResult(_clsVar, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = Bmi1.TrailingZeroCount(data); + + ValidateResult(data, result); + } + + public void RunLclFldScenario() + { + var test = new ScalarUnaryOpTest__TrailingZeroCountUInt64(); + var result = Bmi1.TrailingZeroCount(test._fld); + + ValidateResult(test._fld, result); + } + + public void RunFldScenario() + { + var result = Bmi1.TrailingZeroCount(_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; + + ulong expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result); + + if (isUnexpectedResult) + { + Console.WriteLine($"{nameof(Bmi1)}.{nameof(Bmi1.TrailingZeroCount)}(UInt64): TrailingZeroCount failed:"); + Console.WriteLine($" data: {data}"); + Console.WriteLine($" result: {result}"); + Console.WriteLine(); + } + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx index 47c5f5f..383f135 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx @@ -786,6 +786,12 @@ private static readonly (string templateFileName, Dictionary tem ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Fma", ["LoadIsa"] = "Avx", ["Method"] = "MultiplySubtractNegated", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "(float)(random.NextDouble())", ["NextValueOp2"] = "(float)(random.NextDouble())", ["NextValueOp3"] = "(float)(random.NextDouble())", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(MathF.Round(-(firstOp[0] * secondOp[0]) - thirdOp[0], 3)) != BitConverter.SingleToInt32Bits(MathF.Round(result[0], 3))", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(MathF.Round(-(firstOp[i] * secondOp[i]) - thirdOp[i], 3)) != BitConverter.SingleToInt32Bits(MathF.Round(result[i], 3))"}), }; +private static readonly (string templateFileName, Dictionary templateData)[] Bmi1Inputs = new [] +{ + ("ScalarUnOpTest.template", new Dictionary { ["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 { ["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 templateData)[] inputs) { var testListFileName = Path.Combine("..", groupName, $"Program.{groupName}.cs"); @@ -876,3 +882,4 @@ ProcessInputs("Avx", AvxInputs); ProcessInputs("Avx2", Avx2Inputs); ProcessInputs("Fma_Vector128", Fma_Vector128Inputs); ProcessInputs("Fma_Vector256", Fma_Vector256Inputs); +ProcessInputs("Bmi1", Bmi1Inputs); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarUnOpTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarUnOpTest.template new file mode 100644 index 0000000..646f3ee --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarUnOpTest.template @@ -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 {Method}{RetBaseType}() + { + var test = new ScalarUnaryOpTest__{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 ScalarUnaryOpTest__{Method}{RetBaseType} + { + private static {Op1BaseType} _data; + + private static {Op1BaseType} _clsVar; + + private {Op1BaseType} _fld; + + static ScalarUnaryOpTest__{Method}{RetBaseType}() + { + var random = new Random(); + _clsVar = {NextValueOp1}; + } + + public ScalarUnaryOpTest__{Method}{RetBaseType}() + { + Succeeded = true; + + var random = new Random(); + + _fld = {NextValueOp1}; + _data = {NextValueOp1}; + } + + 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 _data)) + ); + + ValidateResult(_data, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data)) + }); + + ValidateResult(_data, ({RetBaseType})result); + } + + public void RunClsVarScenario() + { + var result = {Isa}.{Method}( + _clsVar + ); + + ValidateResult(_clsVar, result); + } + + public void RunLclVarScenario_UnsafeRead() + { + var data = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data)); + var result = {Isa}.{Method}(data); + + ValidateResult(data, result); + } + + public void RunLclFldScenario() + { + var test = new ScalarUnaryOpTest__{Method}{RetBaseType}(); + var result = {Isa}.{Method}(test._fld); + + ValidateResult(test._fld, result); + } + + public void RunFldScenario() + { + var result = {Isa}.{Method}(_fld); + ValidateResult(_fld, result); + } + + public void RunUnsupportedScenario() + { + Succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult({Op1BaseType} data, {RetBaseType} result, [CallerMemberName] string method = "") + { + var isUnexpectedResult = false; + + {ValidateResult} + + if (isUnexpectedResult) + { + Console.WriteLine($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}): {Method} failed:"); + Console.WriteLine($" data: {data}"); + Console.WriteLine($" result: {result}"); + Console.WriteLine(); + } + } + } +}