From d6509b6910580ee3ce0e145c1af7067708e1cc93 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 6 Feb 2023 06:35:22 -0800 Subject: [PATCH] Have gen* methods use the optimized BitOperations where possible --- src/coreclr/jit/compiler.h | 4 +- src/coreclr/jit/compiler.hpp | 136 +++++++++++++++-------------------- src/coreclr/jit/utils.cpp | 4 +- 3 files changed, 61 insertions(+), 83 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 45dbbec2eb2674..fbf1ddad015568 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -121,8 +121,8 @@ void* operator new[](size_t n, Compiler* context, CompMemKind cmk); /*****************************************************************************/ -unsigned genLog2(unsigned value); -unsigned genLog2(unsigned __int64 value); +uint32_t genLog2(uint32_t value); +uint32_t genLog2(uint64_t value); unsigned ReinterpretHexAsDecimal(unsigned in); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 94dcf70963a413..074afe4881a6e6 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -91,12 +91,23 @@ inline RoundLevel getRoundFloatLevel() * Return the lowest bit that is set */ -template -inline T genFindLowestBit(T value) +inline uint32_t genFindLowestBit(uint32_t value) { return (value & (0 - value)); } +inline uint64_t genFindLowestBit(uint64_t value) +{ + return (value & (0 - value)); +} + +#ifdef __APPLE__ +inline size_t genFindLowestBit(size_t value) +{ + return (value & (0 - value)); +} +#endif // __APPLE__ + //------------------------------------------------------------------------ // genFindHighestBit: Return the highest bit that is set (that is, a mask that includes just the // highest bit). @@ -107,16 +118,10 @@ inline T genFindLowestBit(T value) // Note: // It performs the "LeadingZeroCount " operation using intrinsics and then mask out everything // but the highest bit. -inline unsigned int genFindHighestBit(unsigned int mask) +inline uint32_t genFindHighestBit(uint32_t mask) { assert(mask != 0); -#if defined(_MSC_VER) - unsigned long index; -#else - unsigned int index; -#endif - BitScanReverse(&index, mask); - return 1L << index; + return static_cast(1) << BitOperations::BitScanReverse(mask); } //------------------------------------------------------------------------ @@ -129,82 +134,54 @@ inline unsigned int genFindHighestBit(unsigned int mask) // Note: // It performs the "LeadingZeroCount " operation using intrinsics and then mask out everything // but the highest bit. -inline unsigned __int64 genFindHighestBit(unsigned __int64 mask) +inline uint64_t genFindHighestBit(uint64_t mask) { assert(mask != 0); -#if defined(_MSC_VER) - unsigned long index; -#else - unsigned int index; -#endif - BitScanReverse64(&index, mask); - return 1LL << index; + return static_cast(1) << BitOperations::BitScanReverse(mask); } /***************************************************************************** * -* Return true if the given 64-bit value has exactly zero or one bits set. +* Return true if the given value has exactly zero or one bits set. */ -template -inline bool genMaxOneBit(T value) +inline bool genMaxOneBit(uint32_t value) { return (value & (value - 1)) == 0; } -/***************************************************************************** -* -* Return true if the given 32-bit value has exactly zero or one bits set. -*/ - -inline bool genMaxOneBit(unsigned value) +inline bool genMaxOneBit(uint64_t value) { return (value & (value - 1)) == 0; } /***************************************************************************** * -* Return true if the given 64-bit value has exactly one bit set. +* Return true if the given value has exactly one bit set. */ -template -inline bool genExactlyOneBit(T value) +inline bool genExactlyOneBit(uint32_t value) { - return ((value != 0) && genMaxOneBit(value)); + return genMaxOneBit(value) && (value != 0); } -/***************************************************************************** -* -* Return true if the given 32-bit value has exactly zero or one bits set. -*/ - -inline bool genExactlyOneBit(unsigned value) +inline bool genExactlyOneBit(uint64_t value) { - return ((value != 0) && genMaxOneBit(value)); -} - -/***************************************************************************** - * - * Given a value that has exactly one bit set, return the position of that - * bit, in other words return the logarithm in base 2 of the given value. - */ -inline unsigned genLog2(unsigned value) -{ - return BitPosition(value); + return genMaxOneBit(value) && (value != 0); } // Given an unsigned 64-bit value, returns the lower 32-bits in unsigned format // -inline unsigned ulo32(unsigned __int64 value) +inline uint32_t ulo32(uint64_t value) { - return static_cast(value); + return static_cast(value); } // Given an unsigned 64-bit value, returns the upper 32-bits in unsigned format // -inline unsigned uhi32(unsigned __int64 value) +inline uint32_t uhi32(uint64_t value) { - return static_cast(value >> 32); + return static_cast(value >> 32); } /***************************************************************************** @@ -213,30 +190,25 @@ inline unsigned uhi32(unsigned __int64 value) * bit, in other words return the logarithm in base 2 of the given value. */ -inline unsigned genLog2(unsigned __int64 value) +inline uint32_t genLog2(uint32_t value) { -#ifdef HOST_64BIT - return BitPosition(value); -#else // HOST_32BIT - unsigned lo32 = ulo32(value); - unsigned hi32 = uhi32(value); + // This isn't a true log2 but rather a "log2 for pow2" + assert(genExactlyOneBit(value)); + return BitOperations::BitScanForward(value); +} - if (lo32 != 0) - { - assert(hi32 == 0); - return genLog2(lo32); - } - else - { - return genLog2(hi32) + 32; - } -#endif +inline uint32_t genLog2(uint64_t value) +{ + // This isn't a true log2 but rather a "log2 for pow2" + assert(genExactlyOneBit(value)); + return BitOperations::BitScanForward(value); } #ifdef __APPLE__ -inline unsigned genLog2(size_t value) +inline uint32_t genLog2(size_t value) { - return genLog2((unsigned __int64)value); + // This isn't a true log2 but rather a "log2 for pow2" + return genLog2(static_cast(value)); } #endif // __APPLE__ @@ -255,18 +227,24 @@ inline regMaskTP genFindLowestReg(regMaskTP value) * A rather simple routine that counts the number of bits in a given number. */ -template -inline unsigned genCountBits(T bits) +inline uint32_t genCountBits(int32_t bits) { - unsigned cnt = 0; + return BitOperations::PopCount(static_cast(bits)); +} - while (bits) - { - cnt++; - bits -= genFindLowestBit(bits); - } +inline uint32_t genCountBits(int64_t bits) +{ + return BitOperations::PopCount(static_cast(bits)); +} + +inline uint32_t genCountBits(uint32_t bits) +{ + return BitOperations::PopCount(bits); +} - return cnt; +inline uint32_t genCountBits(uint64_t bits) +{ + return BitOperations::PopCount(bits); } /***************************************************************************** diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp index bf5181be76a0a1..37df548d33987e 100644 --- a/src/coreclr/jit/utils.cpp +++ b/src/coreclr/jit/utils.cpp @@ -2716,7 +2716,7 @@ uint32_t BitOperations::Log2(uint32_t value) { // The 0->0 contract is fulfilled by setting the LSB to 1. // Log(1) is 0, and setting the LSB for values > 1 does not change the log2 result. - return 31 ^ BitOperations::LeadingZeroCount(value | 1); + return BitOperations::BitScanReverse(value | 1); } //------------------------------------------------------------------------ @@ -2732,7 +2732,7 @@ uint32_t BitOperations::Log2(uint64_t value) { // The 0->0 contract is fulfilled by setting the LSB to 1. // Log(1) is 0, and setting the LSB for values > 1 does not change the log2 result. - return 63 ^ BitOperations::LeadingZeroCount(value | 1); + return BitOperations::BitScanReverse(value | 1); } //------------------------------------------------------------------------