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