Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BitOperations arm64 intrinsic for LeadingZeroCount, TrailingZeroCount and Log2 #34486

Merged
merged 5 commits into from
Apr 4, 2020
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86;
using System.Runtime.Intrinsics.Arm;
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved

#if SYSTEM_PRIVATE_CORELIB
using Internal.Runtime.CompilerServices;
Expand Down Expand Up @@ -61,6 +62,11 @@ public static int LeadingZeroCount(uint value)
return (int)Lzcnt.LeadingZeroCount(value);
}

if (ArmBase.IsSupported)
{
return (int)ArmBase.LeadingZeroCount(value);
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved
}

// Unguarded fallback contract is 0->31
if (value == 0)
{
Expand All @@ -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);
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved
}

uint hi = (uint)(value >> 32);

if (hi == 0)
Expand All @@ -104,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
Expand All @@ -113,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);
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved
}

// Fallback contract is 0->0
return Log2SoftwareFallback(value);
}
Expand All @@ -136,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);
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved
}

uint hi = (uint)(value >> 32);

if (hi == 0)
Expand Down Expand Up @@ -275,6 +296,11 @@ public static int TrailingZeroCount(uint value)
return (int)Bmi1.TrailingZeroCount(value);
}

if (ArmBase.IsSupported)
{
return (int)ArmBase.LeadingZeroCount(ArmBase.ReverseElementBits(value));
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved
}

// Unguarded fallback contract is 0->0
if (value == 0)
{
Expand Down Expand Up @@ -313,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));
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved
}
uint lo = (uint)value;

if (lo == 0)
Expand Down