From cc04050d36a20f46fab06e0bbffeb1d09d4ea0f3 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 2 Apr 2020 18:28:24 -0700 Subject: [PATCH 1/5] ARM64 intrinsic for LeadingZeroCount --- .../src/System/Numerics/BitOperations.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index 2506043f6f7215..faf11460785b98 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.X86; +using System.Runtime.Intrinsics.Arm; #if SYSTEM_PRIVATE_CORELIB using Internal.Runtime.CompilerServices; @@ -61,6 +62,11 @@ public static int LeadingZeroCount(uint value) return (int)Lzcnt.LeadingZeroCount(value); } + if (ArmBase.IsSupported) + { + return (int)ArmBase.LeadingZeroCount(value); + } + // Unguarded fallback contract is 0->31 if (value == 0) { @@ -85,6 +91,11 @@ public static int LeadingZeroCount(ulong value) return (int)Lzcnt.X64.LeadingZeroCount(value); } + if (ArmBase.Arm64.IsSupported) + { + return (int)ArmBase.Arm64.LeadingZeroCount(value); + } + uint hi = (uint)(value >> 32); if (hi == 0) From 90be48cc66f465429167fbea50f6f82a189dc2f6 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 2 Apr 2020 18:28:49 -0700 Subject: [PATCH 2/5] ARM64 intrinsic for Log2 --- .../src/System/Numerics/BitOperations.cs | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index faf11460785b98..19b82e30503023 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -115,6 +115,12 @@ public static int LeadingZeroCount(ulong value) [CLSCompliant(false)] public static int Log2(uint value) { + // Enforce conventional contract 0->0 (Log(0) is undefined) + if (value == 0) + { + return 0; + } + // value lzcnt actual expected // ..0000 32 0 0 (by convention, guard clause) // ..0001 31 31-31 0 @@ -124,16 +130,15 @@ public static int Log2(uint value) // 1000.. 0 31-0 31 if (Lzcnt.IsSupported) { - // Enforce conventional contract 0->0 (Log(0) is undefined) - if (value == 0) - { - return 0; - } - // LZCNT contract is 0->32 return 31 - (int)Lzcnt.LeadingZeroCount(value); } + if (ArmBase.IsSupported) + { + return 31 - (int)ArmBase.LeadingZeroCount(value); + } + // Fallback contract is 0->0 return Log2SoftwareFallback(value); } @@ -147,18 +152,23 @@ public static int Log2(uint value) [CLSCompliant(false)] public static int Log2(ulong value) { - if (Lzcnt.X64.IsSupported) + // Enforce conventional contract 0->0 (Log(0) is undefined) + if (value == 0) { - // Enforce conventional contract 0->0 (Log(0) is undefined) - if (value == 0) - { - return 0; - } + return 0; + } + if (Lzcnt.X64.IsSupported) + { // LZCNT contract is 0->64 return 63 - (int)Lzcnt.X64.LeadingZeroCount(value); } + if (ArmBase.Arm64.IsSupported) + { + return 63 - (int)ArmBase.Arm64.LeadingZeroCount(value); + } + uint hi = (uint)(value >> 32); if (hi == 0) From a2effc7312833db838eca6ce4afc02a5730dbd1e Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 2 Apr 2020 17:54:08 -0700 Subject: [PATCH 3/5] ARM64 intrinsic for TrailingZeroCount --- .../src/System/Numerics/BitOperations.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index 19b82e30503023..131fa43c149aca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -296,6 +296,11 @@ public static int TrailingZeroCount(uint value) return (int)Bmi1.TrailingZeroCount(value); } + if (ArmBase.IsSupported) + { + return (int)ArmBase.LeadingZeroCount(ArmBase.ReverseElementBits(value)); + } + // Unguarded fallback contract is 0->0 if (value == 0) { @@ -334,6 +339,10 @@ public static int TrailingZeroCount(ulong value) return (int)Bmi1.X64.TrailingZeroCount(value); } + if (ArmBase.Arm64.IsSupported) + { + return (int)ArmBase.Arm64.LeadingZeroCount(ArmBase.Arm64.ReverseElementBits(value)); + } uint lo = (uint)value; if (lo == 0) From cdf34f96b35ba779bc6c944ad3450f35957ce4e9 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 3 Apr 2020 11:57:47 -0700 Subject: [PATCH 4/5] Remove redundant cast --- .../src/System/Numerics/BitOperations.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index 131fa43c149aca..9844240e1058a3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -4,8 +4,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; #if SYSTEM_PRIVATE_CORELIB using Internal.Runtime.CompilerServices; @@ -64,7 +64,7 @@ public static int LeadingZeroCount(uint value) if (ArmBase.IsSupported) { - return (int)ArmBase.LeadingZeroCount(value); + return ArmBase.LeadingZeroCount(value); } // Unguarded fallback contract is 0->31 @@ -93,7 +93,7 @@ public static int LeadingZeroCount(ulong value) if (ArmBase.Arm64.IsSupported) { - return (int)ArmBase.Arm64.LeadingZeroCount(value); + return ArmBase.Arm64.LeadingZeroCount(value); } uint hi = (uint)(value >> 32); @@ -136,7 +136,7 @@ public static int Log2(uint value) if (ArmBase.IsSupported) { - return 31 - (int)ArmBase.LeadingZeroCount(value); + return 31 - ArmBase.LeadingZeroCount(value); } // Fallback contract is 0->0 @@ -166,7 +166,7 @@ public static int Log2(ulong value) if (ArmBase.Arm64.IsSupported) { - return 63 - (int)ArmBase.Arm64.LeadingZeroCount(value); + return 63 - ArmBase.Arm64.LeadingZeroCount(value); } uint hi = (uint)(value >> 32); @@ -298,7 +298,7 @@ public static int TrailingZeroCount(uint value) if (ArmBase.IsSupported) { - return (int)ArmBase.LeadingZeroCount(ArmBase.ReverseElementBits(value)); + return ArmBase.LeadingZeroCount(ArmBase.ReverseElementBits(value)); } // Unguarded fallback contract is 0->0 @@ -341,7 +341,7 @@ public static int TrailingZeroCount(ulong value) if (ArmBase.Arm64.IsSupported) { - return (int)ArmBase.Arm64.LeadingZeroCount(ArmBase.Arm64.ReverseElementBits(value)); + return ArmBase.Arm64.LeadingZeroCount(ArmBase.Arm64.ReverseElementBits(value)); } uint lo = (uint)value; From 80ff885d3f41b79225665e580c3bdf26e2cff2aa Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 3 Apr 2020 11:58:15 -0700 Subject: [PATCH 5/5] Add entry of System.Runtime.Intrinsic.Arm in shim --- .../Runtime/Intrinsics/Intrinsics.Shims.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs b/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs index 12fba80e1a98f2..33c59a3f122db9 100644 --- a/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs +++ b/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs @@ -103,3 +103,19 @@ public abstract class X64 public static bool TestZ(Vector128 left, Vector128 right) => throw new PlatformNotSupportedException(); } } + +namespace System.Runtime.Intrinsics.Arm +{ + internal abstract class ArmBase + { + public abstract class Arm64 + { + public const bool IsSupported = false; + public static int LeadingZeroCount(ulong value) => throw new PlatformNotSupportedException(); + public static uint ReverseElementBits(ulong value) => throw new PlatformNotSupportedException(); + } + public const bool IsSupported = false; + public static int LeadingZeroCount(uint value) => throw new PlatformNotSupportedException(); + public static uint ReverseElementBits(uint value) => throw new PlatformNotSupportedException(); + } +}