[PATCH 00/17] riscv: vectorized str* routines

Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:31 +0800
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
Hi all,

This series adds RISC-V Vector Extension (RVV) implementations for the str*
family in Newlib, as a follow-up to the earlier mem* work (memset, memcpy,
memmove, and then memccpy, memchr, memcmp, mempcpy, memrchr, rawmemchr).  It
covers the following 17 interfaces:

  strlen, strnlen, strchr, strchrnul, strrchr, strcmp, strncmp, strcpy,
  strncpy, strcat, strncat, strspn, strcspn, strpbrk, strstr, strcasecmp,
  strncasecmp

Each routine follows the same integration pattern as the mem* series: a
hand-written <func>-asm.S guarded by

  __riscv_vector && __riscv_xlen == 64
    && !__OPTIMIZE_SIZE__ && !PREFER_SIZE_OVER_SPEED

with a small <func>.c that falls back to the existing scalar or generic
implementation when the guard is not satisfied, so non-vector RISC-V targets are
unaffected.  For strlen, strcmp, and strcpy the existing hand-optimized scalar
code is kept as the fallback.

Page-boundary safety was a primary concern.  Every scan reads its input(s) with
fault-only-first loads (vle8ff.v): element 0 is always loaded and a fault on any
later element merely truncates vl, so a vector load is never forced across a
page boundary into an unmapped page.  The bounded routines (strnlen, strncmp,
strncpy, strncat, strncasecmp) additionally cap vl by the remaining count so
they never read past the n-th byte.  The set routines (strspn, strcspn, strpbrk)
build a 256-byte table on the stack and gather through it with vluxei8.v, which
only touches the fully-mapped table.  strstr combines a vle8ff scan for the
needle's first byte with a byte-wise verify that stops at a NUL, so neither
phase crosses past the end of either string.


Please note that strcasecmp/strncasecmp fold only the ASCII letters A-Z, i.e.
they implement the C/POSIX locale.  Targets that need locale-aware folding fall
through the guard to the generic implementation.  I'm happy to drop these two if
the locale divergence is unwelcome.

As with the mem* series, this is a fair amount of hand-written assembly to
maintain; other architectures rarely optimize the whole str* family.  I'm glad
to trim the set to whatever subset is considered worth carrying.

Comments and suggestions welcome.

Best regards,
Pincheng Wang

Pincheng Wang (17):
  riscv: add vectorized strlen
  riscv: add vectorized strnlen
  riscv: add vectorized strchr
  riscv: add vectorized strchrnul
  riscv: add vectorized strrchr
  riscv: add vectorized strcmp
  riscv: add vectorized strncmp
  riscv: add vectorized strcpy
  riscv: add vectorized strncpy
  riscv: add vectorized strcat
  riscv: add vectorized strncat
  riscv: add vectorized strspn
  riscv: add vectorized strcspn
  riscv: add vectorized strpbrk
  riscv: add vectorized strstr
  riscv: add vectorized strcasecmp
  riscv: add vectorized strncasecmp

 newlib/libc/machine/riscv/Makefile.inc      | 33 ++++++++++-
 newlib/libc/machine/riscv/strcasecmp-asm.S  | 65 +++++++++++++++++++++
 newlib/libc/machine/riscv/strcasecmp.c      |  5 ++
 newlib/libc/machine/riscv/strcat-asm.S      | 40 +++++++++++++
 newlib/libc/machine/riscv/strcat.c          |  5 ++
 newlib/libc/machine/riscv/strchr-asm.S      | 29 +++++++++
 newlib/libc/machine/riscv/strchr.c          |  5 ++
 newlib/libc/machine/riscv/strchrnul-asm.S   | 31 ++++++++++
 newlib/libc/machine/riscv/strchrnul.c       |  5 ++
 newlib/libc/machine/riscv/strcmp-asm.S      | 55 +++++++++++++++++
 newlib/libc/machine/riscv/strcmp.S          |  4 ++
 newlib/libc/machine/riscv/strcpy-asm.S      | 24 ++++++++
 newlib/libc/machine/riscv/strcpy.c          |  5 ++
 newlib/libc/machine/riscv/strcspn-asm.S     | 55 +++++++++++++++++
 newlib/libc/machine/riscv/strcspn.c         |  5 ++
 newlib/libc/machine/riscv/strlen-asm.S      | 25 ++++++++
 newlib/libc/machine/riscv/strlen.c          |  5 ++
 newlib/libc/machine/riscv/strncasecmp-asm.S | 63 ++++++++++++++++++++
 newlib/libc/machine/riscv/strncasecmp.c     |  5 ++
 newlib/libc/machine/riscv/strncat-asm.S     | 47 +++++++++++++++
 newlib/libc/machine/riscv/strncat.c         |  5 ++
 newlib/libc/machine/riscv/strncmp-asm.S     | 51 ++++++++++++++++
 newlib/libc/machine/riscv/strncmp.c         |  5 ++
 newlib/libc/machine/riscv/strncpy-asm.S     | 46 +++++++++++++++
 newlib/libc/machine/riscv/strncpy.c         |  5 ++
 newlib/libc/machine/riscv/strnlen-asm.S     | 28 +++++++++
 newlib/libc/machine/riscv/strnlen.c         |  5 ++
 newlib/libc/machine/riscv/strpbrk-asm.S     | 55 +++++++++++++++++
 newlib/libc/machine/riscv/strpbrk.c         |  5 ++
 newlib/libc/machine/riscv/strrchr-asm.S     | 42 +++++++++++++
 newlib/libc/machine/riscv/strrchr.c         |  5 ++
 newlib/libc/machine/riscv/strspn-asm.S      | 51 ++++++++++++++++
 newlib/libc/machine/riscv/strspn.c          |  5 ++
 newlib/libc/machine/riscv/strstr-asm.S      | 55 +++++++++++++++++
 newlib/libc/machine/riscv/strstr.c          |  5 ++
 35 files changed, 878 insertions(+), 1 deletion(-)
 create mode 100644 newlib/libc/machine/riscv/strcasecmp-asm.S
 create mode 100644 newlib/libc/machine/riscv/strcasecmp.c
 create mode 100644 newlib/libc/machine/riscv/strcat-asm.S
 create mode 100644 newlib/libc/machine/riscv/strcat.c
 create mode 100644 newlib/libc/machine/riscv/strchr-asm.S
 create mode 100644 newlib/libc/machine/riscv/strchr.c
 create mode 100644 newlib/libc/machine/riscv/strchrnul-asm.S
 create mode 100644 newlib/libc/machine/riscv/strchrnul.c
 create mode 100644 newlib/libc/machine/riscv/strcmp-asm.S
 create mode 100644 newlib/libc/machine/riscv/strcpy-asm.S
 create mode 100644 newlib/libc/machine/riscv/strcspn-asm.S
 create mode 100644 newlib/libc/machine/riscv/strcspn.c
 create mode 100644 newlib/libc/machine/riscv/strlen-asm.S
 create mode 100644 newlib/libc/machine/riscv/strncasecmp-asm.S
 create mode 100644 newlib/libc/machine/riscv/strncasecmp.c
 create mode 100644 newlib/libc/machine/riscv/strncat-asm.S
 create mode 100644 newlib/libc/machine/riscv/strncat.c
 create mode 100644 newlib/libc/machine/riscv/strncmp-asm.S
 create mode 100644 newlib/libc/machine/riscv/strncmp.c
 create mode 100644 newlib/libc/machine/riscv/strncpy-asm.S
 create mode 100644 newlib/libc/machine/riscv/strncpy.c
 create mode 100644 newlib/libc/machine/riscv/strnlen-asm.S
 create mode 100644 newlib/libc/machine/riscv/strnlen.c
 create mode 100644 newlib/libc/machine/riscv/strpbrk-asm.S
 create mode 100644 newlib/libc/machine/riscv/strpbrk.c
 create mode 100644 newlib/libc/machine/riscv/strrchr-asm.S
 create mode 100644 newlib/libc/machine/riscv/strrchr.c
 create mode 100644 newlib/libc/machine/riscv/strspn-asm.S
 create mode 100644 newlib/libc/machine/riscv/strspn.c
 create mode 100644 newlib/libc/machine/riscv/strstr-asm.S
 create mode 100644 newlib/libc/machine/riscv/strstr.c

-- 
2.39.5