From: Willy Tarreau Date: Sun, 17 Dec 2023 15:43:25 +0000 (+0100) Subject: IMPORT: ebtree: implement and use flsnz_long() to count bits X-Git-Tag: v3.0-dev1~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9afe3b59a7d8d57ad315155b012201c97ea75f18;p=thirdparty%2Fhaproxy.git IMPORT: ebtree: implement and use flsnz_long() to count bits The asm code shows multiple conversions. Gcc has always been terribly bad at dealing with chars, which are constantly converted to ints for every operation and zero-extended after each operation. But here in addition there are conversions before and after the flsnz(). Let's just mark the variables as long and use flsnz_long() to process them without any conversion. This shortens the code and makes it slightly faster. Note that the fls operations could make use of __builtin_clz() on gcc 4.6 and above, and it would be useful to implement native support for ARM as well. This is cbtree commit 1f0f83ba26f2279c8bba0080a2e09a803dddde47. This is ebtree commit 9c38dcae22a84f0b0d9c5a56facce1ca2ad0aaef. --- diff --git a/include/import/ebtree.h b/include/import/ebtree.h index d6e51d5be3..b1666bba72 100644 --- a/include/import/ebtree.h +++ b/include/import/ebtree.h @@ -279,6 +279,14 @@ static inline int flsnz8(unsigned char x) return r+1; } +static inline long flsnz_long(unsigned long x) +{ + long r; + __asm__("bsr %1,%0\n" + : "=r" (r) : "rm" (x)); + return r + 1; +} + #else // returns 1 to 32 for 1<<0 to 1<<31. Undefined for 0. #define flsnz(___a) ({ \ @@ -297,6 +305,7 @@ static inline int flsnz8(unsigned int x) return flsnz8_generic(x); } +#define flsnz_long(x) ((sizeof(long) > 4) ? flsnz64(x) : flsnz32(x)) #endif @@ -791,7 +800,7 @@ static forceinline int string_equal_bits(const unsigned char *a, int ignore) { int beg; - unsigned char c; + unsigned long c, d; beg = ignore >> 3; @@ -799,8 +808,6 @@ static forceinline int string_equal_bits(const unsigned char *a, * or at the first zero we encounter on either side. */ while (1) { - unsigned char d; - c = a[beg]; d = b[beg]; beg++; @@ -816,7 +823,7 @@ static forceinline int string_equal_bits(const unsigned char *a, * identical bits. Note that low bit numbers are assigned to high positions * in the byte, as we compare them as strings. */ - return (beg << 3) - flsnz8(c); + return (beg << 3) - flsnz_long(c); } static forceinline int cmp_bits(const unsigned char *a, const unsigned char *b, unsigned int pos)