From 22950665cce29d2350b45fc0a255ffec847e12da Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 14 Oct 2011 02:11:34 +0200 Subject: [PATCH] ffsl: Optimize on 32-bit platforms. * lib/ffsl.h (FUNC): If TYPE has the same representation as 'int', just use ffs() without a loop. --- ChangeLog | 4 ++++ lib/ffsl.h | 38 +++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 866dfa293..fede05e01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-10-13 Bruno Haible + ffsl: Optimize on 32-bit platforms. + * lib/ffsl.h (FUNC): If TYPE has the same representation as 'int', just + use ffs() without a loop. + ffsl, ffsll: Optimize for GCC. * lib/ffsl.h (FUNC): Use GCC_BUILTIN if defined. * lib/ffsl.c (GCC_BUILTIN): New macro. diff --git a/lib/ffsl.h b/lib/ffsl.h index 9f209123d..99e7d264a 100644 --- a/lib/ffsl.h +++ b/lib/ffsl.h @@ -34,18 +34,34 @@ FUNC (TYPE i) #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined GCC_BUILTIN return GCC_BUILTIN (i); #else - int result = 0; - unsigned TYPE j = i; - - /* GCC has __builtin_ffs, but it is limited to int. */ - if (!i) - return 0; - while (1) + if (sizeof (TYPE) == sizeof (int)) + return ffs (i); + else { - if ((unsigned int) j) - return result + ffs ((unsigned int) j); - j >>= CHAR_BIT * sizeof (unsigned int); - result += CHAR_BIT * sizeof (unsigned int); + unsigned TYPE j = i; + /* Split j into chunks, and look at one chunk after the other. */ + /* Define chunk_bits so as to avoid a GCC warning + "right shift count >= width of type" + if sizeof (TYPE) == sizeof (int). */ + enum + { + chunk_bits = (sizeof (TYPE) != sizeof (int) + ? CHAR_BIT * sizeof (unsigned int) + : 0) + }; + int result = 0; + + /* It is tempting to write if (!j) here, but if we do this, + Solaris 10/x86 "cc -O" miscompiles the code. */ + if (!i) + return 0; + while (1) + { + if ((unsigned int) j) + return result + ffs ((unsigned int) j); + j >>= chunk_bits; + result += chunk_bits; + } } #endif } -- 2.11.0