master: arm64, character-string-to-utf8: faster newline tracking

stassats via Sbcl-commits <[email protected]>
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  60b3a47cbff8a96de1f7b36ca39e480cd23d5a52 (commit)
      from  2e5049cd81cd2bad7f3779be0a196c0860a1f846 (commit)

- Log -----------------------------------------------------------------
commit 60b3a47cbff8a96de1f7b36ca39e480cd23d5a52
Author: Stas Boukarev <[email protected]>
Date:   Sat Aug 8 07:53:10 2026 +0300

    arm64, character-string-to-utf8: faster newline tracking
---
 src/code/arm64-simd.lisp | 65 +++++++++++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 26 deletions(-)

diff --git a/src/code/arm64-simd.lisp b/src/code/arm64-simd.lisp
index 688608761..681e128bd 100644
--- a/src/code/arm64-simd.lisp
+++ b/src/code/arm64-simd.lisp
@@ -1421,13 +1421,17 @@
                        ((string sap-reg t))
 
                        ((newlines complex-double-reg))
-                       ((bytes complex-double-reg))
-                       ((bytes2 complex-double-reg))
-                       ((bytes3 complex-double-reg))
-                       ((bytes4 complex-double-reg))
+                       ((f1 complex-double-reg t :offset 1))
+                       ((f2 complex-double-reg t :offset 2))
+                       ((f3 complex-double-reg t :offset 3))
+                       ((bytes complex-double-reg t :offset 4))
+                       ((bytes2 complex-double-reg t :offset 5))
+                       ((bytes3 complex-double-reg t :offset 6))
+                       ((bytes4 complex-double-reg t :offset 7))
                        ((temp complex-double-reg))
                        ((temp2 complex-double-reg))
                        ((indexes))
+                       ((byte-indexes))
                        ((increment))
                        ((last-newlines))
 
@@ -1436,15 +1440,13 @@
                        ((full-table any-reg t))
                        ((shift-mask complex-double-reg))
                        ((c-1b complex-double-reg))
-                       ((f1 complex-double-reg t :offset 1))
-                       ((f2 complex-double-reg t :offset 2))
-                       ((f3 complex-double-reg t :offset 3))
+
                        ((r4 complex-double-reg t))
-                       ((length1 complex-double-reg t :offset 10))
-                       ((length2 complex-double-reg t :offset 11))
-                       ((shuf-mask complex-double-reg t :offset 6))
-                       ((and-mask complex-double-reg t :offset 7))
-                       ((orr-mask complex-double-reg t :offset 8)))
+                       ((length1 complex-double-reg t :offset 8))
+                       ((length2 complex-double-reg t :offset 9))
+                       ((shuf-mask complex-double-reg t :offset 10))
+                       ((and-mask complex-double-reg t :offset 11))
+                       ((orr-mask complex-double-reg t :offset 12)))
               ((read unsigned-reg positive-fixnum :from :load)
                (written unsigned-reg positive-fixnum :from :load)
                (last-newline signed-reg signed-num))
@@ -1487,17 +1489,14 @@
                                                   (setf (aref table (+ (* row row-size) 16 dest-index)) and-mask) ;; and
                                                   (setf (aref table (+ (* row row-size) 32 dest-index)) orr-mask) ;; orr
                                                   (incf dest-index))))
-                       table))
-                   (find-newlines (bytes)
-                     (inst cmeq temp bytes newlines :4s)
-                     (inst bit last-newlines indexes temp :16b)
-                     (inst add indexes indexes increment :4s)))
+                       table)))
              (assemble ()
 
-               (inst movi newlines 10 :4s)
-               (inst movi increment 4 :4s)
+               (inst movi newlines 10 :16b)
+               (inst movi increment 16 :4s)
                (inst mvni last-newlines 0 :4s)
                (load-inline-constant indexes :oword (concat-ub 32 '(3 2 1 0)))
+               (load-inline-constant byte-indexes :oword (concat-ub 8 '(15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)))
 
                (inst add byte-end byte-array* (asr byte-end 1))
                (inst add byte-array byte-array* (lsr byte-start 1))
@@ -1515,14 +1514,24 @@
                (inst orr temp temp temp2 :16b)
                (check-ascii temp temp FULL-START 4)
 
-               (mapc #'find-newlines (list bytes bytes2 bytes3 bytes4))
-
-               (inst add string string 64)
-
                (inst uzp1 bytes2 bytes bytes2 :8h)
                (inst uzp1 bytes4 bytes3 bytes4 :8h)
                (inst uzp1 bytes4 bytes2 bytes4 :16b)
                (inst str  bytes4 (@ byte-array 16 :post-index))
+
+               (inst cmeq temp bytes4 newlines :16b)
+               ;; if anything found set the first S to #xFFFFFFFF
+               (inst umaxv f1 temp :16b)
+               (inst cmgt f1 f1 0 :2s)
+               (inst and temp temp byte-indexes :16b)
+               (inst umaxv temp temp :16b)
+               (inst add temp2 temp indexes :4s)
+               (inst bit last-newlines temp2 f1 :16b)
+
+               (inst add indexes indexes increment :4s)
+
+               (inst add string string 64)
+
                start
                (inst cmp byte-array byte-end)
                (inst b :hi DONE)
@@ -1531,6 +1540,9 @@
                (inst b ASCII-LOOP)
 
                FULL-START
+               (inst add string-end string-end 48) ;; now it reads 16 bytes instead of 64
+               (inst movi newlines 10 :4s)
+               (inst movi increment 4 :4s)
                (load-inline-constant shift-mask :oword #x6000000040000000200000000)
                (load-inline-constant full-table (make-full-table))
                (inst movi c-1b  #x1b :4s)
@@ -1546,7 +1558,9 @@
                  (inst umov tmp temp 0 :b)
                  (inst cbnz tmp DONE)
 
-                 (mapc #'find-newlines (list bytes))
+                 (inst cmeq temp bytes newlines :4s)
+                 (inst bit last-newlines indexes temp :16b)
+                 (inst add indexes indexes increment :4s)
 
                  ;; Remove the low bits for each of the possible 4 resulting bytes
                  (inst ushr f1 bytes 18 :4s)
@@ -1578,9 +1592,8 @@
                  (inst and bytes bytes and-mask :16b)
                  (inst orr bytes bytes orr-mask :16b)
 
-                 (inst str bytes (@ byte-array))
+                 (inst str bytes (@ byte-array 4 :post-index))
 
-                 (inst add byte-array byte-array 4)
                  (inst add byte-array byte-array tmp-tn)
                  (inst add string string 16))
 

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


hooks/post-receive
-- 
SBCL
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.