Messages in this thread Patch in this message | | | From | Paul Burton <> | Subject | [PATCH 16/37] MIPS: bitops: Use generic builtin ffs/fls; drop cpu_has_clo_clz | Date | Mon, 30 Sep 2019 23:08:28 +0000 |
| |
The MIPS-specific implementations of __ffs(), ffs(), __fls() & fls() make use of the MIPS clz instruction where possible. They do this via inline asm, but in any configuration in which the kernel is built for a MIPS32 or MIPS64 release 1 or higher instruction set we know that these instructions are available & can be emitted using the __builtin_clz() function & other associated builtins which are provided by all currently supported versions of gcc.
When targeting an older instruction set GCC will generate a longer code sequence similar to the fallback cases we have in our implementations.
As such, remove our custom implementations of these functions & use the generic versions built atop compiler builtins. This allows us to drop a significant chunk of code, along with the cpu_has_clo_clz feature macro which was only used by these functions.
The only thing we lose here is the ability for kernels built to target a pre-r1 ISA to opportunistically make use of clz when running on a CPU that implements it. This seems like a small cost, and well worth paying to simplify the code.
Signed-off-by: Paul Burton <paul.burton@mips.com> ---
arch/mips/include/asm/bitops.h | 146 +----------------- arch/mips/include/asm/cpu-features.h | 10 -- .../asm/mach-malta/cpu-feature-overrides.h | 2 - 3 files changed, 4 insertions(+), 154 deletions(-)
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index 985d6a02f9ea..4b618afbfa5b 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -491,149 +491,11 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long * nudge_writes(); } -/* - * Return the bit position (0..63) of the most significant 1 bit in a word - * Returns -1 if no 1 bit exists - */ -static __always_inline unsigned long __fls(unsigned long word) -{ - int num; - - if (BITS_PER_LONG == 32 && !__builtin_constant_p(word) && - __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) { - __asm__( - " .set push \n" - " .set "MIPS_ISA_LEVEL" \n" - " clz %0, %1 \n" - " .set pop \n" - : "=r" (num) - : "r" (word)); - - return 31 - num; - } - - if (BITS_PER_LONG == 64 && !__builtin_constant_p(word) && - __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) { - __asm__( - " .set push \n" - " .set "MIPS_ISA_LEVEL" \n" - " dclz %0, %1 \n" - " .set pop \n" - : "=r" (num) - : "r" (word)); - - return 63 - num; - } - - num = BITS_PER_LONG - 1; - -#if BITS_PER_LONG == 64 - if (!(word & (~0ul << 32))) { - num -= 32; - word <<= 32; - } -#endif - if (!(word & (~0ul << (BITS_PER_LONG-16)))) { - num -= 16; - word <<= 16; - } - if (!(word & (~0ul << (BITS_PER_LONG-8)))) { - num -= 8; - word <<= 8; - } - if (!(word & (~0ul << (BITS_PER_LONG-4)))) { - num -= 4; - word <<= 4; - } - if (!(word & (~0ul << (BITS_PER_LONG-2)))) { - num -= 2; - word <<= 2; - } - if (!(word & (~0ul << (BITS_PER_LONG-1)))) - num -= 1; - return num; -} - -/* - * __ffs - find first bit in word. - * @word: The word to search - * - * Returns 0..SZLONG-1 - * Undefined if no bit exists, so code should check against 0 first. - */ -static __always_inline unsigned long __ffs(unsigned long word) -{ - return __fls(word & -word); -} - -/* - * fls - find last bit set. - * @word: The word to search - * - * This is defined the same way as ffs. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -static inline int fls(unsigned int x) -{ - int r; - - if (!__builtin_constant_p(x) && - __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) { - __asm__( - " .set push \n" - " .set "MIPS_ISA_LEVEL" \n" - " clz %0, %1 \n" - " .set pop \n" - : "=r" (x) - : "r" (x)); - - return 32 - x; - } - - r = 32; - if (!x) - return 0; - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; -} - +#include <asm-generic/bitops/builtin-__ffs.h> +#include <asm-generic/bitops/builtin-ffs.h> +#include <asm-generic/bitops/builtin-__fls.h> +#include <asm-generic/bitops/builtin-fls.h> #include <asm-generic/bitops/fls64.h> - -/* - * ffs - find first bit set. - * @word: The word to search - * - * This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static inline int ffs(int word) -{ - if (!word) - return 0; - - return fls(word & -word); -} - #include <asm-generic/bitops/ffz.h> #include <asm-generic/bitops/find.h> diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 983a6a7f43a1..274a35ae15af 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -362,16 +362,6 @@ }) #endif -/* - * MIPS32, MIPS64, VR5500, IDT32332, IDT32334 and maybe a few other - * pre-MIPS32/MIPS64 processors have CLO, CLZ. The IDT RC64574 is 64-bit and - * has CLO and CLZ but not DCLO nor DCLZ. For 64-bit kernels - * cpu_has_clo_clz also indicates the availability of DCLO and DCLZ. - */ -#ifndef cpu_has_clo_clz -#define cpu_has_clo_clz cpu_has_mips_r -#endif - /* * MIPS32 R2, MIPS64 R2, Loongson 3A and Octeon have WSBH. * MIPS64 R2, Loongson 3A and Octeon have WSBH, DSBH and DSHD. diff --git a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h index de3b66a3723e..193c0912d38e 100644 --- a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h @@ -32,7 +32,6 @@ /* #define cpu_has_vtag_icache ? */ /* #define cpu_has_dc_aliases ? */ /* #define cpu_has_ic_fills_f_dc ? */ -#define cpu_has_clo_clz 1 #define cpu_has_nofpuex 0 /* #define cpu_has_64bits ? */ /* #define cpu_has_64bit_zero_reg ? */ @@ -59,7 +58,6 @@ /* #define cpu_has_vtag_icache ? */ /* #define cpu_has_dc_aliases ? */ /* #define cpu_has_ic_fills_f_dc ? */ -#define cpu_has_clo_clz 1 #define cpu_has_nofpuex 0 /* #define cpu_has_64bits ? */ /* #define cpu_has_64bit_zero_reg ? */ -- 2.23.0
| |