base: Make 'findLsbSetFallback' constexpr to fix gcc-8 comp

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
This commit is contained in:
Bobby R. Bruce
2023-08-18 16:39:28 -07:00
parent fe43e4a3e3
commit 709f632730

View File

@@ -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<sizeof(ones) * CHAR_BIT>(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
*/