Expand the bitcount* API to support 64-bit integers, plain ints and longs
and create a "hidden" API that can be used in other system headers without adding namespace pollution. - If the POPCNT instruction is enabled at compile time, use __builtin_popcount*() to implement __bitcount*(), otherwise fall back to software implementations. - Use the existing bitcount16() and bitcount32() from <sys/systm.h> to implement the non-POPCNT __bitcount16() and __bitcount32() in <sys/types.h>. - For the non-POPCNT __bitcount64(), use a similar SWAR method on 64-bit systems. For 32-bit systems, use two __bitcount32() operations on the two halves. - Use __bitcount32() to provide a __bitcount() that operates on plain ints. - Use either __bitcount32() or __bitcount64() to provide a __bitcountl() that operates on longs. - Add public bitcount*() wrappers for __bitcount*() for use in the kernel in <sys/libkern.h>. - Use __builtinl() instead of __builtin_popcountl() in BIT_COUNT(). Discussed with: bde
This commit is contained in:
parent
37143b98d4
commit
589b2c1c1e
@ -182,7 +182,7 @@
|
||||
\
|
||||
__count = 0; \
|
||||
for (__i = 0; __i < __bitset_words((_s)); __i++) \
|
||||
__count += __builtin_popcountl((p)->__bits[__i]); \
|
||||
__count += __bitcountl((p)->__bits[__i]); \
|
||||
__count; \
|
||||
})
|
||||
|
||||
|
@ -98,6 +98,11 @@ int flsl(long);
|
||||
#ifndef HAVE_INLINE_FLSLL
|
||||
int flsll(long long);
|
||||
#endif
|
||||
#define bitcount64(x) __bitcount64((uint64_t)(x))
|
||||
#define bitcount32(x) __bitcount32((uint32_t)(x))
|
||||
#define bitcount16(x) __bitcount16((uint16_t)(x))
|
||||
#define bitcountl(x) __bitcountl((u_long)(x))
|
||||
#define bitcount(x) __bitcount((u_int)(x))
|
||||
|
||||
int fnmatch(const char *, const char *, int);
|
||||
int locc(int, char *, u_int);
|
||||
|
@ -428,33 +428,6 @@ int alloc_unr_specific(struct unrhdr *uh, u_int item);
|
||||
int alloc_unrl(struct unrhdr *uh);
|
||||
void free_unr(struct unrhdr *uh, u_int item);
|
||||
|
||||
/*
|
||||
* Population count algorithm using SWAR approach
|
||||
* - "SIMD Within A Register".
|
||||
*/
|
||||
static __inline uint32_t
|
||||
bitcount32(uint32_t x)
|
||||
{
|
||||
|
||||
x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1);
|
||||
x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2);
|
||||
x = (x + (x >> 4)) & 0x0f0f0f0f;
|
||||
x = (x + (x >> 8));
|
||||
x = (x + (x >> 16)) & 0x000000ff;
|
||||
return (x);
|
||||
}
|
||||
|
||||
static __inline uint16_t
|
||||
bitcount16(uint32_t x)
|
||||
{
|
||||
|
||||
x = (x & 0x5555) + ((x & 0xaaaa) >> 1);
|
||||
x = (x & 0x3333) + ((x & 0xcccc) >> 2);
|
||||
x = (x + (x >> 4)) & 0x0f0f;
|
||||
x = (x + (x >> 8)) & 0x00ff;
|
||||
return (x);
|
||||
}
|
||||
|
||||
void intr_prof_stack_use(struct thread *td, struct trapframe *frame);
|
||||
|
||||
#endif /* !_SYS_SYSTM_H_ */
|
||||
|
@ -294,6 +294,68 @@ typedef _Bool bool;
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
#ifdef __POPCNT__
|
||||
#define __bitcount64(x) __builtin_popcountll((__uint64_t)(x))
|
||||
#define __bitcount32(x) __builtin_popcount((__uint32_t)(x))
|
||||
#define __bitcount16(x) __builtin_popcount((__uint16_t)(x))
|
||||
#define __bitcountl(x) __builtin_popcountl((unsigned long)(x))
|
||||
#define __bitcount(x) __builtin_popcount((unsigned int)(x))
|
||||
#else
|
||||
/*
|
||||
* Population count algorithm using SWAR approach
|
||||
* - "SIMD Within A Register".
|
||||
*/
|
||||
static __inline __uint16_t
|
||||
__bitcount16(__uint16_t _x)
|
||||
{
|
||||
|
||||
_x = (_x & 0x5555) + ((_x & 0xaaaa) >> 1);
|
||||
_x = (_x & 0x3333) + ((_x & 0xcccc) >> 2);
|
||||
_x = (_x + (_x >> 4)) & 0x0f0f;
|
||||
_x = (_x + (_x >> 8)) & 0x00ff;
|
||||
return (_x);
|
||||
}
|
||||
|
||||
static __inline __uint32_t
|
||||
__bitcount32(__uint32_t _x)
|
||||
{
|
||||
|
||||
_x = (_x & 0x55555555) + ((_x & 0xaaaaaaaa) >> 1);
|
||||
_x = (_x & 0x33333333) + ((_x & 0xcccccccc) >> 2);
|
||||
_x = (_x + (_x >> 4)) & 0x0f0f0f0f;
|
||||
_x = (_x + (_x >> 8));
|
||||
_x = (_x + (_x >> 16)) & 0x000000ff;
|
||||
return (_x);
|
||||
}
|
||||
|
||||
#ifdef __LP64__
|
||||
static __inline __uint64_t
|
||||
__bitcount64(__uint64_t _x)
|
||||
{
|
||||
|
||||
_x = (_x & 0x5555555555555555) + ((_x & 0xaaaaaaaaaaaaaaaa) >> 1);
|
||||
_x = (_x & 0x3333333333333333) + ((_x & 0xcccccccccccccccc) >> 2);
|
||||
_x = (_x + (_x >> 4)) & 0x0f0f0f0f0f0f0f0f;
|
||||
_x = (_x + (_x >> 8));
|
||||
_x = (_x + (_x >> 16));
|
||||
_x = (_x + (_x >> 32)) & 0x000000ff;
|
||||
return (_x);
|
||||
}
|
||||
|
||||
#define __bitcountl(x) __bitcount64((unsigned long)(x))
|
||||
#else
|
||||
static __inline __uint64_t
|
||||
__bitcount64(__uint64_t _x)
|
||||
{
|
||||
|
||||
return (__bitcount32(_x >> 32) + __bitcount32(_x));
|
||||
}
|
||||
|
||||
#define __bitcountl(x) __bitcount32((unsigned long)(x))
|
||||
#endif
|
||||
#define __bitcount(x) __bitcount32((unsigned int)(x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* minor() gives a cookie instead of an index since we don't want to
|
||||
* change the meanings of bits 0-15 or waste time and space shifting
|
||||
|
Loading…
Reference in New Issue
Block a user