master: Shrink the table in simd-copy-utf8-sap-to-character-string

stassats via Sbcl-commits <[email protected]> Sun, 05 Jul 2026 23:58:04 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  e5edefadf3d33c883d4564c8e4d1ca141ba80ae0 (commit)
      from  9104b7ce06b159064916c9c4bce7a30381099a3b (commit)

- Log -----------------------------------------------------------------
commit e5edefadf3d33c883d4564c8e4d1ca141ba80ae0
Author: Stas Boukarev <[email protected]>
Date:   Mon Jul 6 02:48:46 2026 +0300

    Shrink the table in simd-copy-utf8-sap-to-character-string
    
    From 4KB to 2.6KB by using an inverted index.
---
 src/code/arm64-simd.lisp  | 10 +++++-----
 src/code/x86-64-simd.lisp | 22 ++++++++++------------
 2 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/src/code/arm64-simd.lisp b/src/code/arm64-simd.lisp
index e6ad660d7..f9e863281 100644
--- a/src/code/arm64-simd.lisp
+++ b/src/code/arm64-simd.lisp
@@ -1653,11 +1653,11 @@
            (type (simple-array character (*)) string))
   (let ((byte-index 0)
         (char-index 0)
-        (table (load-time-value (let ((table (make-array (* 256 16) :element-type '(unsigned-byte 8)
-                                                                    :initial-element #xFF)))
-                                  (loop for row below 256
+        (table (load-time-value (let ((table (make-array (* #b10101011 16) :element-type '(unsigned-byte 8)
+                                                                           :initial-element #xFF)))
+                                  (loop for row to #b10101010 ;; highest possible inverted index for compressing 1/2 bytes
                                         do (loop with indexes = (loop for i below 8
-                                                                      when (logbitp i row)
+                                                                      unless (logbitp i row)
                                                                       collect (* i 2)
                                                                       and
                                                                       collect (1+ (* i 2)))
@@ -1720,7 +1720,7 @@
                 ;; suitable for the lookup table
                 (inst ushr sh current 6 :8b)
                 (inst cmeq continuations sh mask-2 :8b)
-                (inst bic starts powers continuations :8b)
+                (inst and starts powers continuations :8b)
                 (inst addv starts starts :8b)
                 (inst addv count continuations :8b)
                 (inst umov tmp starts 0 :b)
diff --git a/src/code/x86-64-simd.lisp b/src/code/x86-64-simd.lisp
index ecb3fc578..d63a87588 100644
--- a/src/code/x86-64-simd.lisp
+++ b/src/code/x86-64-simd.lisp
@@ -2273,11 +2273,11 @@
            (type (simple-array character (*)) string))
   (let ((byte-index 0)
         (char-index 0)
-        (table (load-time-value (let ((table (make-array (* 256 16) :element-type '(unsigned-byte 8)
-                                                                    :initial-element #xFF)))
-                                  (loop for row below 256
+        (table (load-time-value (let ((table (make-array (* #b10101011 16) :element-type '(unsigned-byte 8)
+                                                                           :initial-element #xFF)))
+                                  (loop for row to #b10101010  ;; highest possible inverted index for compressing 1/2 bytes
                                         do (loop with indexes = (loop for i below 8
-                                                                      when (logbitp i row)
+                                                                      unless (logbitp i row)
                                                                       collect (* i 2)
                                                                       and
                                                                       collect (1+ (* i 2)))
@@ -2340,7 +2340,7 @@
 
                 LOOP
                 (inst vmovq current (ea byte-array byte-index))
-                (inst vmovq next (ea 1 byte-array byte-index))
+                (inst vpmovzxbw next (ea 1 byte-array byte-index))
 
                 ;; Check for 3 or 4 bytes
                 (inst vpsubusb temp current mask-df)
@@ -2352,13 +2352,9 @@
                 (inst vpand temp current mask-c0)
                 (inst vpcmpeqb temp temp mask-80)
                 (inst vpmovmskb tmp temp)
-                (inst xor :dword tmp #xFF)
 
                 (inst shl :dword tmp 4)
-                (inst vmovdqu temp (ea table tmp))
-
                 (inst vpmovzxbw packed current)
-                (inst vpmovzxbw next next)
 
                 ;; next is shifted by one,
                 ;; construct a codepoint from two overlapping bytes,
@@ -2372,9 +2368,11 @@
                 (inst vpcmpgtw next packed mask-bf)
                 (inst vpblendvb packed packed combined next)
 
+
                 ;; Remove the gaps left over from using two bytes as one codepoint
-                (inst vpshufb packed packed temp)
+                (inst vpshufb packed packed (ea table tmp))
 
+                (inst xor :dword tmp #xFF0) ;; Count non-continuation bytes
                 (inst popcnt :dword tmp tmp)
 
                 ;; Widen
@@ -2397,8 +2395,8 @@
                 (inst jmp :l DONE)
                 (inst inc byte-index)
 
-                DONE
-                (inst vzeroupper)))))
+                (inst vzeroupper)
+                DONE))))
     (loop while (< byte-index length) do
           (let ((b0 (sap-ref-8 sap byte-index)))
             (cond

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


hooks/post-receive
-- 
SBCL