From: "Ze Huang" <huang.ze@linux.dev>
To: "Jisheng Zhang" <jszhang@kernel.org>,
"Paul Walmsley" <pjw@kernel.org>,
"Palmer Dabbelt" <palmer@dabbelt.com>,
"Albert Ou" <aou@eecs.berkeley.edu>,
"Alexandre Ghiti" <alex@ghiti.fr>
Cc: <linux-riscv@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
"linux-riscv" <linux-riscv-bounces@lists.infradead.org>
Subject: Re: [PATCH RESEND v5 3/3] riscv: word-at-a-time: improve find_zero() for Zbb
Date: Sun, 08 Nov 2026 18:32:07 +0800 [thread overview]
Message-ID: <DMPREBS6GFIY.1NHDQRMP9OUKQ@linux.dev> (raw)
In-Reply-To: <20261107134613.17830-4-jszhang@kernel.org>
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@linux.dev>
>
> Signed-off-by: Jisheng Zhang <jszhang@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
>
WARNING: multiple messages have this Message-ID (diff)
From: "Ze Huang" <huang.ze@linux.dev>
To: "Jisheng Zhang" <jszhang@kernel.org>,
"Paul Walmsley" <pjw@kernel.org>,
"Palmer Dabbelt" <palmer@dabbelt.com>,
"Albert Ou" <aou@eecs.berkeley.edu>,
"Alexandre Ghiti" <alex@ghiti.fr>
Cc: <linux-riscv@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
"linux-riscv" <linux-riscv-bounces@lists.infradead.org>
Subject: Re: [PATCH RESEND v5 3/3] riscv: word-at-a-time: improve find_zero() for Zbb
Date: Sun, 08 Nov 2026 18:32:07 +0800 [thread overview]
Message-ID: <DMPREBS6GFIY.1NHDQRMP9OUKQ@linux.dev> (raw)
In-Reply-To: <20261107134613.17830-4-jszhang@kernel.org>
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@linux.dev>
>
> Signed-off-by: Jisheng Zhang <jszhang@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
>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2026-11-08 10:32 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 13:46 [PATCH RESEND v5 0/3] riscv: word-at-a-time: improve find_zero() Jisheng Zhang
2026-11-07 13:46 ` Jisheng Zhang
2026-11-07 13:46 ` [PATCH RESEND v5 1/3] riscv: word-at-a-time: improve find_zero() for !RISCV_ISA_ZBB or no Zbb Jisheng Zhang
2026-11-07 13:46 ` Jisheng Zhang
2026-11-07 13:46 ` [PATCH RESEND v5 2/3] riscv: word-at-a-time: improve find_zero() for RV32 Jisheng Zhang
2026-11-07 13:46 ` Jisheng Zhang
2026-11-07 13:46 ` [PATCH RESEND v5 3/3] riscv: word-at-a-time: improve find_zero() for Zbb Jisheng Zhang
2026-11-07 13:46 ` Jisheng Zhang
2026-11-08 10:32 ` Ze Huang [this message]
2026-11-08 10:32 ` Ze Huang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DMPREBS6GFIY.1NHDQRMP9OUKQ@linux.dev \
--to=huang.ze@linux.dev \
--cc=alex@ghiti.fr \
--cc=aou@eecs.berkeley.edu \
--cc=jszhang@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv-bounces@lists.infradead.org \
--cc=linux-riscv@lists.infradead.org \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.