From cperciva@beastie.daemonology.net  Thu Jan 15 19:53:44 2004
Return-Path: <cperciva@beastie.daemonology.net>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id E9A4016A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 15 Jan 2004 19:53:44 -0800 (PST)
Received: from pd4mo3so.prod.shaw.ca (shawidc-mo1.cg.shawcable.net [24.71.223.10])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 7F8F243D1D
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 15 Jan 2004 19:53:42 -0800 (PST)
	(envelope-from cperciva@beastie.daemonology.net)
Received: from pd2mr1so.prod.shaw.ca (pd2mr1so-ser.prod.shaw.ca [10.0.141.110])
 by l-daemon (iPlanet Messaging Server 5.2 HotFix 1.18 (built Jul 28 2003))
 with ESMTP id <0HRK004O5D9YBL@l-daemon> for FreeBSD-gnats-submit@freebsd.org;
 Thu, 15 Jan 2004 20:49:10 -0700 (MST)
Received: from pn2ml8so.prod.shaw.ca
 (pn2ml8so-qfe0.prod.shaw.ca [10.0.121.152]) by l-daemon
 (iPlanet Messaging Server 5.2 HotFix 1.18 (built Jul 28 2003))
 with ESMTP id <0HRK00LDLD9Y1I@l-daemon> for FreeBSD-gnats-submit@freebsd.org;
 Thu, 15 Jan 2004 20:49:10 -0700 (MST)
Received: from beastie.daemonology.net
 (h24-87-233-42.vc.shawcable.net [24.87.233.42])
 by l-daemon (iPlanet Messaging Server 5.2 HotFix 1.18 (built Jul 28 2003))
 with SMTP id <0HRK0033BD9XFA@l-daemon> for FreeBSD-gnats-submit@freebsd.org;
 Thu, 15 Jan 2004 20:49:10 -0700 (MST)
Received: (qmail 23250 invoked by uid 1001); Fri, 16 Jan 2004 03:49:09 +0000
Message-Id: <20040116034909.23249.qmail@beastie.daemonology.net>
Date: Fri, 16 Jan 2004 03:49:09 +0000
From: Colin Percival <cperciva@daemonology.net>
Reply-To: Colin Percival <cperciva@daemonology.net>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: A faster ffs(3)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         61405
>Category:       bin
>Synopsis:       A faster ffs(3)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    cperciva
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 15 20:00:34 PST 2004
>Closed-Date:    Sun Feb 24 00:12:32 UTC 2008
>Last-Modified:  Sun Feb 24 00:12:32 UTC 2008
>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:
Responsible-Changed-From-To: freebsd-bugs->cperciva 
Responsible-Changed-By: kris 
Responsible-Changed-When: Sat Apr 9 00:49:06 GMT 2005 
Responsible-Changed-Why:  
Submitter is now a committer 

http://www.freebsd.org/cgi/query-pr.cgi?pr=61405 
State-Changed-From-To: open->closed 
State-Changed-By: cperciva 
State-Changed-When: Sun Feb 24 00:11:34 UTC 2008 
State-Changed-Why:  
I don't plan on doing anything with this, and the speed-up, if any, is 
minimal on modern CPUs. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=61405 
>Unformatted:
