[PATCH 16/17] riscv: add vectorized strcasecmp
Pincheng Wang
pincheng.plct@isrc.iscas.ac.cn
Thu Jul 16 15:00:47 GMT 2026
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 <pincheng.plct@isrc.iscas.ac.cn>
---
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
More information about the Newlib
mailing list