- "Slap" the __builtin_ffs/ctzl() compiler builtins in front of the

kernel's optimized ffs()/ffz() helpers in order to make use of the
 compiler's constant folding optmization passes.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmM8PWQACgkQEsHwGGHe
 VUqyoRAAhS/b9Jie/Tvx4gVHkydCe+6403MVjRumSqh4634QaiJP1nILOgH+P3qj
 BSuR0el8rAVxGm6vF6IoU5+rM17MQ4d3M2xtz+ZxdIOwIFDVoHoJS9EQSiArOspD
 eOUOLlPb/Q5/n0pPMCxBzR3NYfhaWQ9YzujtVeFvR2KxesQAKpN9DpQxX1rybyee
 YJhsRlC7+8TEW7CgFo4+qzC291eUE1kdteGkjM4GH2ts3R3sllP5wjPJpHj/oCR4
 LBVi8Ie+5yHHpKfnkYNR4DephsYlpmjcKngYT6Jf+dBEhzXpgvJNzpUG42ZjJb94
 g8RG67tvYslU9psutpx/AilohLxaYSyY5AnXcaHGjvX27dadAX1vPKlP+Xqpc+IM
 /LHpKdcsWDuH0v68kw2wbLtUgD+Is7OQbE5oOaGCQ3VbMkhtFoqbFayu3KHu3uyt
 4Jkb0xPjHi//eOp69334PuP/ksbO7vs/AEZi6PvNp71szBw8u80+9LzhgWnqN4hU
 sb2+PYP27bIxflcavPqPg8WqwZrRSrE/gb6AG0J3M4zFAZ3tBx/Gpd8Auk4V0VhZ
 aLTOa0S6C0Q5IO6NlkA5OGedphMud+Pki21gyJQIweVsScrjEd1l/YDJMFcoCSqW
 mNAkEPq+7Xerlmfv/BhlyOjPH/DBrb3pthNoJDTui4eiyrw8WEU=
 =Reul
 -----END PGP SIGNATURE-----

Merge tag 'x86_asm_for_v6.1_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 asm update from Borislav Petkov:

 - Use the __builtin_ffs/ctzl() compiler builtins for the constant
   argument case in the kernel's optimized ffs()/ffz() helpers in order
   to make use of the compiler's constant folding optmization passes.

* tag 'x86_asm_for_v6.1_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/asm/bitops: Use __builtin_ctzl() to evaluate constant expressions
  x86/asm/bitops: Use __builtin_ffs() to evaluate constant expressions
This commit is contained in:
Linus Torvalds 2022-10-04 09:49:50 -07:00
commit bb1f11546e

View file

@ -247,17 +247,30 @@ 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)
{
asm("rep; bsf %1,%0"
: "=r" (word)
: "rm" (word));
return word;
}
/**
* __ffs - find first set bit in word
* @word: The word to search
*
* Undefined if no bit exists, so code should check against 0 first.
*/
static __always_inline unsigned long __ffs(unsigned long word)
#define __ffs(word) \
(__builtin_constant_p(word) ? \
(unsigned long)__builtin_ctzl(word) : \
variable__ffs(word))
static __always_inline unsigned long variable_ffz(unsigned long word)
{
asm("rep; bsf %1,%0"
: "=r" (word)
: "rm" (word));
: "r" (~word));
return word;
}
@ -267,13 +280,10 @@ static __always_inline unsigned long __ffs(unsigned long word)
*
* Undefined if no zero exists, so code should check against ~0UL first.
*/
static __always_inline unsigned long ffz(unsigned long word)
{
asm("rep; bsf %1,%0"
: "=r" (word)
: "r" (~word));
return word;
}
#define ffz(word) \
(__builtin_constant_p(word) ? \
(unsigned long)__builtin_ctzl(~word) : \
variable_ffz(word))
/*
* __fls: find last set bit in word
@ -292,18 +302,7 @@ static __always_inline unsigned long __fls(unsigned long word)
#undef ADDR
#ifdef __KERNEL__
/**
* ffs - find first set bit in word
* @x: the word to search
*
* This is defined the same way as the libc and compiler builtin ffs
* routines, therefore differs in spirit from the other bitops.
*
* ffs(value) returns 0 if value is 0 or the position of the first
* set bit if value is nonzero. The first (least significant) bit
* is at position 1.
*/
static __always_inline int ffs(int x)
static __always_inline int variable_ffs(int x)
{
int r;
@ -333,6 +332,19 @@ static __always_inline int ffs(int x)
return r + 1;
}
/**
* ffs - find first set bit in word
* @x: the word to search
*
* This is defined the same way as the libc and compiler builtin ffs
* routines, therefore differs in spirit from the other bitops.
*
* ffs(value) returns 0 if value is 0 or the position of the first
* set bit if value is nonzero. The first (least significant) bit
* is at position 1.
*/
#define ffs(x) (__builtin_constant_p(x) ? __builtin_ffs(x) : variable_ffs(x))
/**
* fls - find last set bit in word
* @x: the word to search