master: avx2/character-string-to-utf8: reduce a LUT by 4KB
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 6efe9cda26a8f41468198df68da3ae4c11d89a89 (commit)
from 977441e82786a2fb868fa926c343d087a0ace5a0 (commit)
- Log -----------------------------------------------------------------
commit 6efe9cda26a8f41468198df68da3ae4c11d89a89
Author: Stas Boukarev <[email protected]>
Date: Sat Aug 15 07:32:59 2026 +0300
avx2/character-string-to-utf8: reduce a LUT by 4KB
A tag mask can be computed in one instruction from character lengths.
---
src/code/x86-64-simd.lisp | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/src/code/x86-64-simd.lisp b/src/code/x86-64-simd.lisp
index fc1801b0b..82a2b9d4f 100644
--- a/src/code/x86-64-simd.lisp
+++ b/src/code/x86-64-simd.lisp
@@ -1538,6 +1538,7 @@
((last-newlines))
((t2 complex-double-reg))
((t3 complex-double-reg))
+ ((temp2))
((errors))
((:label error)))
((string any-reg positive-fixnum :from :load)
@@ -1545,7 +1546,7 @@
(last-newline signed-reg signed-num))
(flet ((make-full-table ()
(let* ((table-size 256)
- (row-size 32)
+ (row-size 16)
(total-size (+ (* table-size row-size) table-size))
(table (make-array total-size :element-type '(unsigned-byte 8)
:initial-element 0)))
@@ -1556,13 +1557,7 @@
for bytes = (1+ (ldb (byte 2 (* lane 2)) row))
do (loop for b below bytes
for src-index = (+ (* lane 4) (- bytes 1 b))
- for lead-p = (= b 0)
- for orr-mask = (if lead-p
- (case bytes
- (1 #x00) (2 #xC0) (3 #xE0) (4 #xF0))
- #x80)
do (setf (aref table (+ (* row row-size) dest-index)) src-index)
- (setf (aref table (+ (* row row-size) 16 dest-index)) orr-mask)
(incf dest-index)))
;; for vpshufb to produce zeros
(loop for i from dest-index below 16
@@ -1670,6 +1665,9 @@
;; Negate
(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)
@@ -1678,7 +1676,7 @@
;; 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 5)) ;; shift left 5 for the table entry size
+ (inst shr tmp (- 56 4)) ;; shift left 5 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
@@ -1700,12 +1698,13 @@
(inst vpor bytes temp t1)
(inst vpor bytes bytes t2)
+ (inst vpor bytes bytes temp2)
+
;; Shuffle the bytes into place
- (inst vpshufb bytes bytes (ea 0 full-table tmp))
+ (inst vpshufb bytes bytes (ea full-table tmp))
- (inst vpor bytes bytes (ea 16 full-table tmp))
- (inst shr :dword tmp 5)
- (inst mov :byte tmp (ea 8192 full-table tmp)) ;; number of produced bytes
+ (inst shr :dword tmp 4)
+ (inst mov :byte tmp (ea 4096 full-table tmp)) ;; number of produced bytes
(inst vmovdqu (ea byte-array) bytes)
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL