From: Andrew Cooper Date: Fri, 29 Dec 2017 12:56:24 +0000 (+0000) Subject: x86/bitops: Introduce variable/constant pairs for __{set,clear,change}_bit() X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~838 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2b84016c59dbe9f6e42e857a5d8176fd4e52c95c;p=xen.git x86/bitops: Introduce variable/constant pairs for __{set,clear,change}_bit() Just as with test_bit, the non-atomic set/clear/change helpers can be better optimised by the compiler in the case that the nr parameter is constant, and it often is. This results in a general replacement of `mov $imm, %reg; bt* %reg, mem` with the shorter and more simple `op $imm, mem`, also reducing register pressure. The net diffstat is: add/remove: 0/1 grow/shrink: 5/17 up/down: 90/-301 (-211) As a piece of minor cleanup, drop unnecessary brackets in the test_bit() macro, and fix the indentation. Signed-off-by: Andrew Cooper Reviewed-by: Dario Faggioli Reviewed-by: Jan Beulich --- diff --git a/xen/include/asm-x86/bitops.h b/xen/include/asm-x86/bitops.h index 440abb7ec9..e66d861080 100644 --- a/xen/include/asm-x86/bitops.h +++ b/xen/include/asm-x86/bitops.h @@ -51,13 +51,19 @@ static inline void set_bit(int nr, volatile void *addr) * If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static inline void __set_bit(int nr, void *addr) +static inline void variable_set_bit(int nr, void *addr) { asm volatile ( "btsl %1,%0" : "+m" (*(int *)addr) : "Ir" (nr) : "memory" ); } +static inline void constant_set_bit(int nr, void *addr) +{ + ((unsigned int *)addr)[nr >> 5] |= (1u << (nr & 31)); +} #define __set_bit(nr, addr) ({ \ if ( bitop_bad_size(addr) ) __bitop_bad_size(); \ - __set_bit(nr, addr); \ + __builtin_constant_p(nr) ? \ + constant_set_bit(nr, addr) : \ + variable_set_bit(nr, addr); \ }) /** @@ -86,13 +92,19 @@ static inline void clear_bit(int nr, volatile void *addr) * If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static inline void __clear_bit(int nr, void *addr) +static inline void variable_clear_bit(int nr, void *addr) { asm volatile ( "btrl %1,%0" : "+m" (*(int *)addr) : "Ir" (nr) : "memory" ); } +static inline void constant_clear_bit(int nr, void *addr) +{ + ((unsigned int *)addr)[nr >> 5] &= ~(1u << (nr & 31)); +} #define __clear_bit(nr, addr) ({ \ if ( bitop_bad_size(addr) ) __bitop_bad_size(); \ - __clear_bit(nr, addr); \ + __builtin_constant_p(nr) ? \ + constant_clear_bit(nr, addr) : \ + variable_clear_bit(nr, addr); \ }) /** @@ -104,13 +116,19 @@ static inline void __clear_bit(int nr, void *addr) * If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static inline void __change_bit(int nr, void *addr) +static inline void variable_change_bit(int nr, void *addr) { asm volatile ( "btcl %1,%0" : "+m" (*(int *)addr) : "Ir" (nr) : "memory" ); } +static inline void constant_change_bit(int nr, void *addr) +{ + ((unsigned int *)addr)[nr >> 5] ^= (1u << (nr & 31)); +} #define __change_bit(nr, addr) ({ \ if ( bitop_bad_size(addr) ) __bitop_bad_size(); \ - __change_bit(nr, addr); \ + __builtin_constant_p(nr) ? \ + constant_change_bit(nr, addr) : \ + variable_change_bit(nr, addr); \ }) /** @@ -291,9 +309,9 @@ static inline int variable_test_bit(int nr, const volatile void *addr) #define test_bit(nr, addr) ({ \ if ( bitop_bad_size(addr) ) __bitop_bad_size(); \ - (__builtin_constant_p(nr) ? \ - constant_test_bit((nr),(addr)) : \ - variable_test_bit((nr),(addr))); \ + __builtin_constant_p(nr) ? \ + constant_test_bit(nr, addr) : \ + variable_test_bit(nr, addr); \ }) extern unsigned int __find_first_bit(