[PATCH v3 07/15] riscv: add vectorized strncmp

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); vl is additionally capped by the
remaining count so it never reads past the n-th byte and never crosses
into an unmapped page.  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/strncmp-asm.S | 47 +++++++++++++++++++++++++
 newlib/libc/machine/riscv/strncmp.c     |  5 +++
 3 files changed, 54 insertions(+)
 create mode 100644 newlib/libc/machine/riscv/strncmp-asm.S
 create mode 100644 newlib/libc/machine/riscv/strncmp.c

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index 243195b36..015b91799 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -29,6 +29,8 @@ libc_a_SOURCES += \
 	%D%/strcpy.c \
 	%D%/strlen-asm.S \
 	%D%/strlen.c \
+	%D%/strncmp-asm.S \
+	%D%/strncmp.c \
 	%D%/strnlen-asm.S \
 	%D%/strnlen.c \
 	%D%/strrchr-asm.S \
diff --git a/newlib/libc/machine/riscv/strncmp-asm.S b/newlib/libc/machine/riscv/strncmp-asm.S
new file mode 100644
index 000000000..c178c32e2
--- /dev/null
+++ b/newlib/libc/machine/riscv/strncmp-asm.S
@@ -0,0 +1,47 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+ENTRY(strncmp)
+  beqz a2, .Lzero_length
+.Lloop:
+  vsetvli zero, a2, e8, m1, ta, ma
+
+  vle8ff.v v0, (a0)
+  /* v0[i] == 0.  */
+  vmseq.vx v8, v0, zero
+
+  vle8ff.v v4, (a1)
+  /* v0[i] != v4[i].  */
+  vmsne.vv v9, v0, v4
+
+  csrr a3, vl
+
+  /* r = mask1 | mask2
+     Combine the first NUL in a0 with the first differing byte so a single
+     vfirst.m locates whichever comes first.  */
+  vmor.mm v8, v8, v9
+
+  sub a2, a2, a3
+
+  vfirst.m a4, v8
+
+  bgez a4, .Lend_loop
+
+  add a0, a0, a3
+  add a1, a1, a3
+  bnez a2, .Lloop
+.Lend_loop:
+
+  add a0, a0, a4
+  add a1, a1, a4
+  lbu a4, 0(a0)
+  lbu a5, 0(a1)
+
+  sub a0, a4, a5
+  ret
+
+.Lzero_length:
+  li a0, 0
+  ret
+END(strncmp)
+#endif
diff --git a/newlib/libc/machine/riscv/strncmp.c b/newlib/libc/machine/riscv/strncmp.c
new file mode 100644
index 000000000..81ccf1e58
--- /dev/null
+++ b/newlib/libc/machine/riscv/strncmp.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector)
+# include "../../string/strncmp.c"
+#else
+/* strncmp defined in strncmp-asm.S */
+#endif
-- 
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.