Skip to content

Commit 14ef9e1

Browse files
committed
use intrinsics correctly
1 parent a7ca3a5 commit 14ef9e1

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

src/coreclr/inc/gcinfotypes.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,31 @@ __forceinline size_t SAFE_SHIFT_RIGHT(size_t x, size_t count)
4747

4848
inline UINT32 CeilOfLog2(size_t x)
4949
{
50-
// we want lzcnt, but bsr is ok too
50+
// it is ok to use bsr or clz unconditionally
5151
_ASSERTE(x > 0);
5252

5353
x = (x << 1) - 1;
5454

5555
#ifdef TARGET_64BIT
5656
#ifdef _MSC_VER
57-
DWORD lzcountCeil;
58-
_BitScanReverse64(&lzcountCeil, (unsigned long)x);
57+
DWORD result;
58+
_BitScanReverse64(&result, (unsigned long)x);
59+
return (UINT32)result;
5960
#else // _MSC_VER
60-
UINT32 lzcountCeil = (UINT32)__builtin_clzl((unsigned long)x);
61+
// LZCNT returns index starting from MSB, whereas BSR gives the index from LSB.
62+
// 63 ^ BSR here is equivalent to 63 - BSR since the BSR result is always between 0 and 63.
63+
// This saves an instruction, as subtraction from constant requires either MOV/SUB or NEG/ADD.
64+
return (UINT32)63 ^ (UINT32)__builtin_clzl((unsigned long)x);
6165
#endif // _MSC_VER
6266
#else // TARGET_64BIT
6367
#ifdef _MSC_VER
64-
DWORD lzcountCeil;
65-
_BitScanReverse(&lzcountCeil, (unsigned long)x);
68+
DWORD result;
69+
_BitScanReverse(&result, (unsigned int)x);
70+
return (UINT32)result;
6671
#else // _MSC_VER
67-
UINT32 lzcountCeil = (UINT32)__builtin_clz((unsigned int)x);
72+
return (UINT32)31 ^ (UINT32)__builtin_clz((unsigned int)x);
6873
#endif // _MSC_VER
6974
#endif
70-
71-
return BITS_PER_SIZE_T - lzcountCeil;
7275
}
7376

7477
enum GcSlotFlags

0 commit comments

Comments
 (0)