From b973a1b377c2801bc72425421d6794bbc70269e3 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 2 Sep 2024 14:16:05 -0400 Subject: [PATCH] kernel/util: Add fls to BitUtils. Implemented using __builtin_clz where available, otherwise using an algorithm derived from "Bit Twiddling Hacks" which is similar to the one ramfs uses. GCC and Clang seem to unroll the loop on x86 at least (but it doesn't matter there as the builtin exists, implemented using the "bsr" instruction.) --- headers/private/kernel/util/BitUtils.h | 25 +++++++++ src/add-ons/kernel/file_systems/ramfs/Misc.h | 56 -------------------- 2 files changed, 25 insertions(+), 56 deletions(-) diff --git a/headers/private/kernel/util/BitUtils.h b/headers/private/kernel/util/BitUtils.h index e4169dffe8..ed092caab7 100644 --- a/headers/private/kernel/util/BitUtils.h +++ b/headers/private/kernel/util/BitUtils.h @@ -40,6 +40,31 @@ count_set_bits(uint32 v) } +static inline uint32 +fls(uint32 value) +{ + if (value == 0) + return 0; + +#if __has_builtin(__builtin_clz) + return ((sizeof(value) * 8) - __builtin_clz(value)); +#else + // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog + static const uint32 masks[] = { + 0xaaaaaaaa, + 0xcccccccc, + 0xf0f0f0f0, + 0xff00ff00, + 0xffff0000 + }; + uint32 result = (value & masks[0]) != 0; + for (int i = 4; i > 0; i--) + result |= ((value & masks[i]) != 0) << i; + return result + 1; +#endif +} + + static inline uint32 log2(uint32 v) { diff --git a/src/add-ons/kernel/file_systems/ramfs/Misc.h b/src/add-ons/kernel/file_systems/ramfs/Misc.h index d869777e7f..e609287bf7 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Misc.h +++ b/src/add-ons/kernel/file_systems/ramfs/Misc.h @@ -17,62 +17,6 @@ static inline C min(const C &a, const C &b) { return (a < b ? a : b); } template static inline C max(const C &a, const C &b) { return (a > b ? a : b); } -// find last (most significant) set bit -static inline -int -fls(uint32 value) -{ - if (!value) - return -1; - int index = 0; -#define HAND_OPTIMIZED_FLS 1 -#if !HAND_OPTIMIZED_FLS -// This is the algorithm in its pure form. - const uint32 masks[] = { - 0xffff0000, - 0xff00ff00, - 0xf0f0f0f0, - 0xcccccccc, - 0xaaaaaaaa, - }; - int range = 16; - for (int i = 0; i < 5; i++) { - if (value & masks[i]) { - index += range; - value &= masks[i]; - } - range /= 2; - } -#else // HAND_OPTIMIZED_FLS -// This is how the compiler should optimize it for us: Unroll the loop and -// inline the masks. - // 0: 0xffff0000 - if (value & 0xffff0000) { - index += 16; - value &= 0xffff0000; - } - // 1: 0xff00ff00 - if (value & 0xff00ff00) { - index += 8; - value &= 0xff00ff00; - } - // 2: 0xf0f0f0f0 - if (value & 0xf0f0f0f0) { - index += 4; - value &= 0xf0f0f0f0; - } - // 3: 0xcccccccc - if (value & 0xcccccccc) { - index += 2; - value &= 0xcccccccc; - } - // 4: 0xaaaaaaaa - if (value & 0xaaaaaaaa) - index++; -#endif // HAND_OPTIMIZED_FLS - return index; -} - // node_child_hash static inline uint32