Skip to content

Commit

Permalink
Optimize System.HexConverter.IsHexChar on 64 bits (#52470)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 authored May 11, 2021
1 parent 22bfc75 commit 0ee10e9
Showing 1 changed file with 25 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/libraries/Common/src/System/HexConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,31 @@ public static int FromLowerChar(int c)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHexChar(int c)
{
if (IntPtr.Size == 8)
{
// This code path, when used, has no branches and doesn't depend on cache hits,
// so it's faster and does not vary in speed depending on input data distribution.
// We only use this logic on 64-bit systems, as using 64 bit values would otherwise
// be much slower than just using the lookup table anyway (no hardware support).
// The magic constant 18428868213665201664 is a 64 bit value containing 1s at the
// indices corresponding to all the valid hex characters (ie. "0123456789ABCDEFabcdef")
// minus 48 (ie. '0'), and backwards (so from the most significant bit and downwards).
// The offset of 48 for each bit is necessary so that the entire range fits in 64 bits.
// First, we subtract '0' to the input digit (after casting to uint to account for any
// negative inputs). Note that even if this subtraction underflows, this happens before
// the result is zero-extended to ulong, meaning that `i` will always have upper 32 bits
// equal to 0. We then left shift the constant with this offset, and apply a bitmask that
// has the highest bit set (the sign bit) if and only if `c` is in the ['0', '0' + 64) range.
// Then we only need to check whether this final result is less than 0: this will only be
// the case if both `i` was in fact the index of a set bit in the magic constant, and also
// `c` was in the allowed range (this ensures that false positive bit shifts are ignored).
ulong i = (uint)c - '0';
ulong shift = 18428868213665201664UL << (int)i;
ulong mask = i - 64;

return (long)(shift & mask) < 0 ? true : false;
}

return FromChar(c) != 0xFF;
}

Expand Down

0 comments on commit 0ee10e9

Please sign in to comment.