Commit bb1f1154 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 8cded8fb fdb6649a
...@@ -247,17 +247,30 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr) ...@@ -247,17 +247,30 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
variable_test_bit(nr, 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 * __ffs - find first set bit in word
* @word: The word to search * @word: The word to search
* *
* Undefined if no bit exists, so code should check against 0 first. * 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" asm("rep; bsf %1,%0"
: "=r" (word) : "=r" (word)
: "rm" (word)); : "r" (~word));
return word; return word;
} }
...@@ -267,13 +280,10 @@ static __always_inline unsigned long __ffs(unsigned long 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. * Undefined if no zero exists, so code should check against ~0UL first.
*/ */
static __always_inline unsigned long ffz(unsigned long word) #define ffz(word) \
{ (__builtin_constant_p(word) ? \
asm("rep; bsf %1,%0" (unsigned long)__builtin_ctzl(~word) : \
: "=r" (word) variable_ffz(word))
: "r" (~word));
return word;
}
/* /*
* __fls: find last set bit in word * __fls: find last set bit in word
...@@ -292,18 +302,7 @@ static __always_inline unsigned long __fls(unsigned long word) ...@@ -292,18 +302,7 @@ static __always_inline unsigned long __fls(unsigned long word)
#undef ADDR #undef ADDR
#ifdef __KERNEL__ #ifdef __KERNEL__
/** static __always_inline int variable_ffs(int x)
* 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)
{ {
int r; int r;
...@@ -333,6 +332,19 @@ static __always_inline int ffs(int x) ...@@ -333,6 +332,19 @@ static __always_inline int ffs(int x)
return r + 1; 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 * fls - find last set bit in word
* @x: the word to search * @x: the word to search
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment