diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2005-07-28 08:45:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-28 08:40:31 -0700 |
commit | cd85c8b4457a52d3545fdb9532082b2c1ebd5f21 (patch) | |
tree | 58b294ef3cd90f08fa77555352de63934a881405 /include | |
parent | 79a8810221ee9ea96c4e5a5817afb88f22ea698c (diff) | |
download | linux-3.10-cd85c8b4457a52d3545fdb9532082b2c1ebd5f21.tar.gz linux-3.10-cd85c8b4457a52d3545fdb9532082b2c1ebd5f21.tar.bz2 linux-3.10-cd85c8b4457a52d3545fdb9532082b2c1ebd5f21.zip |
[PATCH] speed up on find_first_bit for i386 (let compiler do the work)
Avoid using "rep scas", just let the compiler select a sequence of
regular instructions.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-i386/bitops.h | 54 |
1 files changed, 24 insertions, 30 deletions
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h index 9db0b712d57..1caee103936 100644 --- a/include/asm-i386/bitops.h +++ b/include/asm-i386/bitops.h @@ -311,6 +311,20 @@ static inline int find_first_zero_bit(const unsigned long *addr, unsigned size) int find_next_zero_bit(const unsigned long *addr, int size, int offset); /** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ + __asm__("bsfl %1,%0" + :"=r" (word) + :"rm" (word)); + return word; +} + +/** * find_first_bit - find the first set bit in a memory region * @addr: The address to start the search at * @size: The maximum size to search @@ -320,22 +334,16 @@ int find_next_zero_bit(const unsigned long *addr, int size, int offset); */ static inline int find_first_bit(const unsigned long *addr, unsigned size) { - int d0, d1; - int res; - - /* This looks at memory. Mark it volatile to tell gcc not to move it around */ - __asm__ __volatile__( - "xorl %%eax,%%eax\n\t" - "repe; scasl\n\t" - "jz 1f\n\t" - "leal -4(%%edi),%%edi\n\t" - "bsfl (%%edi),%%eax\n" - "1:\tsubl %%ebx,%%edi\n\t" - "shll $3,%%edi\n\t" - "addl %%edi,%%eax" - :"=a" (res), "=&c" (d0), "=&D" (d1) - :"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory"); - return res; + int x = 0; + do { + if (*addr) + return __ffs(*addr) + x; + addr++; + if (x >= size) + break; + x += (sizeof(*addr)<<3); + } while (1); + return x; } /** @@ -360,20 +368,6 @@ static inline unsigned long ffz(unsigned long word) return word; } -/** - * __ffs - find first bit in word. - * @word: The word to search - * - * Undefined if no bit exists, so code should check against 0 first. - */ -static inline unsigned long __ffs(unsigned long word) -{ - __asm__("bsfl %1,%0" - :"=r" (word) - :"rm" (word)); - return word; -} - /* * fls: find last bit set. */ |