ffsl: Optimize on 32-bit platforms.
authorBruno Haible <bruno@clisp.org>
Fri, 14 Oct 2011 00:11:34 +0000 (02:11 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 14 Oct 2011 00:11:34 +0000 (02:11 +0200)
* lib/ffsl.h (FUNC): If TYPE has the same representation as 'int', just
use ffs() without a loop.

ChangeLog
lib/ffsl.h

index 866dfa2..fede05e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2011-10-13  Bruno Haible  <bruno@clisp.org>
 
+       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.
index 9f20912..99e7d26 100644 (file)
@@ -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
 }