Re: [V2] riscv: Implement Zbb based strlen and prefer it over the RVV based strlen implementation when Zbb is available

Florian Weimer <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
* Jeffrey Law:

> Neither the Zbb nor the RVV implementation seems at all sensitive to
> data alignment concerns on the K3.  So we can safely ignore that input
> axis and focus on how many cycles it takes to handle a string of a
> particular length.

The alignment affects the effective string length, though.

What about this (completely untested)?  The LLMs think it's never
slower.  The two-word and and three-word cases should be faster.

(I don't consider the attached version LLM-generated anymore.)

Thanks,
Florian
strlen-zbb.S (text/plain, 2.7 KB)
/* Re-include the RISC-V Zbb based strlen implementation.
   Copyright (C) 2026 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <https://www.gnu.org/licenses/>.  */

#if IS_IN(libc)
# define STRLEN __strlen_zbb
# undef libc_hidden_builtin_def
# define libc_hidden_builtin_def(name)
# undef weak_alias
# define weak_alias(name, alias)

#include <sysdep.h>
#include <sys/asm.h>

/* Assumptions: rvi_zbb.  */
/* Implementation from the Bitmanip specification.  */

#define src		a0
#define result		a0
#define addr		a1
#define data		a2
#define offset		a3
#define offset_bits	a3
#define mask		a3
#define m1		a4

#if __riscv_xlen == 64
# define REG_L	ld
# define SZREG	8
# define PTRLOG	3
#else
# define REG_L	lw
# define SZREG	4
# define PTRLOG	2
#endif

#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define CZ	clz
# define SHIFT	srl
#else
# define CZ	ctz
# define SHIFT	sll
#endif

#ifndef STRLEN
# define STRLEN __strlen_zbb
#endif

ENTRY (STRLEN)
.option push
.option arch,+zbb

	/* Number of irrelevant bytes in the first word.  */
	andi	offset, src, SZREG-1
	/* Align pointer.  */
	andi	addr, src, -SZREG

	li	m1, -1

	/* Get the first word.  */
	REG_L	data, 0(addr)

	slli	offset_bits, offset, PTRLOG

	/* Mask for ignored bytes.  The CZ in the epilogue compensates
	   for the negative offset from the pointer alignment.  */
	SHIFT	mask, m1, offset_bits

	/* Convert non-NUL into 0xff and NUL into 0x00.  */
	orc.b	data, data
	/* In data, convert non-NUL into 0x00 and NUL into 0xff.  */
	andn	data, mask, data

	/* Non-zero bytes mean that there is a NUL in the first word.  */
	bnez	data, L(epilogue)

	/* Our critical loop is 4 instructions and processes data in
	 * 4 byte or 8 byte chunks.  */
	.p2align 3
L(loop):
	REG_L	data, SZREG(addr)
	addi	addr, addr, SZREG
	orc.b	data, data
	beq	data, m1, L(loop)

	not	data, data

L(epilogue):
	/* Get number of processed words before this one.  */
	sub	result, addr, src
	CZ	data, data
	srli	data, data, 3
	/* Add number of characters in the last word.  */
	add	result, result, data
	ret

.option pop

END (STRLEN)
libc_hidden_builtin_def (STRLEN)
weak_alias (STRLEN, strlen)

#endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.