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:
parent
26bb3e1acf
commit
08e4a1a4dc
20 changed files with 108 additions and 115 deletions
|
@ -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>(); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue