[PATCH 17/17] riscv: add vectorized strncasecmp
Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:48 +0800
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
The vector implementation folds and compares both operands in vector-length chunks using fault-only-first loads (vle8ff.v); vl is additionally capped by the remaining count so it never reads past the n-th byte and never crosses into an unmapped page. The case folding covers the ASCII letters A-Z only, matching the C/POSIX locale. This provides significant performance improvements on RVV-capable hardware. Use conditional compilation to fall back to the generic implementation when __riscv_vector is not available, maintaining compatibility with non-vector RISC-V systems. Signed-off-by: Pincheng Wang <[email protected]> --- newlib/libc/machine/riscv/Makefile.inc | 2 + newlib/libc/machine/riscv/strncasecmp-asm.S | 63 +++++++++++++++++++++ newlib/libc/machine/riscv/strncasecmp.c | 5 ++ 3 files changed, 70 insertions(+) create mode 100644 newlib/libc/machine/riscv/strncasecmp-asm.S create mode 100644 newlib/libc/machine/riscv/strncasecmp.c diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc index 2988f191f..6461aacd4 100644 --- a/newlib/libc/machine/riscv/Makefile.inc +++ b/newlib/libc/machine/riscv/Makefile.inc @@ -36,6 +36,8 @@ libc_a_SOURCES += \ %D%/strcspn.c \ %D%/strlen-asm.S \ %D%/strlen.c \ + %D%/strncasecmp-asm.S \ + %D%/strncasecmp.c \ %D%/strncat-asm.S \ %D%/strncat.c \ %D%/strncmp-asm.S \ diff --git a/newlib/libc/machine/riscv/strncasecmp-asm.S b/newlib/libc/machine/riscv/strncasecmp-asm.S new file mode 100644 index 000000000..03f4d8df0 --- /dev/null +++ b/newlib/libc/machine/riscv/strncasecmp-asm.S @@ -0,0 +1,63 @@ +#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED) +.text +.option push +.option arch, +v +/* int strncasecmp(const char *a0, const char *a1, size_t a2) + Case-insensitive compare of at most a2 bytes. vle8ff keeps loads from + crossing a page boundary; vl is also capped by the remaining count so we + never read past the n-th byte. The case folding covers the ASCII letters + A-Z only (the C/POSIX locale). */ +.global strncasecmp +.type strncasecmp, @function +strncasecmp: + beqz a2, .Lzero + li t0, 65 /* 'A' */ + li t1, 26 + li t2, 32 +.Lloop: + vsetvli zero, a2, e8, m1, ta, mu + vle8ff.v v8, (a0) + vle8ff.v v16, (a1) + csrr a3, vl + /* fold left */ + vsub.vx v24, v8, t0 + vmsltu.vx v0, v24, t1 + vadd.vx v8, v8, t2, v0.t + /* fold right */ + vsub.vx v24, v16, t0 + vmsltu.vx v0, v24, t1 + vadd.vx v16, v16, t2, v0.t + /* NUL in left or mismatch */ + vmseq.vi v1, v8, 0 + vmsne.vv v2, v8, v16 + vmor.mm v1, v1, v2 + sub a2, a2, a3 + vfirst.m a4, v1 + bgez a4, .Lend + add a0, a0, a3 + add a1, a1, a3 + bnez a2, .Lloop + /* exhausted n with no NUL/diff: all compared bytes were equal -> 0 */ + li a0, 0 + ret +.Lend: + add a0, a0, a4 + add a1, a1, a4 + lbu a4, 0(a0) + lbu a5, 0(a1) + addi a6, a4, -65 + sltiu a6, a6, 26 + slli a6, a6, 5 + add a4, a4, a6 + addi a6, a5, -65 + sltiu a6, a6, 26 + slli a6, a6, 5 + add a5, a5, a6 + sub a0, a4, a5 + ret +.Lzero: + li a0, 0 + ret +.size strncasecmp, .-strncasecmp +.option pop +#endif diff --git a/newlib/libc/machine/riscv/strncasecmp.c b/newlib/libc/machine/riscv/strncasecmp.c new file mode 100644 index 000000000..30f71d169 --- /dev/null +++ b/newlib/libc/machine/riscv/strncasecmp.c @@ -0,0 +1,5 @@ +#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || __riscv_xlen != 64 +# include "../../string/strncasecmp.c" +#else +/* strncasecmp defined in strncasecmp-asm.S */ +#endif -- 2.39.5