master: arm64: implement simd-copy-utf8-sap-to-character-string using NEON

stassats via Sbcl-commits <[email protected]> Sun, 28 Jun 2026 20:40:52 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  db02ba3bce49baa7b7e414945d9b8be914b0b7f5 (commit)
      from  7e81a161c78d6dc2200aab516d00917856da0f52 (commit)

- Log -----------------------------------------------------------------
commit db02ba3bce49baa7b7e414945d9b8be914b0b7f5
Author: Stas Boukarev <[email protected]>
Date:   Sun Jun 28 23:39:48 2026 +0300

    arm64: implement simd-copy-utf8-sap-to-character-string using NEON
---
 src/code/arm64-simd.lisp                 | 46 ++++++++++++++++++++++++++++++++
 src/code/external-formats/enc-basic.lisp | 13 +++++----
 2 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/src/code/arm64-simd.lisp b/src/code/arm64-simd.lisp
index 3df63084f..907bdf50d 100644
--- a/src/code/arm64-simd.lisp
+++ b/src/code/arm64-simd.lisp
@@ -584,6 +584,52 @@
       (setf (sb-impl::buffer-head ibuf) (+ head copied))
       (+ start copied))))
 
+#+sb-unicode
+(defun simd-copy-utf8-sap-to-character-string (sap string length)
+  (declare (optimize speed (safety 0))
+           (system-area-pointer sap)
+           (index length))
+  (let ((n (logand length -16)))
+    (with-pinned-objects-in-registers (string)
+      (inline-vop (((byte-array* sap-reg t) sap)
+                   ((byte-array sap-reg t))
+                   ((32-bit-array sap-reg t) (vector-sap string))
+                   ((end unsigned-reg))
+                   ((n any-reg) n)
+                   ((bytes complex-double-reg))
+                   ((16-bits complex-double-reg))
+                   ((16-bits-2 complex-double-reg))
+                   ((32-bits complex-double-reg t :offset 4))
+                   ((32-bits-2 complex-double-reg t :offset 5))
+                   ((32-bits-3 complex-double-reg t :offset 6))
+                   ((32-bits-4 complex-double-reg t :offset 7)))
+          ()
+        (inst add end byte-array* (lsr n 1))
+        (inst mov byte-array byte-array*)
+        (inst b start)
+
+        LOOP
+        (inst ldr bytes (@ byte-array 16 :post-index))
+
+        (inst ushll 16-bits :8h bytes :8b)
+        (inst ushll 32-bits :4s 16-bits :4h)
+
+        (inst ushll2 16-bits-2 :8h bytes :16b)
+        (inst ushll2 32-bits-2 :4s 16-bits :8h)
+
+        (inst ushll 32-bits-3 :4s 16-bits-2 :4h)
+        (inst ushll2 32-bits-4 :4s 16-bits-2 :8h)
+        (inst st1 (list 32-bits 32-bits-2 32-bits-3 32-bits-4) (@ 32-bit-array 64 :post-index) :4s)
+
+        start
+        (inst cmp byte-array end)
+        (inst b :lt LOOP)
+
+        DONE))
+    (loop for i from n below length
+          do (setf (aref string i)
+                   (code-char (sap-ref-8 sap i))))))
+
 (defun simd-copy-utf8-to-base-string (start end string ibuf)
   (declare (type index start end)
            (optimize speed (safety 0)))
diff --git a/src/code/external-formats/enc-basic.lisp b/src/code/external-formats/enc-basic.lisp
index 929835f7c..221c4f922 100644
--- a/src/code/external-formats/enc-basic.lisp
+++ b/src/code/external-formats/enc-basic.lisp
@@ -664,7 +664,7 @@
       (truly-the index (values (truncate string-offset 4))))))
 
 ;;; No validations
-#+(and sb-unicode 64-bit little-endian)
+#+(and sb-unicode 64-bit little-endian (not arm64))
 (defun sb-vm::simd-copy-utf8-sap-to-character-string (sap string length)
   (declare (index length)
            (simple-character-string string)
@@ -673,6 +673,7 @@
     (let* ((n (logand length (- sb-vm:n-word-bytes)))
            (string-sap (vector-sap string))
            (string-offset 0))
+      (declare (fixnum string-offset))
       (loop for byte-offset below n by sb-vm:n-word-bytes
             do
             (let ((word (sap-ref-word sap byte-offset)))
@@ -692,12 +693,10 @@
                     (dpb (ldb (byte 8 56) word)
                          (byte 8 32)
                          (ldb (byte 8 48) word))))
-            (incf string-offset (* 4 sb-vm:n-word-bytes))
-            finally (let ((string-offset (truncate string-offset 4)))
-                      (loop for i from n below length
-                            do (setf (aref string string-offset)
-                                     (code-char (sap-ref-8 sap i)))
-                            (incf string-offset)))))))
+            (incf string-offset (* 4 sb-vm:n-word-bytes)))
+      (loop for i from n below length
+            do (setf (aref string i)
+                     (code-char (sap-ref-8 sap i)))))))
 
 #+(and sb-unicode 64-bit little-endian)
 (defun sb-vm::simd-copy-utf8-crlf-to-character-string-with-size (start end string ibuf size-buffer)

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL