From 709f632730d66f03977b29c60bfbddc0689e909a Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 18 Aug 2023 16:39:28 -0700 Subject: [PATCH] base: Make 'findLsbSetFallback' constexpr to fix gcc-8 comp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compilation bug found on: https://github.com/gem5/gem5/actions/runs/5899831222/job/16002984553 In gcc Version 8 and below the following error is received: ``` src/base/bitfield.hh: In function ‘constexpr int gem5::findLsbSet(uint64_t)’: src/base/bitfield.hh:365:34: error: call to non-‘constexpr’ function ‘int gem5::{anonymous}::findLsbSetFallback(uint64_t)’ return findLsbSetFallback(val); ~~~~~~~~~~~~~~~~~~^~~~~ scons: *** [build/ALL/kern/linux/events.o] Error 1 ``` `findLsbSet` cannot be `constexr` as it calls non-constexpr function `findLsbSetFallback`. `findLsbSetFallback`. The problematic function is the `count` on the std::bitset. This patch changes this to a constexpr. Change-Id: I48bd15d03e4615148be6c4d926a3c9c2f777dc3c --- src/base/bitfield.hh | 54 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 29f8929065..bceed60f4e 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -325,33 +325,43 @@ hasBuiltinCtz() { } [[maybe_unused]] -int +constexpr int findLsbSetFallback(uint64_t val) { - // Create a mask with val's trailing zeros flipped to 1, lsb set flipped to - // 0 and the rest unchanged. This effectively is equivalent to doing -1. - // e.g.: 0101000 - 1 = 0100111 - // ^^^^ ^^^^ - auto mask = val - 1; - // This will create a mask of ones from lsb set to last bit - // e.g.: 0101000 ^ 0100111 = 00001111 - // ^^^^ ^^^^ - auto masked = val ^ mask; - // Shift that mask to that there is 1s only where there was 0s after the - // lsb set before - // e.g.: 00001111 >> 1 = 00000111 (val is 0101000 in the example) - auto ones = masked >> 1; - // Number of bit set is the lsb set. This operation should be optimized by - // the compiler without unsing intrinsics. This operation will become - // constexpr starting from C++23. In the meantime, that fallback should not - // be used much in favor of the constexpr intrinsic - return std::bitset(ones).count(); -} + int lsb = 0; + if (!val) { + return sizeof(val) * 8; + } + if (!bits(val, 31, 0)) { + lsb += 32; + val >>= 32; + } + if (!bits(val, 15, 0)) { + lsb += 16; + val >>= 16; + } + if (!bits(val, 7, 0)) { + lsb += 8; + val >>= 8; + } + if (!bits(val, 3, 0)) { + lsb += 4; + val >>= 4; + } + if (!bits(val, 1, 0)) { + lsb += 2; + val >>= 2; + } + if (!bits(val, 0, 0)) { + lsb += 1; + } + return lsb; } +} // anonymous namespace /** * Returns the bit position of the LSB that is set in the input - * That function will either use a builting that exploit a "count trailing - * zeros" instruction or use a bit-fidling algorithm explained bellow. + * That function will either use a builtin that exploit a "count trailing + * zeros" instruction or use fall back method, `findLsbSetFallback`. * * @ingroup api_bitfield */