From 40f7302f227f7fde344e1e586b1eb31300946120 Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Wed, 7 Mar 2018 19:07:51 -0500 Subject: [PATCH] [Arm64] Add Base HW intrinsic tests --- tests/src/JIT/HardwareIntrinsics/Arm64/Base.cs | 181 +++++++++++++++++++++ tests/src/JIT/HardwareIntrinsics/Arm64/Base.csproj | 36 ++++ 2 files changed, 217 insertions(+) create mode 100644 tests/src/JIT/HardwareIntrinsics/Arm64/Base.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/Arm64/Base.csproj diff --git a/tests/src/JIT/HardwareIntrinsics/Arm64/Base.cs b/tests/src/JIT/HardwareIntrinsics/Arm64/Base.cs new file mode 100644 index 0000000..e6efcd0 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/Arm64/Base.cs @@ -0,0 +1,181 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm.Arm64; + +namespace Arm64intrisicsTest +{ + class Program + { + static void testUnaryOp(String testCaseDescription, Func binOp, Func check, T value) + { + bool failed = false; + try + { + int expected = check(value); + int result = binOp(value); + + if (result != expected) + { + Console.WriteLine($"testUnaryOp<{typeof(T).Name}>{testCaseDescription}: Check Failed"); + Console.WriteLine($" result = {result}, expected = {expected}"); + throw new Exception($"testUnaryOp<{typeof(T).Name}>{testCaseDescription}: Failed"); + } + } + catch + { + Console.WriteLine($"testUnaryOp<{typeof(T).Name}>{testCaseDescription}: Unexpected exception"); + throw; + } + } + + static void testThrowsPlatformNotSupported(String testCaseDescription, Func unaryOp, T value) + { + bool notSupported = false; + + try + { + unaryOp(value); + } + catch (PlatformNotSupportedException) + { + notSupported = true; + } + catch + { + Console.WriteLine($"testThrowsPlatformNotSupported: Unexpected exception"); + throw; + } + + if (notSupported == false) + { + throw new Exception($"testThrowsPlatformNotSupported<{typeof(T).Name} >{testCaseDescription}: Failed"); + } + } + + static ulong bitsToUint64(T x) + { + return Unsafe.As(ref x) & ~(~0UL << 8*Unsafe.SizeOf()); + } + + static int leadingZero(T x) + where T : IConvertible + { + ulong compare = 0x1UL << (8*Unsafe.SizeOf() - 1); + int result = 0; + ulong value = bitsToUint64(x); + + while(value < compare) + { + result++; + compare >>= 1; + } + + return result; + + throw new Exception("Unexpected Type"); + } + + static int leadingSign(T x) + where T : IConvertible + { + ulong value = bitsToUint64(x); + ulong signBit = value & (0x1UL << (8*Unsafe.SizeOf() - 1)); + int result = 0; + + if (signBit == 0) + { + result = leadingZero(x); + } + else + { + result = leadingZero((T) Convert.ChangeType(value ^ (signBit + (signBit - 1)), typeof(T))); + } + + return result - 1; + } + + static void TestLeadingSignCount() + { +#if COREFX_HAS_ARM64_BASE + String name = "LeadingSignCount"; + + if (Base.IsSupported) + { + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), 0); + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), -1); + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), 1 << 30); + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), -1 << 30); + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), 0); + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), -1); + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), 1L << 60); + testUnaryOp(name, (x) => Base.LeadingSignCount(x), (x) => leadingSign(x), -1L << 60); + } + else + { + testThrowsPlatformNotSupported(name, (x) => Base.LeadingSignCount(x), 0); + testThrowsPlatformNotSupported(name, (x) => Base.LeadingSignCount(x), 0); + } + + Console.WriteLine($"Test{name} passed"); +#endif // COREFX_HAS_ARM64_BASE + } + + static void TestLeadingZeroCount() + { +#if COREFX_HAS_ARM64_BASE + String name = "LeadingZeroCount"; + + if (Base.IsSupported) + { + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 0); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), -1); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 1 << 30); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), -1 << 30); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 0); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 1 << 30); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 0); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), -1); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 1L << 60); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), -1L << 60); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 0); + testUnaryOp(name, (x) => Base.LeadingZeroCount(x), (x) => leadingZero(x), 1L << 60); + } + else + { + testThrowsPlatformNotSupported(name, (x) => Base.LeadingZeroCount(x), 0); + testThrowsPlatformNotSupported(name, (x) => Base.LeadingZeroCount(x), 0); + testThrowsPlatformNotSupported(name, (x) => Base.LeadingZeroCount(x), 0); + testThrowsPlatformNotSupported(name, (x) => Base.LeadingZeroCount(x), 0); + } + + Console.WriteLine($"Test{name} passed"); +#endif // COREFX_HAS_ARM64_BASE + } + + static void ExecuteAllTests() + { + TestLeadingSignCount(); + TestLeadingZeroCount(); + } + + static int Main(string[] args) + { +#if COREFX_HAS_ARM64_BASE + Console.WriteLine($"System.Runtime.Intrinsics.Arm.Arm64.Base.IsSupported = {Base.IsSupported}"); + + // Reflection call + var issupported = "get_IsSupported"; + bool reflectedIsSupported = Convert.ToBoolean(typeof(Base).GetMethod(issupported).Invoke(null, null)); + + Debug.Assert(reflectedIsSupported == Base.IsSupported, "Reflection result does not match"); +#endif // COREFX_HAS_ARM64_BASE + + ExecuteAllTests(); + + return 100; + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/Arm64/Base.csproj b/tests/src/JIT/HardwareIntrinsics/Arm64/Base.csproj new file mode 100644 index 0000000..45dd4b6 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/Arm64/Base.csproj @@ -0,0 +1,36 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + None + True + + + + + + + + + + + + -- 2.7.4