From ede9c697bc7513f210103fa77a9031e89726ae40 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 29 Apr 2008 00:58:35 -0700 Subject: Avoid divides in BITS_TO_LONGS BITS_PER_LONG is a signed value (32 or 64) DIV_ROUND_UP(nr, BITS_PER_LONG) performs signed arithmetic if "nr" is signed too. Converting BITS_TO_LONGS(nr) to DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) makes sure compiler can perform a right shift, even if "nr" is a signed value, instead of an expensive integer divide. Applying this patch saves 141 bytes on x86 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y and speedup bitmap operations. Signed-off-by: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/bitops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/bitops.h') diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 48bde60..8340a3a 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -6,8 +6,8 @@ #define BIT(nr) (1UL << (nr)) #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG) #define BITS_PER_BYTE 8 +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #endif /* -- cgit v1.1 From fee4b19fb3f28d17c0b9f9ea0668db5275697178 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 29 Apr 2008 12:01:02 +0200 Subject: bitops: remove "optimizations" The mapsize optimizations which were moved from x86 to the generic code in commit 64970b68d2b3ed32b964b0b30b1b98518fde388e increased the binary size on non x86 architectures. Looking into the real effects of the "optimizations" it turned out that they are not used in find_next_bit() and find_next_zero_bit(). The ones in find_first_bit() and find_first_zero_bit() are used in a couple of places but none of them is a real hot path. Remove the "optimizations" all together and call the library functions unconditionally. Boot-tested on x86 and compile tested on every cross compiler I have. Signed-off-by: Thomas Gleixner Signed-off-by: Linus Torvalds --- include/linux/bitops.h | 115 ++++++------------------------------------------- 1 file changed, 12 insertions(+), 103 deletions(-) (limited to 'include/linux/bitops.h') diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 8340a3a..024f2b0 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -114,8 +114,6 @@ static inline unsigned fls_long(unsigned long l) #ifdef __KERNEL__ #ifdef CONFIG_GENERIC_FIND_FIRST_BIT -extern unsigned long __find_first_bit(const unsigned long *addr, - unsigned long size); /** * find_first_bit - find the first set bit in a memory region @@ -124,28 +122,8 @@ extern unsigned long __find_first_bit(const unsigned long *addr, * * Returns the bit number of the first set bit. */ -static __always_inline unsigned long -find_first_bit(const unsigned long *addr, unsigned long size) -{ - /* Avoid a function call if the bitmap size is a constant */ - /* and not bigger than BITS_PER_LONG. */ - - /* insert a sentinel so that __ffs returns size if there */ - /* are no set bits in the bitmap */ - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) - return __ffs((*addr) | (1ul << size)); - - /* the result of __ffs(0) is undefined, so it needs to be */ - /* handled separately */ - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) - return ((*addr) == 0) ? BITS_PER_LONG : __ffs(*addr); - - /* size is not constant or too big */ - return __find_first_bit(addr, size); -} - -extern unsigned long __find_first_zero_bit(const unsigned long *addr, - unsigned long size); +extern unsigned long find_first_bit(const unsigned long *addr, + unsigned long size); /** * find_first_zero_bit - find the first cleared bit in a memory region @@ -154,31 +132,12 @@ extern unsigned long __find_first_zero_bit(const unsigned long *addr, * * Returns the bit number of the first cleared bit. */ -static __always_inline unsigned long -find_first_zero_bit(const unsigned long *addr, unsigned long size) -{ - /* Avoid a function call if the bitmap size is a constant */ - /* and not bigger than BITS_PER_LONG. */ - - /* insert a sentinel so that __ffs returns size if there */ - /* are no set bits in the bitmap */ - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) { - return __ffs(~(*addr) | (1ul << size)); - } - - /* the result of __ffs(0) is undefined, so it needs to be */ - /* handled separately */ - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) - return (~(*addr) == 0) ? BITS_PER_LONG : __ffs(~(*addr)); - - /* size is not constant or too big */ - return __find_first_zero_bit(addr, size); -} +extern unsigned long find_first_zero_bit(const unsigned long *addr, + unsigned long size); + #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ #ifdef CONFIG_GENERIC_FIND_NEXT_BIT -extern unsigned long __find_next_bit(const unsigned long *addr, - unsigned long size, unsigned long offset); /** * find_next_bit - find the next set bit in a memory region @@ -186,36 +145,8 @@ extern unsigned long __find_next_bit(const unsigned long *addr, * @offset: The bitnumber to start searching at * @size: The bitmap size in bits */ -static __always_inline unsigned long -find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - unsigned long value; - - /* Avoid a function call if the bitmap size is a constant */ - /* and not bigger than BITS_PER_LONG. */ - - /* insert a sentinel so that __ffs returns size if there */ - /* are no set bits in the bitmap */ - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) { - value = (*addr) & ((~0ul) << offset); - value |= (1ul << size); - return __ffs(value); - } - - /* the result of __ffs(0) is undefined, so it needs to be */ - /* handled separately */ - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) { - value = (*addr) & ((~0ul) << offset); - return (value == 0) ? BITS_PER_LONG : __ffs(value); - } - - /* size is not constant or too big */ - return __find_next_bit(addr, size, offset); -} - -extern unsigned long __find_next_zero_bit(const unsigned long *addr, - unsigned long size, unsigned long offset); +extern unsigned long find_next_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); /** * find_next_zero_bit - find the next cleared bit in a memory region @@ -223,33 +154,11 @@ extern unsigned long __find_next_zero_bit(const unsigned long *addr, * @offset: The bitnumber to start searching at * @size: The bitmap size in bits */ -static __always_inline unsigned long -find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - unsigned long value; - - /* Avoid a function call if the bitmap size is a constant */ - /* and not bigger than BITS_PER_LONG. */ - - /* insert a sentinel so that __ffs returns size if there */ - /* are no set bits in the bitmap */ - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) { - value = (~(*addr)) & ((~0ul) << offset); - value |= (1ul << size); - return __ffs(value); - } - - /* the result of __ffs(0) is undefined, so it needs to be */ - /* handled separately */ - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) { - value = (~(*addr)) & ((~0ul) << offset); - return (value == 0) ? BITS_PER_LONG : __ffs(value); - } - - /* size is not constant or too big */ - return __find_next_zero_bit(addr, size, offset); -} + +extern unsigned long find_next_zero_bit(const unsigned long *addr, + unsigned long size, + unsigned long offset); + #endif /* CONFIG_GENERIC_FIND_NEXT_BIT */ #endif /* __KERNEL__ */ #endif -- cgit v1.1