[PATCH v3 06/15] riscv: add vectorized strcmp

Pincheng Wang <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
The vector implementation compares both operands in vector-length chunks
using fault-only-first loads (vle8ff.v), detecting the terminating NUL and
the first differing byte in the same pass without ever crossing into an
unmapped page.  This provides significant performance improvements on
RVV-capable hardware.  Use conditional compilation to fall back to the
existing scalar 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 |  1 +
 newlib/libc/machine/riscv/strcmp-asm.S | 51 ++++++++++++++++++++++++++
 newlib/libc/machine/riscv/strcmp.S     |  4 ++
 3 files changed, 56 insertions(+)
 create mode 100644 newlib/libc/machine/riscv/strcmp-asm.S

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index 4bb7fefbb..243195b36 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -24,6 +24,7 @@ libc_a_SOURCES += \
 	%D%/strchr.c \
 	%D%/strchrnul-asm.S \
 	%D%/strchrnul.c \
+	%D%/strcmp-asm.S \
 	%D%/strcmp.S \
 	%D%/strcpy.c \
 	%D%/strlen-asm.S \
diff --git a/newlib/libc/machine/riscv/strcmp-asm.S b/newlib/libc/machine/riscv/strcmp-asm.S
new file mode 100644
index 000000000..5592a88b6
--- /dev/null
+++ b/newlib/libc/machine/riscv/strcmp-asm.S
@@ -0,0 +1,51 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+ENTRY(strcmp)
+.Lloop:
+  vsetvli a2, zero, e8, m1, ta, ma
+  vle8ff.v v0, (a0)
+  /* check if v0[i] == 0 */
+  vmseq.vx v16, v0, zero
+
+  vle8ff.v v8, (a1)
+  /* check if v0[i] != v8[i] */
+  vmsne.vv v17, v0, v8
+
+  /* find the index x for v0[x]==0 */
+  vfirst.m a3, v16
+  /* find the index x for v0[x]!=v8[x] */
+  vfirst.m a4, v17
+
+  bgez a3, .Lcheck1
+  bgez a4, .Lcheck2
+
+  /* get the current vl updated by vle8ff. */
+  csrr a2, vl
+  add a0, a0, a2
+  add a1, a1, a2
+  j .Lloop
+
+  /* a3>=0 */
+.Lcheck1:
+  bltz a4, .Lreturn_at_nul
+  blt a4, a3, .Lcheck2
+.Lreturn_at_nul:
+  /* a4<0, or a4>=0 && a3<=a4 */
+  add a0, a0, a3
+  add a1, a1, a3
+  lbu a3, 0(a0)
+  lbu a4, 0(a1)
+  sub a0, a3, a4
+  ret
+
+  /* a3<0 && a4>=0, or a4<a3 */
+.Lcheck2:
+  add a0, a0, a4
+  add a1, a1, a4
+  lbu a3, 0(a0)
+  lbu a4, 0(a1)
+  sub a0, a3, a4
+  ret
+END(strcmp)
+#endif
diff --git a/newlib/libc/machine/riscv/strcmp.S b/newlib/libc/machine/riscv/strcmp.S
index 1fd0f1440..8f2f406af 100644
--- a/newlib/libc/machine/riscv/strcmp.S
+++ b/newlib/libc/machine/riscv/strcmp.S
@@ -12,6 +12,8 @@
 #include <sys/asm.h>
 #include "newlib.h"
 
+#if !(defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED))
+
 ENTRY(strcmp)
 
 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
@@ -243,3 +245,5 @@ mask:
 .dword 0x7f7f7f7f7f7f7f7f
 #endif
 #endif
+
+#endif /* not __riscv_vector */
-- 
2.39.5
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.