1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 08:44:58 +00:00

AK+Everywhere: Replace __builtin bit functions

In order to reduce our reliance on __builtin_{ffs, clz, ctz, popcount},
this commit removes all calls to these functions and replaces them with
the equivalent functions in AK/BuiltinWrappers.h.
This commit is contained in:
Nick Johnson 2021-12-19 15:46:55 -06:00 committed by Andreas Kling
parent 26bb3e1acf
commit 08e4a1a4dc
20 changed files with 108 additions and 115 deletions

View file

@ -54,30 +54,30 @@ public:
byte &= bitmask_first_byte[start % 8];
if (first == last) {
byte &= bitmask_last_byte[(start + len) % 8];
count = __builtin_popcount(byte);
count = popcount(byte);
} else {
count = __builtin_popcount(byte);
count = popcount(byte);
// Don't access *last if it's out of bounds
if (last < &m_data[size_in_bytes()]) {
byte = *last;
byte &= bitmask_last_byte[(start + len) % 8];
count += __builtin_popcount(byte);
count += popcount(byte);
}
if (++first < last) {
const u32* ptr32 = (const u32*)(((FlatPtr)first + sizeof(u32) - 1) & ~(sizeof(u32) - 1));
if ((const u8*)ptr32 > last)
ptr32 = (const u32*)last;
while (first < (const u8*)ptr32) {
count += __builtin_popcount(*first);
const size_t* ptr_large = (const size_t*)(((FlatPtr)first + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1));
if ((const u8*)ptr_large > last)
ptr_large = (const size_t*)last;
while (first < (const u8*)ptr_large) {
count += popcount(*first);
first++;
}
const u32* last32 = (const u32*)((FlatPtr)last & ~(sizeof(u32) - 1));
while (ptr32 < last32) {
count += __builtin_popcountl(*ptr32);
ptr32++;
const size_t* last_large = (const size_t*)((FlatPtr)last & ~(sizeof(size_t) - 1));
while (ptr_large < last_large) {
count += popcount(*ptr_large);
ptr_large++;
}
for (first = (const u8*)ptr32; first < last; first++)
count += __builtin_popcount(*first);
for (first = (const u8*)ptr_large; first < last; first++)
count += popcount(*first);
}
}
@ -100,34 +100,34 @@ public:
// We will use hint as what it is: a hint. Because we try to
// scan over entire 32 bit words, we may start searching before
// the hint!
const u32* ptr32 = (const u32*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(u32) - 1));
if ((const u8*)ptr32 < &m_data[0]) {
ptr32++;
const size_t* ptr_large = (const size_t*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(size_t) - 1));
if ((const u8*)ptr_large < &m_data[0]) {
ptr_large++;
// m_data isn't aligned, check first bytes
size_t start_ptr32 = (const u8*)ptr32 - &m_data[0];
size_t start_ptr_large = (const u8*)ptr_large - &m_data[0];
size_t i = 0;
u8 byte = VALUE ? 0x00 : 0xff;
while (i < start_ptr32 && m_data[i] == byte)
while (i < start_ptr_large && m_data[i] == byte)
i++;
if (i < start_ptr32) {
if (i < start_ptr_large) {
byte = m_data[i];
if constexpr (!VALUE)
byte = ~byte;
VERIFY(byte != 0);
return i * 8 + __builtin_ffs(byte) - 1;
return i * 8 + bit_scan_forward(byte) - 1;
}
}
u32 val32 = VALUE ? 0x0 : 0xffffffff;
const u32* end32 = (const u32*)((FlatPtr)end & ~(sizeof(u32) - 1));
while (ptr32 < end32 && *ptr32 == val32)
ptr32++;
size_t val_large = VALUE ? 0x0 : NumericLimits<size_t>::max();
const size_t* end_large = (const size_t*)((FlatPtr)end & ~(sizeof(size_t) - 1));
while (ptr_large < end_large && *ptr_large == val_large)
ptr_large++;
if (ptr32 == end32) {
if (ptr_large == end_large) {
// We didn't find anything, check the remaining few bytes (if any)
u8 byte = VALUE ? 0x00 : 0xff;
size_t i = (const u8*)ptr32 - &m_data[0];
size_t i = (const u8*)ptr_large - &m_data[0];
size_t byte_count = m_size / 8;
VERIFY(i <= byte_count);
while (i < byte_count && m_data[i] == byte)
@ -137,7 +137,7 @@ public:
return {}; // We already checked from the beginning
// Try scanning before the hint
end = (const u8*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(u32) - 1));
end = (const u8*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(size_t) - 1));
hint = 0;
continue;
}
@ -145,16 +145,16 @@ public:
if constexpr (!VALUE)
byte = ~byte;
VERIFY(byte != 0);
return i * 8 + __builtin_ffs(byte) - 1;
return i * 8 + bit_scan_forward(byte) - 1;
}
// NOTE: We don't really care about byte ordering. We found *one*
// free bit, just calculate the position and return it
val32 = *ptr32;
val_large = *ptr_large;
if constexpr (!VALUE)
val32 = ~val32;
VERIFY(val32 != 0);
return ((const u8*)ptr32 - &m_data[0]) * 8 + __builtin_ffsl(val32) - 1;
val_large = ~val_large;
VERIFY(val_large != 0);
return ((const u8*)ptr_large - &m_data[0]) * 8 + bit_scan_forward(val_large) - 1;
}
}
@ -184,7 +184,7 @@ public:
if constexpr (!VALUE)
byte = ~byte;
VERIFY(byte != 0);
return i * 8 + __builtin_ffs(byte) - 1;
return i * 8 + bit_scan_forward(byte) - 1;
}
Optional<size_t> find_first_set() const { return find_first<true>(); }