[PATCH RESEND v5 3/3] riscv: word-at-a-time: improve find_zero() for Zbb

Ze Huang huang.ze at linux.dev
Sun Nov 8 02:32:07 PST 2026


On Sat Nov 7, 2026 at 9:46 PM CST, Jisheng Zhang wrote:
> In commit f915a3e5b018 ("arm64: word-at-a-time: improve byte count
> calculations for LE"), Linus improved the find_zero() for arm64 LE.
> Do the same optimization as he did: "do __ffs() on the intermediate value
> that found whether there is a zero byte, before we've actually computed
> the final byte mask.", so that we share the similar improvements:
>
> "The difference between the old and the new implementation is that
> "count_zero()" ends up scheduling better because it is being done on a
> value that is available earlier (before the final mask).
>
> But more importantly, it can be implemented without the insane semantics
> of the standard bit finding helpers that have the off-by-one issue and
> have to special-case the zero mask situation."
>
> Before the patch:
> 0000000000000000 <find_zero>:
>    0:	c909                	beqz	a0,12 <.L1>
>    2:	60051793          	clz	a5,a0
>    6:	03f00513          	li	a0,63
>    a:	8d1d                	sub	a0,a0,a5
>    c:	2505                	addiw	a0,a0,1
>    e:	4035551b          	sraiw	a0,a0,0x3
>
> 0000000000000012 <.L1>:
>   12:	8082                	ret
>
> After the patch:
>
> 0000000000000000 <find_zero>:
>    0:	60151513          	ctz	a0,a0
>    4:	810d                	srli	a0,a0,0x3
>    6:	8082                	ret
>
> 7 instructions vs 3 instructions!
>
> As can be seen, on RV64 w/ Zbb, the new "find_zero()" ends up just
> "ctz" plus the shift right that then ends up being subsumed by the
> "add to final length".
>
> But I have no HW platform which supports Zbb, so I can't get the
> performance improvement numbers by the last patch, only built and
> tested the patch on QEMU.

Hi,

I tested patch 3 on a SpacemiT K3 board (rv64imafdcvbvh, Zbb).

Against patch 1+2, the has_zero -> prep -> create_zero_mask -> find_zero chain
takes 45% less time: 3.74 ns -> 2.05 ns per call (-1.69 ns). Both versions are
built into the same image and measured alternately within one boot (6 cold
boots).

Note that this is a per-call figure, not a workload one: find_zero() runs once
per string operation, which takes less than 1% time of an openat() here.

Method and raw data:
https://gist.github.com/Sutter099/1c51abdb192eeedbf051ae582a1e8145#file-fzbench-md

Tested-by: Ze Huang <huang.ze at linux.dev>

>
> Signed-off-by: Jisheng Zhang <jszhang at kernel.org>
> ---
>  arch/riscv/include/asm/word-at-a-time.h | 18 +++++++++++++++---
>  1 file changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/arch/riscv/include/asm/word-at-a-time.h b/arch/riscv/include/asm/word-at-a-time.h
> index f2d16c1eea8d..31240133eccd 100644
> --- a/arch/riscv/include/asm/word-at-a-time.h
> +++ b/arch/riscv/include/asm/word-at-a-time.h
> @@ -35,6 +35,10 @@ static inline unsigned long prep_zero_mask(unsigned long val,
>  
>  static inline unsigned long create_zero_mask(unsigned long bits)
>  {
> +	if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) &&
> +	    riscv_has_extension_likely(RISCV_ISA_EXT_ZBB))
> +		return bits;
> +
>  	bits = (bits - 1) & ~bits;
>  	return bits >> 7;
>  }
> @@ -67,13 +71,21 @@ static inline unsigned long find_zero(unsigned long mask)
>  {
>  	if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) &&
>  	    riscv_has_extension_likely(RISCV_ISA_EXT_ZBB))
> -		return !mask ? 0 : ((__fls(mask) + 1) >> 3);
> +		return __ffs(mask) >> 3;
>  
>  	return count_masked_bytes(mask);
>  }
>  
> -/* The mask we created is directly usable as a bytemask */
> -#define zero_bytemask(mask) (mask)
> +static inline unsigned long zero_bytemask(unsigned long bits)
> +{
> +	if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) &&
> +	    riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) {
> +		bits = (bits - 1) & ~bits;
> +		return bits >> 7;
> +	}
> +
> +	return bits;
> +}
>  
>  #ifdef CONFIG_DCACHE_WORD_ACCESS
>  





More information about the linux-riscv mailing list