[PATCH 16/17] riscv: add vectorized strcasecmp
Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:47 +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), so a vector load is never forced across a page boundary into an unmapped page. The case folding covers the ASCII letters A-Z only, matching the C/POSIX locale; builds that need locale-aware folding are handled by the guard below. 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/strcasecmp-asm.S | 65 ++++++++++++++++++++++ newlib/libc/machine/riscv/strcasecmp.c | 5 ++ 3 files changed, 72 insertions(+) create mode 100644 newlib/libc/machine/riscv/strcasecmp-asm.S create mode 100644 newlib/libc/machine/riscv/strcasecmp.c diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc index c2d918d03..2988f191f 100644 --- a/newlib/libc/machine/riscv/Makefile.inc +++ b/newlib/libc/machine/riscv/Makefile.inc @@ -20,6 +20,8 @@ libc_a_SOURCES += \ %D%/memset.S \ %D%/setjmp.S \ %D%/stpcpy.c \ + %D%/strcasecmp-asm.S \ + %D%/strcasecmp.c \ %D%/strcat-asm.S \ %D%/strcat.c \ %D%/strchr-asm.S \ diff --git a/newlib/libc/machine/riscv/strcasecmp-asm.S b/newlib/libc/machine/riscv/strcasecmp-asm.S new file mode 100644 index 000000000..3b07ea164 --- /dev/null +++ b/newlib/libc/machine/riscv/strcasecmp-asm.S @@ -0,0 +1,65 @@ +#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED) +.text +.option push +.option arch, +v +/* int strcasecmp(const char *a0, const char *a1) + Case-insensitive compare. Scans with vle8ff so a vector load is never + forced across a page boundary into an unmapped page: element 0 is always + loaded, and a fault on any later element merely truncates vl. The case + folding covers the ASCII letters A-Z only (the C/POSIX locale). */ +.global strcasecmp +.type strcasecmp, @function +strcasecmp: + li t0, 65 /* 'A' */ + li t1, 26 /* range of upper-case letters */ + li t2, 32 /* 'a' - 'A' */ +.Lloop: + vsetvli a2, zero, e8, m1, ta, mu + vle8ff.v v8, (a0) + vle8ff.v v16, (a1) + csrr a2, vl + /* fold left: if (b-'A') <u 26 then b += 32 */ + 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 + /* compare folded bytes */ + vmseq.vi v1, v8, 0 /* NUL in left */ + vmsne.vv v2, v8, v16 /* mismatch */ + vfirst.m a3, v1 + vfirst.m a4, v2 + bgez a3, .Lnul + bgez a4, .Ldiff + add a0, a0, a2 + add a1, a1, a2 + j .Lloop +.Lnul: /* a3 >= 0 (NUL position) */ + bltz a4, .Lend + bge a4, a3, .Lend /* NUL at or before mismatch */ + mv a3, a4 + j .Lend +.Ldiff: /* a3 < 0, a4 >= 0 */ + mv a3, a4 +.Lend: + add a0, a0, a3 + add a1, a1, a3 + lbu a4, 0(a0) + lbu a5, 0(a1) + /* tolower(a4) */ + addi a6, a4, -65 + sltiu a6, a6, 26 + slli a6, a6, 5 + add a4, a4, a6 + /* tolower(a5) */ + addi a6, a5, -65 + sltiu a6, a6, 26 + slli a6, a6, 5 + add a5, a5, a6 + sub a0, a4, a5 + ret +.size strcasecmp, .-strcasecmp +.option pop +#endif diff --git a/newlib/libc/machine/riscv/strcasecmp.c b/newlib/libc/machine/riscv/strcasecmp.c new file mode 100644 index 000000000..d603d09bc --- /dev/null +++ b/newlib/libc/machine/riscv/strcasecmp.c @@ -0,0 +1,5 @@ +#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || __riscv_xlen != 64 +# include "../../string/strcasecmp.c" +#else +/* strcasecmp defined in strcasecmp-asm.S */ +#endif -- 2.39.5