master: avx2/character-string-to-utf8: don't use a lookup table for sizes

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  4f0383a5287790c7c9ada870420c9b8a3bd3a353 (commit)
      from  a797aedf9d9fbf2662f942e130b309865997d865 (commit)

- Log -----------------------------------------------------------------
commit 4f0383a5287790c7c9ada870420c9b8a3bd3a353
Author: Stas Boukarev <[email protected]>
Date:   Sat Aug 15 22:15:01 2026 +0300

    avx2/character-string-to-utf8: don't use a lookup table for sizes
    
    Use a sequence of gpr instructions.
---
 src/code/x86-64-simd.lisp | 41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/src/code/x86-64-simd.lisp b/src/code/x86-64-simd.lisp
index 82a2b9d4f..28f92caf6 100644
--- a/src/code/x86-64-simd.lisp
+++ b/src/code/x86-64-simd.lisp
@@ -1526,7 +1526,7 @@
                         ((c-ffff complex-double-reg))
                         ((c-d800 complex-double-reg))
 
-                        ((multiplier unsigned-reg))
+                        ((tmp2 unsigned-reg))
 
                         ((ascii-mask int-avx2-reg))
                         ((newlines int-avx2-reg))
@@ -1547,9 +1547,9 @@
              (flet ((make-full-table ()
                       (let* ((table-size 256)
                              (row-size 16)
-                             (total-size (+ (* table-size row-size) table-size))
+                             (total-size (* table-size row-size))
                              (table (make-array total-size :element-type '(unsigned-byte 8)
-                                                           :initial-element 0)))
+                                                           :initial-element #xFF)))
                         (loop for row below table-size
                               for dest-index = 0
                               do (loop
@@ -1558,12 +1558,7 @@
                                    do (loop for b below bytes
                                             for src-index = (+ (* lane 4) (- bytes 1 b))
                                             do (setf (aref table (+ (* row row-size) dest-index)) src-index)
-                                               (incf dest-index)))
-                                 ;; for vpshufb to produce zeros
-                                 (loop for i from dest-index below 16
-                                       do (setf (aref table (+ (* row row-size) i)) #xFF))
-                                 ;; produced bytes
-                                 (setf (aref table (+ (* table-size row-size) row)) dest-index))
+                                               (incf dest-index))))
                         table)))
                (macrolet ((track-newline (bytes)
                             `(progn
@@ -1636,7 +1631,6 @@
                    (inst vmovd temp tmp)
                    (inst vpbroadcastd c-7ff temp)
 
-                   (inst mov multiplier #x0100040010004000)
                    (inst vpsrld increment increment 1) ;; go from 8 to 4
 
                    (inst vpcmpeqd errors errors errors) ;; FF..FF
@@ -1666,17 +1660,25 @@
                      (inst vpabsd temp temp)
 
                      ;; Create a tag mask from lengths
-                     (inst vpermd temp2 temp (register-inline-constant :oword #xF0808080F0E08080F080C080F0808000))
 
                      ;; Build an 8-bit index mask
                      ;; Narrow to 16 bits, making a 64-bit mask
-                     (inst vpackusdw temp temp temp)
-                     (inst vmovq tmp temp)
+                     (inst vpackusdw temp2 temp temp)
+                     (inst vmovq tmp temp2)
+
+                     ;; Create a tag mask from lengths
+                     (inst vpermd temp2 temp (register-inline-constant :oword #xF0808080F0E08080F080C080F0808000))
+
+                     ;; Sum utf8 lengths, step 1
+                     ;; step 2 is computed later, when tmp becomes free.
+                     (inst mov tmp2 tmp)
+                     (inst shr tmp2 32)
+                     (inst add :dword tmp2 tmp)
 
                      ;; Multiplying by 1 + 2^6 + 2^12 + 2^18
                      ;; shifts two bits per byte into the upper byte
-                     (inst imul tmp multiplier) ; #x0100040010004000
-                     (inst shr tmp (- 56 4)) ;; shift left 5 for the table entry size
+                     (inst imul tmp (constantize #x0100040010004000))
+                     (inst shr tmp (- 56 4)) ;; shift left 4 for the table entry size
 
                      ;; Spread the character to all 4 bytes
                      ;; For the first byte, the mask depends on if it's a single byte or a continuation byte
@@ -1703,12 +1705,15 @@
                      ;; Shuffle the bytes into place
                      (inst vpshufb bytes bytes (ea full-table tmp))
 
-                     (inst shr :dword tmp 4)
-                     (inst mov :byte tmp (ea 4096 full-table tmp)) ;; number of produced bytes
+                     ;; Sum the remaining part of the utf8 lengths
+                     (inst mov :dword tmp tmp2)
+                     (inst shr :dword tmp 16)
+                     (inst add :dword tmp2 tmp)
+                     (inst and :dword tmp2 #xF)
 
                      (inst vmovdqu (ea byte-array) bytes)
 
-                     (inst add byte-array tmp)
+                     (inst lea byte-array (ea 4 byte-array tmp2))
                      (inst add string 16)
 
                      (inst cmp byte-array byte-end)

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


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.