[PATCH] x86/asm/bitops: Change function return types from long to int

From: Thorsten Blum
Date: Sat May 25 2024 - 13:45:52 EST


Change the return types of bitops functions (ffs, ffz, and fls) from
long to int. The expected return values are in the range [0, 64], for
which int is sufficient.

Additionally, int aligns well with the return types of the corresponding
__builtin_* functions, potentially reducing overall type conversions.

Many of the existing bitops functions already return an int and don't
need to be changed.

With GCC 14 and defconfig, these changes reduced the number of x86-64
instructions by 342 (using objdump -d and compared to 0b32d436c015).

Summary of the most significant changes in instruction counts:

insn before after diff
----------------------------
ja 16044 15166 -878
cmp 171197 170583 -614
movsxd 16796 16271 -525
add 94692 94454 -238
jbe 9053 8815 -238
xor 97499 97478 -21
...
and 47291 47312 +21
nop 1036207 1036233 +26
cs 5622 5656 +34
int3 2815714 2815842 +128
lea 118250 118488 +238
je 190859 191132 +273
test 204887 205484 +597
jne 134316 135161 +845

Signed-off-by: Thorsten Blum <thorsten.blum@xxxxxxxxxx>
---
arch/x86/include/asm/bitops.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index b96d45944c59..4d91517a395d 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -246,7 +246,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
variable_test_bit(nr, addr);
}

-static __always_inline unsigned long variable__ffs(unsigned long word)
+static __always_inline unsigned int variable__ffs(unsigned long word)
{
asm("rep; bsf %1,%0"
: "=r" (word)
@@ -262,10 +262,10 @@ static __always_inline unsigned long variable__ffs(unsigned long word)
*/
#define __ffs(word) \
(__builtin_constant_p(word) ? \
- (unsigned long)__builtin_ctzl(word) : \
+ (unsigned int)__builtin_ctzl(word) : \
variable__ffs(word))

-static __always_inline unsigned long variable_ffz(unsigned long word)
+static __always_inline unsigned int variable_ffz(unsigned long word)
{
asm("rep; bsf %1,%0"
: "=r" (word)
@@ -281,7 +281,7 @@ static __always_inline unsigned long variable_ffz(unsigned long word)
*/
#define ffz(word) \
(__builtin_constant_p(word) ? \
- (unsigned long)__builtin_ctzl(~word) : \
+ (unsigned int)__builtin_ctzl(~word) : \
variable_ffz(word))

/*
@@ -290,7 +290,7 @@ static __always_inline unsigned long variable_ffz(unsigned long word)
*
* Undefined if no set bit exists, so code should check against 0 first.
*/
-static __always_inline unsigned long __fls(unsigned long word)
+static __always_inline unsigned int __fls(unsigned long word)
{
if (__builtin_constant_p(word))
return BITS_PER_LONG - 1 - __builtin_clzl(word);

base-commit: 0b32d436c015d5a88b3368405e3d8fe82f195a54
--
2.45.1