bin/61405: A faster ffs(3)
Colin Percival
cperciva at daemonology.net
Thu Jan 15 20:00:40 PST 2004
>Number: 61405
>Category: bin
>Synopsis: A faster ffs(3)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Thu Jan 15 20:00:34 PST 2004
>Closed-Date:
>Last-Modified:
>Originator: Colin Percival
>Release: FreeBSD 4.7-SECURITY i386
>Organization:
>Environment:
>Description:
ffs(3) currently loops, testing one bit per iteration until the
least set bit is found. This can be significantly improved.
>How-To-Repeat:
>Fix:
I'm not sure how important this is, since ffs is a single instruction on
many processors, but the following magic is very fast:
--- ffs.c begins here ---
#include <sys/types.h>
static int ffslut32[] = {
32, 1, 23, 2, 29, 24, 14, 3,
30, 27, 25, 18, 20, 15, 10, 4,
31, 22, 28, 13, 26, 17, 19, 9,
21, 12, 16, 8, 11, 7, 6, 5
};
static int ffslut64[] = {
64, 1, 48, 2, 57, 49, 28, 3,
61, 58, 50, 42, 38, 29, 17, 4,
62, 55, 59, 36, 53, 51, 43, 22,
45, 39, 33, 30, 24, 18, 12, 5,
63, 47, 56, 27, 60, 41, 37, 16,
54, 35, 52, 21, 44, 32, 23, 11,
46, 26, 40, 15, 34, 20, 31, 10,
25, 14, 19, 9, 13, 8, 7, 6
};
static int ffs32(uint32_t mask)
{
return mask ? ffslut32[((mask & (-mask)) * 0x0FB9AC52) >> 27] : 0;
}
static int ffs64(uint64_t mask)
{
return mask ? ffslut64[((mask & (-mask)) * 0x07EF3AE369961512) >> 58] : 0;
}
int ffs(int mask)
{
if (sizeof(int) == 8) return ffs64(mask);
if (sizeof(int) == 4) return ffs32(mask);
return -1;
}
int ffsl(long mask)
{
if (sizeof(long) == 8) return ffs64(mask);
if (sizeof(long) == 4) return ffs32(mask);
return -1;
}
--- ffs.c ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list