]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tools: improve the popcount() operation
authorWilly Tarreau <w@1wt.eu>
Sat, 2 Feb 2019 19:17:31 +0000 (20:17 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 4 Feb 2019 04:09:15 +0000 (05:09 +0100)
We'll call popcount() more often so better use a parallel method
than an iterative one. One optimal design is proposed at the site
below. It requires a fast multiplication though, but even without
it will still be faster than the iterative one, and all relevant
64 bit platforms do have a multiply unit.

     https://graphics.stanford.edu/~seander/bithacks.html

include/common/standard.h

index dc771477bdf9ac429835527ee24fdcef876d87ca..4f4b2d509a98bbc2d0aea7b6fd12e5d2690d99cb 100644 (file)
@@ -790,15 +790,15 @@ static inline unsigned int div64_32(unsigned long long o1, unsigned int o2)
        return result;
 }
 
-/* Simple popcountl implementation. It returns the number of ones in a word */
+/* Simple popcountl implementation. It returns the number of ones in a word.
+ * Described here : https://graphics.stanford.edu/~seander/bithacks.html
+ */
 static inline unsigned int my_popcountl(unsigned long a)
 {
-       unsigned int cnt;
-       for (cnt = 0; a; a >>= 1) {
-               if (a & 1)
-                       cnt++;
-       }
-       return cnt;
+       a = a - ((a >> 1) & ~0UL/3);
+       a = (a & ~0UL/15*3) + ((a >> 2) & ~0UL/15*3);
+       a = (a + (a >> 4)) & ~0UL/255*15;
+       return (unsigned long)(a * (~0UL/255)) >> (sizeof(unsigned long) - 1) * 8;
 }
 
 /* returns non-zero if <a> has at least 2 bits set */