Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <tglx@linutronix.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Thomas Gleixner and committed by
Linus Torvalds
fee4b19f 89723312

+19 -112
+9 -100
include/linux/bitops.h
··· 114 114 115 115 #ifdef __KERNEL__ 116 116 #ifdef CONFIG_GENERIC_FIND_FIRST_BIT 117 - extern unsigned long __find_first_bit(const unsigned long *addr, 118 - unsigned long size); 119 117 120 118 /** 121 119 * find_first_bit - find the first set bit in a memory region ··· 122 124 * 123 125 * Returns the bit number of the first set bit. 124 126 */ 125 - static __always_inline unsigned long 126 - find_first_bit(const unsigned long *addr, unsigned long size) 127 - { 128 - /* Avoid a function call if the bitmap size is a constant */ 129 - /* and not bigger than BITS_PER_LONG. */ 130 - 131 - /* insert a sentinel so that __ffs returns size if there */ 132 - /* are no set bits in the bitmap */ 133 - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) 134 - return __ffs((*addr) | (1ul << size)); 135 - 136 - /* the result of __ffs(0) is undefined, so it needs to be */ 137 - /* handled separately */ 138 - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) 139 - return ((*addr) == 0) ? BITS_PER_LONG : __ffs(*addr); 140 - 141 - /* size is not constant or too big */ 142 - return __find_first_bit(addr, size); 143 - } 144 - 145 - extern unsigned long __find_first_zero_bit(const unsigned long *addr, 146 - unsigned long size); 127 + extern unsigned long find_first_bit(const unsigned long *addr, 128 + unsigned long size); 147 129 148 130 /** 149 131 * find_first_zero_bit - find the first cleared bit in a memory region ··· 132 154 * 133 155 * Returns the bit number of the first cleared bit. 134 156 */ 135 - static __always_inline unsigned long 136 - find_first_zero_bit(const unsigned long *addr, unsigned long size) 137 - { 138 - /* Avoid a function call if the bitmap size is a constant */ 139 - /* and not bigger than BITS_PER_LONG. */ 157 + extern unsigned long find_first_zero_bit(const unsigned long *addr, 158 + unsigned long size); 140 159 141 - /* insert a sentinel so that __ffs returns size if there */ 142 - /* are no set bits in the bitmap */ 143 - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) { 144 - return __ffs(~(*addr) | (1ul << size)); 145 - } 146 - 147 - /* the result of __ffs(0) is undefined, so it needs to be */ 148 - /* handled separately */ 149 - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) 150 - return (~(*addr) == 0) ? BITS_PER_LONG : __ffs(~(*addr)); 151 - 152 - /* size is not constant or too big */ 153 - return __find_first_zero_bit(addr, size); 154 - } 155 160 #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ 156 161 157 162 #ifdef CONFIG_GENERIC_FIND_NEXT_BIT 158 - extern unsigned long __find_next_bit(const unsigned long *addr, 159 - unsigned long size, unsigned long offset); 160 163 161 164 /** 162 165 * find_next_bit - find the next set bit in a memory region ··· 145 186 * @offset: The bitnumber to start searching at 146 187 * @size: The bitmap size in bits 147 188 */ 148 - static __always_inline unsigned long 149 - find_next_bit(const unsigned long *addr, unsigned long size, 150 - unsigned long offset) 151 - { 152 - unsigned long value; 153 - 154 - /* Avoid a function call if the bitmap size is a constant */ 155 - /* and not bigger than BITS_PER_LONG. */ 156 - 157 - /* insert a sentinel so that __ffs returns size if there */ 158 - /* are no set bits in the bitmap */ 159 - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) { 160 - value = (*addr) & ((~0ul) << offset); 161 - value |= (1ul << size); 162 - return __ffs(value); 163 - } 164 - 165 - /* the result of __ffs(0) is undefined, so it needs to be */ 166 - /* handled separately */ 167 - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) { 168 - value = (*addr) & ((~0ul) << offset); 169 - return (value == 0) ? BITS_PER_LONG : __ffs(value); 170 - } 171 - 172 - /* size is not constant or too big */ 173 - return __find_next_bit(addr, size, offset); 174 - } 175 - 176 - extern unsigned long __find_next_zero_bit(const unsigned long *addr, 177 - unsigned long size, unsigned long offset); 189 + extern unsigned long find_next_bit(const unsigned long *addr, 190 + unsigned long size, unsigned long offset); 178 191 179 192 /** 180 193 * find_next_zero_bit - find the next cleared bit in a memory region ··· 154 223 * @offset: The bitnumber to start searching at 155 224 * @size: The bitmap size in bits 156 225 */ 157 - static __always_inline unsigned long 158 - find_next_zero_bit(const unsigned long *addr, unsigned long size, 159 - unsigned long offset) 160 - { 161 - unsigned long value; 162 226 163 - /* Avoid a function call if the bitmap size is a constant */ 164 - /* and not bigger than BITS_PER_LONG. */ 227 + extern unsigned long find_next_zero_bit(const unsigned long *addr, 228 + unsigned long size, 229 + unsigned long offset); 165 230 166 - /* insert a sentinel so that __ffs returns size if there */ 167 - /* are no set bits in the bitmap */ 168 - if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) { 169 - value = (~(*addr)) & ((~0ul) << offset); 170 - value |= (1ul << size); 171 - return __ffs(value); 172 - } 173 - 174 - /* the result of __ffs(0) is undefined, so it needs to be */ 175 - /* handled separately */ 176 - if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) { 177 - value = (~(*addr)) & ((~0ul) << offset); 178 - return (value == 0) ? BITS_PER_LONG : __ffs(value); 179 - } 180 - 181 - /* size is not constant or too big */ 182 - return __find_next_zero_bit(addr, size, offset); 183 - } 184 231 #endif /* CONFIG_GENERIC_FIND_NEXT_BIT */ 185 232 #endif /* __KERNEL__ */ 186 233 #endif
+10 -12
lib/find_next_bit.c
··· 20 20 /* 21 21 * Find the next set bit in a memory region. 22 22 */ 23 - unsigned long __find_next_bit(const unsigned long *addr, 24 - unsigned long size, unsigned long offset) 23 + unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 24 + unsigned long offset) 25 25 { 26 26 const unsigned long *p = addr + BITOP_WORD(offset); 27 27 unsigned long result = offset & ~(BITS_PER_LONG-1); ··· 58 58 found_middle: 59 59 return result + __ffs(tmp); 60 60 } 61 - EXPORT_SYMBOL(__find_next_bit); 61 + EXPORT_SYMBOL(find_next_bit); 62 62 63 63 /* 64 64 * This implementation of find_{first,next}_zero_bit was stolen from 65 65 * Linus' asm-alpha/bitops.h. 66 66 */ 67 - unsigned long __find_next_zero_bit(const unsigned long *addr, 68 - unsigned long size, unsigned long offset) 67 + unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, 68 + unsigned long offset) 69 69 { 70 70 const unsigned long *p = addr + BITOP_WORD(offset); 71 71 unsigned long result = offset & ~(BITS_PER_LONG-1); ··· 102 102 found_middle: 103 103 return result + ffz(tmp); 104 104 } 105 - EXPORT_SYMBOL(__find_next_zero_bit); 105 + EXPORT_SYMBOL(find_next_zero_bit); 106 106 #endif /* CONFIG_GENERIC_FIND_NEXT_BIT */ 107 107 108 108 #ifdef CONFIG_GENERIC_FIND_FIRST_BIT 109 109 /* 110 110 * Find the first set bit in a memory region. 111 111 */ 112 - unsigned long __find_first_bit(const unsigned long *addr, 113 - unsigned long size) 112 + unsigned long find_first_bit(const unsigned long *addr, unsigned long size) 114 113 { 115 114 const unsigned long *p = addr; 116 115 unsigned long result = 0; ··· 130 131 found: 131 132 return result + __ffs(tmp); 132 133 } 133 - EXPORT_SYMBOL(__find_first_bit); 134 + EXPORT_SYMBOL(find_first_bit); 134 135 135 136 /* 136 137 * Find the first cleared bit in a memory region. 137 138 */ 138 - unsigned long __find_first_zero_bit(const unsigned long *addr, 139 - unsigned long size) 139 + unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) 140 140 { 141 141 const unsigned long *p = addr; 142 142 unsigned long result = 0; ··· 156 158 found: 157 159 return result + ffz(tmp); 158 160 } 159 - EXPORT_SYMBOL(__find_first_zero_bit); 161 + EXPORT_SYMBOL(find_first_zero_bit); 160 162 #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ 161 163 162 164 #ifdef __BIG_ENDIAN