mirror of
https://github.com/RGBCube/serenity
synced 2025-07-08 20:37:35 +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];
|
byte &= bitmask_first_byte[start % 8];
|
||||||
if (first == last) {
|
if (first == last) {
|
||||||
byte &= bitmask_last_byte[(start + len) % 8];
|
byte &= bitmask_last_byte[(start + len) % 8];
|
||||||
count = __builtin_popcount(byte);
|
count = popcount(byte);
|
||||||
} else {
|
} else {
|
||||||
count = __builtin_popcount(byte);
|
count = popcount(byte);
|
||||||
// Don't access *last if it's out of bounds
|
// Don't access *last if it's out of bounds
|
||||||
if (last < &m_data[size_in_bytes()]) {
|
if (last < &m_data[size_in_bytes()]) {
|
||||||
byte = *last;
|
byte = *last;
|
||||||
byte &= bitmask_last_byte[(start + len) % 8];
|
byte &= bitmask_last_byte[(start + len) % 8];
|
||||||
count += __builtin_popcount(byte);
|
count += popcount(byte);
|
||||||
}
|
}
|
||||||
if (++first < last) {
|
if (++first < last) {
|
||||||
const u32* ptr32 = (const u32*)(((FlatPtr)first + sizeof(u32) - 1) & ~(sizeof(u32) - 1));
|
const size_t* ptr_large = (const size_t*)(((FlatPtr)first + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1));
|
||||||
if ((const u8*)ptr32 > last)
|
if ((const u8*)ptr_large > last)
|
||||||
ptr32 = (const u32*)last;
|
ptr_large = (const size_t*)last;
|
||||||
while (first < (const u8*)ptr32) {
|
while (first < (const u8*)ptr_large) {
|
||||||
count += __builtin_popcount(*first);
|
count += popcount(*first);
|
||||||
first++;
|
first++;
|
||||||
}
|
}
|
||||||
const u32* last32 = (const u32*)((FlatPtr)last & ~(sizeof(u32) - 1));
|
const size_t* last_large = (const size_t*)((FlatPtr)last & ~(sizeof(size_t) - 1));
|
||||||
while (ptr32 < last32) {
|
while (ptr_large < last_large) {
|
||||||
count += __builtin_popcountl(*ptr32);
|
count += popcount(*ptr_large);
|
||||||
ptr32++;
|
ptr_large++;
|
||||||
}
|
}
|
||||||
for (first = (const u8*)ptr32; first < last; first++)
|
for (first = (const u8*)ptr_large; first < last; first++)
|
||||||
count += __builtin_popcount(*first);
|
count += popcount(*first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,34 +100,34 @@ public:
|
||||||
// We will use hint as what it is: a hint. Because we try to
|
// 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
|
// scan over entire 32 bit words, we may start searching before
|
||||||
// the hint!
|
// the hint!
|
||||||
const u32* ptr32 = (const u32*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(u32) - 1));
|
const size_t* ptr_large = (const size_t*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(size_t) - 1));
|
||||||
if ((const u8*)ptr32 < &m_data[0]) {
|
if ((const u8*)ptr_large < &m_data[0]) {
|
||||||
ptr32++;
|
ptr_large++;
|
||||||
|
|
||||||
// m_data isn't aligned, check first bytes
|
// 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;
|
size_t i = 0;
|
||||||
u8 byte = VALUE ? 0x00 : 0xff;
|
u8 byte = VALUE ? 0x00 : 0xff;
|
||||||
while (i < start_ptr32 && m_data[i] == byte)
|
while (i < start_ptr_large && m_data[i] == byte)
|
||||||
i++;
|
i++;
|
||||||
if (i < start_ptr32) {
|
if (i < start_ptr_large) {
|
||||||
byte = m_data[i];
|
byte = m_data[i];
|
||||||
if constexpr (!VALUE)
|
if constexpr (!VALUE)
|
||||||
byte = ~byte;
|
byte = ~byte;
|
||||||
VERIFY(byte != 0);
|
VERIFY(byte != 0);
|
||||||
return i * 8 + __builtin_ffs(byte) - 1;
|
return i * 8 + bit_scan_forward(byte) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 val32 = VALUE ? 0x0 : 0xffffffff;
|
size_t val_large = VALUE ? 0x0 : NumericLimits<size_t>::max();
|
||||||
const u32* end32 = (const u32*)((FlatPtr)end & ~(sizeof(u32) - 1));
|
const size_t* end_large = (const size_t*)((FlatPtr)end & ~(sizeof(size_t) - 1));
|
||||||
while (ptr32 < end32 && *ptr32 == val32)
|
while (ptr_large < end_large && *ptr_large == val_large)
|
||||||
ptr32++;
|
ptr_large++;
|
||||||
|
|
||||||
if (ptr32 == end32) {
|
if (ptr_large == end_large) {
|
||||||
// We didn't find anything, check the remaining few bytes (if any)
|
// We didn't find anything, check the remaining few bytes (if any)
|
||||||
u8 byte = VALUE ? 0x00 : 0xff;
|
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;
|
size_t byte_count = m_size / 8;
|
||||||
VERIFY(i <= byte_count);
|
VERIFY(i <= byte_count);
|
||||||
while (i < byte_count && m_data[i] == byte)
|
while (i < byte_count && m_data[i] == byte)
|
||||||
|
@ -137,7 +137,7 @@ public:
|
||||||
return {}; // We already checked from the beginning
|
return {}; // We already checked from the beginning
|
||||||
|
|
||||||
// Try scanning before the hint
|
// 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;
|
hint = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -145,16 +145,16 @@ public:
|
||||||
if constexpr (!VALUE)
|
if constexpr (!VALUE)
|
||||||
byte = ~byte;
|
byte = ~byte;
|
||||||
VERIFY(byte != 0);
|
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*
|
// NOTE: We don't really care about byte ordering. We found *one*
|
||||||
// free bit, just calculate the position and return it
|
// free bit, just calculate the position and return it
|
||||||
val32 = *ptr32;
|
val_large = *ptr_large;
|
||||||
if constexpr (!VALUE)
|
if constexpr (!VALUE)
|
||||||
val32 = ~val32;
|
val_large = ~val_large;
|
||||||
VERIFY(val32 != 0);
|
VERIFY(val_large != 0);
|
||||||
return ((const u8*)ptr32 - &m_data[0]) * 8 + __builtin_ffsl(val32) - 1;
|
return ((const u8*)ptr_large - &m_data[0]) * 8 + bit_scan_forward(val_large) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ public:
|
||||||
if constexpr (!VALUE)
|
if constexpr (!VALUE)
|
||||||
byte = ~byte;
|
byte = ~byte;
|
||||||
VERIFY(byte != 0);
|
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>(); }
|
Optional<size_t> find_first_set() const { return find_first<true>(); }
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Concepts.h"
|
#include "Concepts.h"
|
||||||
#include "Platform.h"
|
|
||||||
|
|
||||||
template<Unsigned IntType>
|
template<Unsigned IntType>
|
||||||
inline constexpr int popcount(IntType value)
|
inline constexpr int popcount(IntType value)
|
||||||
|
@ -108,3 +107,25 @@ inline constexpr int count_leading_zeroes_safe(IntType value)
|
||||||
return 8 * sizeof(IntType);
|
return 8 * sizeof(IntType);
|
||||||
return count_leading_zeroes(value);
|
return count_leading_zeroes(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The function will return the number of leading zeroes in the type. If
|
||||||
|
// the given number is zero, this function will return the number of bits
|
||||||
|
// in the IntType.
|
||||||
|
template<Integral IntType>
|
||||||
|
inline constexpr int bit_scan_forward(IntType value)
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
static_assert(sizeof(IntType) <= sizeof(unsigned long long));
|
||||||
|
if constexpr (sizeof(IntType) <= sizeof(unsigned int))
|
||||||
|
return __builtin_ffs(value);
|
||||||
|
if constexpr (sizeof(IntType) == sizeof(unsigned long))
|
||||||
|
return __builtin_ffsl(value);
|
||||||
|
if constexpr (sizeof(IntType) == sizeof(unsigned long long))
|
||||||
|
return __builtin_ffsll(value);
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
#else
|
||||||
|
if (value == 0)
|
||||||
|
return 0;
|
||||||
|
return 1 + count_trailing_zeroes(static_cast<MakeUnsigned<IntType>>(value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
19
AK/Math.h
19
AK/Math.h
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Concepts.h>
|
#include <AK/Concepts.h>
|
||||||
#include <AK/StdLibExtraDetails.h>
|
#include <AK/StdLibExtraDetails.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
@ -45,21 +46,6 @@ constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
|
||||||
return __builtin_##function##f(args); \
|
return __builtin_##function##f(args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INTEGER_BUILTIN(name) \
|
|
||||||
template<Integral T> \
|
|
||||||
constexpr T name(T x) \
|
|
||||||
{ \
|
|
||||||
if constexpr (sizeof(T) == sizeof(long long)) \
|
|
||||||
return __builtin_##name##ll(x); \
|
|
||||||
if constexpr (sizeof(T) == sizeof(long)) \
|
|
||||||
return __builtin_##name##l(x); \
|
|
||||||
return __builtin_##name(x); \
|
|
||||||
}
|
|
||||||
|
|
||||||
INTEGER_BUILTIN(clz);
|
|
||||||
INTEGER_BUILTIN(ctz);
|
|
||||||
INTEGER_BUILTIN(popcnt);
|
|
||||||
|
|
||||||
namespace Division {
|
namespace Division {
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
constexpr T fmod(T x, T y)
|
constexpr T fmod(T x, T y)
|
||||||
|
@ -312,7 +298,7 @@ constexpr T log2(T x)
|
||||||
template<Integral T>
|
template<Integral T>
|
||||||
constexpr T log2(T x)
|
constexpr T log2(T x)
|
||||||
{
|
{
|
||||||
return x ? 8 * sizeof(T) - clz(x) : 0;
|
return x ? 8 * sizeof(T) - count_leading_zeroes(static_cast<MakeUnsigned<T>>(x)) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
|
@ -468,6 +454,5 @@ constexpr T pow(T x, T y)
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CONSTEXPR_STATE
|
#undef CONSTEXPR_STATE
|
||||||
#undef INTEGER_BUILTIN
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,29 +106,6 @@ extern "C" {
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
ALWAYS_INLINE int count_trailing_zeroes_32(unsigned int val)
|
|
||||||
{
|
|
||||||
# if defined(__GNUC__) || defined(__clang__)
|
|
||||||
return __builtin_ctz(val);
|
|
||||||
# else
|
|
||||||
for (u8 i = 0; i < 32; ++i) {
|
|
||||||
if ((val >> i) & 1) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE int count_trailing_zeroes_32_safe(unsigned int val)
|
|
||||||
{
|
|
||||||
if (val == 0)
|
|
||||||
return 32;
|
|
||||||
return count_trailing_zeroes_32(val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef AK_OS_BSD_GENERIC
|
#ifdef AK_OS_BSD_GENERIC
|
||||||
# define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
|
# define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
|
||||||
# define CLOCK_REALTIME_COARSE CLOCK_REALTIME
|
# define CLOCK_REALTIME_COARSE CLOCK_REALTIME
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Checked.h>
|
#include <AK/Checked.h>
|
||||||
#include <AK/Concepts.h>
|
#include <AK/Concepts.h>
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
|
@ -90,9 +91,9 @@ public:
|
||||||
constexpr size_t clz() const requires(IsSame<T, u64>)
|
constexpr size_t clz() const requires(IsSame<T, u64>)
|
||||||
{
|
{
|
||||||
if (m_high)
|
if (m_high)
|
||||||
return __builtin_clzll(m_high);
|
return count_leading_zeroes(m_high);
|
||||||
else
|
else
|
||||||
return sizeof(T) * 8 + __builtin_clzll(m_low);
|
return sizeof(T) * 8 + count_leading_zeroes(m_low);
|
||||||
}
|
}
|
||||||
constexpr size_t clz() const requires(!IsSame<T, u64>)
|
constexpr size_t clz() const requires(!IsSame<T, u64>)
|
||||||
{
|
{
|
||||||
|
@ -104,9 +105,9 @@ public:
|
||||||
constexpr size_t ctz() const requires(IsSame<T, u64>)
|
constexpr size_t ctz() const requires(IsSame<T, u64>)
|
||||||
{
|
{
|
||||||
if (m_low)
|
if (m_low)
|
||||||
return __builtin_ctzll(m_low);
|
return count_trailing_zeroes(m_low);
|
||||||
else
|
else
|
||||||
return sizeof(T) * 8 + __builtin_ctzll(m_high);
|
return sizeof(T) * 8 + count_trailing_zeroes(m_high);
|
||||||
}
|
}
|
||||||
constexpr size_t ctz() const requires(!IsSame<T, u64>)
|
constexpr size_t ctz() const requires(!IsSame<T, u64>)
|
||||||
{
|
{
|
||||||
|
@ -598,7 +599,7 @@ public:
|
||||||
R x1 = *this;
|
R x1 = *this;
|
||||||
R x2 = *this * *this;
|
R x2 = *this * *this;
|
||||||
u64 exp_copy = exp;
|
u64 exp_copy = exp;
|
||||||
for (ssize_t i = sizeof(u64) * 8 - __builtin_clzll(exp) - 2; i >= 0; --i) {
|
for (ssize_t i = sizeof(u64) * 8 - count_leading_zeroes(exp) - 2; i >= 0; --i) {
|
||||||
if (exp_copy & 1u) {
|
if (exp_copy & 1u) {
|
||||||
x2 *= x1;
|
x2 *= x1;
|
||||||
x1 *= x1;
|
x1 *= x1;
|
||||||
|
@ -642,7 +643,7 @@ public:
|
||||||
|
|
||||||
U res = 1;
|
U res = 1;
|
||||||
u64 exp_copy = exp;
|
u64 exp_copy = exp;
|
||||||
for (size_t i = sizeof(u64) - __builtin_clzll(exp) - 1u; i < exp; ++i) {
|
for (size_t i = sizeof(u64) - count_leading_zeroes(exp) - 1u; i < exp; ++i) {
|
||||||
res *= res;
|
res *= res;
|
||||||
res %= mod;
|
res %= mod;
|
||||||
if (exp_copy & 1u) {
|
if (exp_copy & 1u) {
|
||||||
|
@ -682,7 +683,7 @@ public:
|
||||||
constexpr size_t logn(u64 base)
|
constexpr size_t logn(u64 base)
|
||||||
{
|
{
|
||||||
// FIXME: proper rounding
|
// FIXME: proper rounding
|
||||||
return log2() / (sizeof(u64) - __builtin_clzll(base));
|
return log2() / (sizeof(u64) - count_leading_zeroes(base));
|
||||||
}
|
}
|
||||||
template<Unsigned U>
|
template<Unsigned U>
|
||||||
requires(sizeof(U) > sizeof(u64)) constexpr size_t logn(U base)
|
requires(sizeof(U) > sizeof(u64)) constexpr size_t logn(U base)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
#include <AK/StdLibExtras.h>
|
#include <AK/StdLibExtras.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
@ -771,13 +772,13 @@ u32 Processor::smp_wake_n_idle_processors(u32 wake_count)
|
||||||
while (did_wake_count < wake_count) {
|
while (did_wake_count < wake_count) {
|
||||||
// Try to get a set of idle CPUs and flip them to busy
|
// Try to get a set of idle CPUs and flip them to busy
|
||||||
u32 idle_mask = s_idle_cpu_mask.load(AK::MemoryOrder::memory_order_relaxed) & ~(1u << current_id);
|
u32 idle_mask = s_idle_cpu_mask.load(AK::MemoryOrder::memory_order_relaxed) & ~(1u << current_id);
|
||||||
u32 idle_count = __builtin_popcountl(idle_mask);
|
u32 idle_count = popcount(idle_mask);
|
||||||
if (idle_count == 0)
|
if (idle_count == 0)
|
||||||
break; // No (more) idle processor available
|
break; // No (more) idle processor available
|
||||||
|
|
||||||
u32 found_mask = 0;
|
u32 found_mask = 0;
|
||||||
for (u32 i = 0; i < idle_count; i++) {
|
for (u32 i = 0; i < idle_count; i++) {
|
||||||
u32 cpu = __builtin_ffsl(idle_mask) - 1;
|
u32 cpu = bit_scan_forward(idle_mask) - 1;
|
||||||
idle_mask &= ~(1u << cpu);
|
idle_mask &= ~(1u << cpu);
|
||||||
found_mask |= 1u << cpu;
|
found_mask |= 1u << cpu;
|
||||||
}
|
}
|
||||||
|
@ -785,9 +786,9 @@ u32 Processor::smp_wake_n_idle_processors(u32 wake_count)
|
||||||
idle_mask = s_idle_cpu_mask.fetch_and(~found_mask, AK::MemoryOrder::memory_order_acq_rel) & found_mask;
|
idle_mask = s_idle_cpu_mask.fetch_and(~found_mask, AK::MemoryOrder::memory_order_acq_rel) & found_mask;
|
||||||
if (idle_mask == 0)
|
if (idle_mask == 0)
|
||||||
continue; // All of them were flipped to busy, try again
|
continue; // All of them were flipped to busy, try again
|
||||||
idle_count = __builtin_popcountl(idle_mask);
|
idle_count = popcount(idle_mask);
|
||||||
for (u32 i = 0; i < idle_count; i++) {
|
for (u32 i = 0; i < idle_count; i++) {
|
||||||
u32 cpu = __builtin_ffsl(idle_mask) - 1;
|
u32 cpu = bit_scan_forward(idle_mask) - 1;
|
||||||
idle_mask &= ~(1u << cpu);
|
idle_mask &= ~(1u << cpu);
|
||||||
|
|
||||||
// Send an IPI to that CPU to wake it up. There is a possibility
|
// Send an IPI to that CPU to wake it up. There is a possibility
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/NonnullRefPtr.h>
|
#include <AK/NonnullRefPtr.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <Kernel/Assertions.h>
|
#include <Kernel/Assertions.h>
|
||||||
|
@ -80,7 +81,7 @@ OwnPtr<PhysicalRegion> PhysicalRegion::try_take_pages_from_beginning(unsigned pa
|
||||||
NonnullRefPtrVector<PhysicalPage> PhysicalRegion::take_contiguous_free_pages(size_t count)
|
NonnullRefPtrVector<PhysicalPage> PhysicalRegion::take_contiguous_free_pages(size_t count)
|
||||||
{
|
{
|
||||||
auto rounded_page_count = next_power_of_two(count);
|
auto rounded_page_count = next_power_of_two(count);
|
||||||
auto order = __builtin_ctz(rounded_page_count);
|
auto order = count_trailing_zeroes(rounded_page_count);
|
||||||
|
|
||||||
Optional<PhysicalAddress> page_base;
|
Optional<PhysicalAddress> page_base;
|
||||||
for (auto& zone : m_usable_zones) {
|
for (auto& zone : m_usable_zones) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
#include <Kernel/Memory/MemoryManager.h>
|
#include <Kernel/Memory/MemoryManager.h>
|
||||||
#include <Kernel/Memory/PhysicalPage.h>
|
#include <Kernel/Memory/PhysicalPage.h>
|
||||||
|
@ -31,7 +32,7 @@ PhysicalZone::PhysicalZone(PhysicalAddress base_address, size_t page_count)
|
||||||
bucket.bitmap.grow(bitmap_size_for_order, false);
|
bucket.bitmap.grow(bitmap_size_for_order, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto first_order = __builtin_ctz(page_count);
|
auto first_order = count_trailing_zeroes(page_count);
|
||||||
size_t block_size = 2u << first_order;
|
size_t block_size = 2u << first_order;
|
||||||
auto& bucket = m_buckets[first_order];
|
auto& bucket = m_buckets[first_order];
|
||||||
size_t remaining_chunk_count = chunk_count;
|
size_t remaining_chunk_count = chunk_count;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/ScopeGuard.h>
|
#include <AK/ScopeGuard.h>
|
||||||
#include <AK/Singleton.h>
|
#include <AK/Singleton.h>
|
||||||
#include <AK/Time.h>
|
#include <AK/Time.h>
|
||||||
|
@ -77,7 +78,7 @@ Thread& Scheduler::pull_next_runnable_thread()
|
||||||
return g_ready_queues->with([&](auto& ready_queues) -> Thread& {
|
return g_ready_queues->with([&](auto& ready_queues) -> Thread& {
|
||||||
auto priority_mask = ready_queues.mask;
|
auto priority_mask = ready_queues.mask;
|
||||||
while (priority_mask != 0) {
|
while (priority_mask != 0) {
|
||||||
auto priority = __builtin_ffsl(priority_mask);
|
auto priority = bit_scan_forward(priority_mask);
|
||||||
VERIFY(priority > 0);
|
VERIFY(priority > 0);
|
||||||
auto& ready_queue = ready_queues.queues[--priority];
|
auto& ready_queue = ready_queues.queues[--priority];
|
||||||
for (auto& thread : ready_queue.thread_list) {
|
for (auto& thread : ready_queue.thread_list) {
|
||||||
|
@ -116,7 +117,7 @@ Thread* Scheduler::peek_next_runnable_thread()
|
||||||
return g_ready_queues->with([&](auto& ready_queues) -> Thread* {
|
return g_ready_queues->with([&](auto& ready_queues) -> Thread* {
|
||||||
auto priority_mask = ready_queues.mask;
|
auto priority_mask = ready_queues.mask;
|
||||||
while (priority_mask != 0) {
|
while (priority_mask != 0) {
|
||||||
auto priority = __builtin_ffsl(priority_mask);
|
auto priority = bit_scan_forward(priority_mask);
|
||||||
VERIFY(priority > 0);
|
VERIFY(priority > 0);
|
||||||
auto& ready_queue = ready_queues.queues[--priority];
|
auto& ready_queue = ready_queues.queues[--priority];
|
||||||
for (auto& thread : ready_queue.thread_list) {
|
for (auto& thread : ready_queue.thread_list) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/Atomic.h>
|
#include <AK/Atomic.h>
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
@ -185,12 +186,12 @@ RefPtr<StorageDevice> AHCIController::device(u32 index) const
|
||||||
{
|
{
|
||||||
NonnullRefPtrVector<StorageDevice> connected_devices;
|
NonnullRefPtrVector<StorageDevice> connected_devices;
|
||||||
u32 pi = hba().control_regs.pi;
|
u32 pi = hba().control_regs.pi;
|
||||||
u32 bit = __builtin_ffsl(pi);
|
u32 bit = bit_scan_forward(pi);
|
||||||
while (bit) {
|
while (bit) {
|
||||||
dbgln_if(AHCI_DEBUG, "Checking implemented port {}, pi {:b}", bit - 1, pi);
|
dbgln_if(AHCI_DEBUG, "Checking implemented port {}, pi {:b}", bit - 1, pi);
|
||||||
pi &= ~(1u << (bit - 1));
|
pi &= ~(1u << (bit - 1));
|
||||||
auto checked_device = device_by_port(bit - 1);
|
auto checked_device = device_by_port(bit - 1);
|
||||||
bit = __builtin_ffsl(pi);
|
bit = bit_scan_forward(pi);
|
||||||
if (checked_device.is_null())
|
if (checked_device.is_null())
|
||||||
continue;
|
continue;
|
||||||
connected_devices.append(checked_device.release_nonnull());
|
connected_devices.append(checked_device.release_nonnull());
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <Kernel/Debug.h>
|
#include <Kernel/Debug.h>
|
||||||
#include <Kernel/FileSystem/OpenFileDescription.h>
|
#include <Kernel/FileSystem/OpenFileDescription.h>
|
||||||
#include <Kernel/Net/Socket.h>
|
#include <Kernel/Net/Socket.h>
|
||||||
|
@ -473,7 +474,7 @@ bool Thread::SignalBlocker::check_pending_signals(bool from_add_blocker)
|
||||||
if (m_did_unblock)
|
if (m_did_unblock)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto matching_pending_signal = __builtin_ffsl(thread().pending_signals() & m_pending_set);
|
auto matching_pending_signal = bit_scan_forward(thread().pending_signals() & m_pending_set);
|
||||||
if (matching_pending_signal == 0)
|
if (matching_pending_signal == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "SoftCPU.h"
|
#include "SoftCPU.h"
|
||||||
#include "Emulator.h"
|
#include "Emulator.h"
|
||||||
#include <AK/Assertions.h>
|
#include <AK/Assertions.h>
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -978,7 +979,7 @@ void SoftCPU::BOUND(const X86::Instruction&) { TODO_INSN(); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ALWAYS_INLINE static T op_bsf(SoftCPU&, T value)
|
ALWAYS_INLINE static T op_bsf(SoftCPU&, T value)
|
||||||
{
|
{
|
||||||
return { (typename T::ValueType)__builtin_ctz(value.value()), value.shadow() };
|
return { (typename T::ValueType)bit_scan_forward(value.value()), value.shadow() };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <AK/ScopedValueRollback.h>
|
#include <AK/ScopedValueRollback.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
@ -437,7 +438,7 @@ void* malloc(size_t size)
|
||||||
// _aligned_free(), so it can be easily implemented on top of malloc().
|
// _aligned_free(), so it can be easily implemented on top of malloc().
|
||||||
void* _aligned_malloc(size_t size, size_t alignment)
|
void* _aligned_malloc(size_t size, size_t alignment)
|
||||||
{
|
{
|
||||||
if (__builtin_popcount(alignment) != 1) {
|
if (popcount(alignment) != 1) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "UnsignedBigIntegerAlgorithms.h"
|
#include "UnsignedBigIntegerAlgorithms.h"
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
|
|
||||||
namespace Crypto {
|
namespace Crypto {
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ FLATTEN void UnsignedBigIntegerAlgorithms::bitwise_not_without_allocation(
|
||||||
auto last_word_index = right.length() - 1;
|
auto last_word_index = right.length() - 1;
|
||||||
auto last_word = right.words()[last_word_index];
|
auto last_word = right.words()[last_word_index];
|
||||||
|
|
||||||
output.m_words[last_word_index] = ((u32)0xffffffffffffffff >> __builtin_clz(last_word)) & ~last_word;
|
output.m_words[last_word_index] = ((u32)0xffffffffffffffff >> count_leading_zeroes(last_word)) & ~last_word;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
@ -326,9 +327,9 @@ static void populate_dib_mask_info_if_needed(BMPLoadingContext& context)
|
||||||
mask_sizes.append(0);
|
mask_sizes.append(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int trailing_zeros = count_trailing_zeroes_32(mask);
|
int trailing_zeros = count_trailing_zeroes(mask);
|
||||||
// If mask is exactly `0xFFFFFFFF`, then we might try to count the trailing zeros of 0x00000000 here, so we need the safe version:
|
// If mask is exactly `0xFFFFFFFF`, then we might try to count the trailing zeros of 0x00000000 here, so we need the safe version:
|
||||||
int size = count_trailing_zeroes_32_safe(~(mask >> trailing_zeros));
|
int size = count_trailing_zeroes_safe(~(mask >> trailing_zeros));
|
||||||
if (size > 8) {
|
if (size > 8) {
|
||||||
// Drop lowest bits if mask is longer than 8 bits.
|
// Drop lowest bits if mask is longer than 8 bits.
|
||||||
trailing_zeros += size - 8;
|
trailing_zeros += size - 8;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "BitmapFont.h"
|
#include "BitmapFont.h"
|
||||||
#include "Emoji.h"
|
#include "Emoji.h"
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Utf32View.h>
|
#include <AK/Utf32View.h>
|
||||||
#include <AK/Utf8View.h>
|
#include <AK/Utf8View.h>
|
||||||
#include <LibCore/FileStream.h>
|
#include <LibCore/FileStream.h>
|
||||||
|
@ -95,7 +96,7 @@ NonnullRefPtr<BitmapFont> BitmapFont::masked_character_set() const
|
||||||
}
|
}
|
||||||
size_t new_glyph_count { 0 };
|
size_t new_glyph_count { 0 };
|
||||||
for (size_t i = 0; i < new_range_mask_size; ++i) {
|
for (size_t i = 0; i < new_range_mask_size; ++i) {
|
||||||
new_glyph_count += 256 * __builtin_popcount(new_range_mask[i]);
|
new_glyph_count += 256 * popcount(new_range_mask[i]);
|
||||||
}
|
}
|
||||||
size_t bytes_per_glyph = sizeof(u32) * m_glyph_height;
|
size_t bytes_per_glyph = sizeof(u32) * m_glyph_height;
|
||||||
auto* new_rows = static_cast<u8*>(calloc(new_glyph_count, bytes_per_glyph));
|
auto* new_rows = static_cast<u8*>(calloc(new_glyph_count, bytes_per_glyph));
|
||||||
|
@ -191,7 +192,7 @@ RefPtr<BitmapFont> BitmapFont::load_from_memory(const u8* data)
|
||||||
size_t glyph_count { 0 };
|
size_t glyph_count { 0 };
|
||||||
u8* range_mask = const_cast<u8*>(data + sizeof(FontFileHeader));
|
u8* range_mask = const_cast<u8*>(data + sizeof(FontFileHeader));
|
||||||
for (size_t i = 0; i < header.range_mask_size; ++i)
|
for (size_t i = 0; i < header.range_mask_size; ++i)
|
||||||
glyph_count += 256 * __builtin_popcount(range_mask[i]);
|
glyph_count += 256 * popcount(range_mask[i]);
|
||||||
u8* rows = range_mask + header.range_mask_size;
|
u8* rows = range_mask + header.range_mask_size;
|
||||||
u8* widths = (u8*)(rows) + glyph_count * bytes_per_glyph;
|
u8* widths = (u8*)(rows) + glyph_count * bytes_per_glyph;
|
||||||
return adopt_ref(*new BitmapFont(String(header.name), String(header.family), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing, header.range_mask_size, range_mask, header.baseline, header.mean_line, header.presentation_size, header.weight, header.slope));
|
return adopt_ref(*new BitmapFont(String(header.name), String(header.family), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing, header.range_mask_size, range_mask, header.baseline, header.mean_line, header.presentation_size, header.weight, header.slope));
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/CharacterTypes.h>
|
#include <AK/CharacterTypes.h>
|
||||||
#include <AK/Hex.h>
|
#include <AK/Hex.h>
|
||||||
#include <AK/Platform.h>
|
#include <AK/Platform.h>
|
||||||
|
@ -500,7 +501,7 @@ static ThrowCompletionOr<String> decode(JS::GlobalObject& global_object, const S
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto leading_ones = count_trailing_zeroes_32_safe(~decoded_code_unit) - 24;
|
auto leading_ones = count_trailing_zeroes_safe(static_cast<u32>(~decoded_code_unit)) - 24;
|
||||||
if (leading_ones == 1 || leading_ones > 4)
|
if (leading_ones == 1 || leading_ones > 4)
|
||||||
return global_object.vm().throw_completion<URIError>(global_object, ErrorType::URIMalformed);
|
return global_object.vm().throw_completion<URIError>(global_object, ErrorType::URIMalformed);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/Random.h>
|
#include <AK/Random.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
@ -303,7 +304,7 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::clz32)
|
||||||
auto number = TRY(vm.argument(0).to_u32(global_object));
|
auto number = TRY(vm.argument(0).to_u32(global_object));
|
||||||
if (number == 0)
|
if (number == 0)
|
||||||
return Value(32);
|
return Value(32);
|
||||||
return Value(__builtin_clz(number));
|
return Value(count_leading_zeroes(number));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 21.3.2.2 Math.acos ( x ), https://tc39.es/ecma262/#sec-math.acos
|
// 21.3.2.2 Math.acos ( x ), https://tc39.es/ecma262/#sec-math.acos
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/ExtraMathConstants.h>
|
#include <AK/ExtraMathConstants.h>
|
||||||
#include <AK/Math.h>
|
#include <AK/Math.h>
|
||||||
#include <AK/Platform.h>
|
#include <AK/Platform.h>
|
||||||
|
@ -278,7 +279,7 @@ static FloatT internal_scalbn(FloatT x, int exponent) NOEXCEPT
|
||||||
return extractor.d;
|
return extractor.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned leading_mantissa_zeroes = extractor.mantissa == 0 ? 32 : __builtin_clz(extractor.mantissa);
|
unsigned leading_mantissa_zeroes = extractor.mantissa == 0 ? 32 : count_leading_zeroes(extractor.mantissa);
|
||||||
int shift = min((int)leading_mantissa_zeroes, exponent);
|
int shift = min((int)leading_mantissa_zeroes, exponent);
|
||||||
exponent = max(exponent - shift, 0);
|
exponent = max(exponent - shift, 0);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/BitCast.h>
|
#include <AK/BitCast.h>
|
||||||
|
#include <AK/BuiltinWrappers.h>
|
||||||
#include <AK/Result.h>
|
#include <AK/Result.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
@ -176,10 +177,8 @@ struct CountLeadingZeros {
|
||||||
if (lhs == 0)
|
if (lhs == 0)
|
||||||
return sizeof(Lhs) * CHAR_BIT;
|
return sizeof(Lhs) * CHAR_BIT;
|
||||||
|
|
||||||
if constexpr (sizeof(Lhs) == 4)
|
if constexpr (sizeof(Lhs) == 4 || sizeof(Lhs) == 8)
|
||||||
return __builtin_clz(lhs);
|
return count_leading_zeroes(MakeUnsigned<Lhs>(lhs));
|
||||||
else if constexpr (sizeof(Lhs) == 8)
|
|
||||||
return __builtin_clzll(lhs);
|
|
||||||
else
|
else
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -193,10 +192,8 @@ struct CountTrailingZeros {
|
||||||
if (lhs == 0)
|
if (lhs == 0)
|
||||||
return sizeof(Lhs) * CHAR_BIT;
|
return sizeof(Lhs) * CHAR_BIT;
|
||||||
|
|
||||||
if constexpr (sizeof(Lhs) == 4)
|
if constexpr (sizeof(Lhs) == 4 || sizeof(Lhs) == 8)
|
||||||
return __builtin_ctz(lhs);
|
return count_trailing_zeroes(MakeUnsigned<Lhs>(lhs));
|
||||||
else if constexpr (sizeof(Lhs) == 8)
|
|
||||||
return __builtin_ctzll(lhs);
|
|
||||||
else
|
else
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -207,10 +204,8 @@ struct PopCount {
|
||||||
template<typename Lhs>
|
template<typename Lhs>
|
||||||
auto operator()(Lhs lhs) const
|
auto operator()(Lhs lhs) const
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(Lhs) == 4)
|
if constexpr (sizeof(Lhs) == 4 || sizeof(Lhs) == 8)
|
||||||
return __builtin_popcount(lhs);
|
return popcount(MakeUnsigned<Lhs>(lhs));
|
||||||
else if constexpr (sizeof(Lhs) == 8)
|
|
||||||
return __builtin_popcountll(lhs);
|
|
||||||
else
|
else
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue