master: arm64: try sign-extending when encoding constants for logand

stassats via Sbcl-commits <[email protected]> Tue, 28 Jul 2026 08:39:42 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  fee81d44837e36a86c4851deacefcb75b1798d35 (commit)
      from  ac74dc12c4edf21205cf38ea09454931c062e694 (commit)

- Log -----------------------------------------------------------------
commit fee81d44837e36a86c4851deacefcb75b1798d35
Author: Stas Boukarev <[email protected]>
Date:   Tue Jul 28 09:27:33 2026 +0300

    arm64: try sign-extending when encoding constants for logand
---
 src/compiler/arm64/arith.lisp | 82 +++++++++++++++++++++++++++++--------------
 1 file changed, 55 insertions(+), 27 deletions(-)

diff --git a/src/compiler/arm64/arith.lisp b/src/compiler/arm64/arith.lisp
index 997e2600c..589f87b71 100644
--- a/src/compiler/arm64/arith.lisp
+++ b/src/compiler/arm64/arith.lisp
@@ -244,22 +244,38 @@
       (let* ((y-untagged y)
              (y (fixnumize y))
              (imm
-               (cond ((encode-logical-immediate y) y)
-                     ((let ((tagged (logior y fixnum-tag-mask)))
-                        (and (encode-logical-immediate tagged) tagged)))
-                     ((and (typep y '(unsigned-byte 32)) (encode-logical-immediate y 32)) (setf r (32-bit-reg r)) y)
-                     ((and (typep y '(unsigned-byte 32))
-                           (let ((tagged (logior y fixnum-tag-mask)))
-                             (when (encode-logical-immediate tagged 32) (setf r (32-bit-reg r)) tagged))))
-                     ((load-immediate-word tmp-tn y t t))
-                     ;; Use BIC if the inverted constant can be loaded with one instruction
-                     ((let* ((width (or (sb-c::unsigned-type-width (tn-ref-type x-ref))
-                                        n-fixnum-bits))
-                             (inverted (ash (ldb (byte width 0) (lognot y-untagged)) n-fixnum-tag-bits)))
-                        (when (load-immediate-word tmp-tn inverted t t)
-                          (inst bic r x tmp-tn)
-                          (return))))
-                     ((load-immediate-word tmp-tn y nil t)))))
+               (flet ((try-imm (y)
+                        (cond ((encode-logical-immediate y) y)
+                              ((let ((tagged (logior y fixnum-tag-mask)))
+                                 (and (encode-logical-immediate tagged) tagged)))
+                              ((and (typep y '(unsigned-byte 32))
+                                    (encode-logical-immediate y 32))
+                               (setf r (32-bit-reg r))
+                               y)
+                              ((and (typep y '(unsigned-byte 32))
+                                    (let ((tagged (logior y fixnum-tag-mask)))
+                                      (when (encode-logical-immediate tagged 32)
+                                        (setf r (32-bit-reg r))
+                                        tagged)))))))
+                 (cond ((try-imm y))
+                       ((let ((width (sb-c::unsigned-type-width (tn-ref-type x-ref))))
+                          (or (and width
+                                   (incf width n-fixnum-tag-bits)
+                                   ;; Try putting 1 where X already has 0
+                                   (let ((extended (dpb -1 (byte (- 64 width) width) y)))
+                                     (or (try-imm extended)
+                                         (and (< width 32)
+                                              (try-imm (dpb -1 (byte (- 32 width) width) y))))))
+                              (load-immediate-word tmp-tn y t t)
+                              ;; Use BIC if the inverted constant can be loaded with one instruction
+                              (let ((inverted (ash (ldb (byte (or width
+                                                                  n-fixnum-bits) 0)
+                                                        (lognot y-untagged))
+                                                   n-fixnum-tag-bits)))
+                                (when (load-immediate-word tmp-tn inverted t t)
+                                  (inst bic r x tmp-tn)
+                                  (return))))))
+                       ((load-immediate-word tmp-tn y nil t))))))
         (inst and r x imm)))))
 
 (define-vop (fast-logand-c/signed=>signed fast-signed-binop-c)
@@ -269,17 +285,29 @@
   (:generator 2
     (block nil
       (let* ((imm
-               (cond ((encode-logical-immediate y) y)
-                     ((and (typep y '(unsigned-byte 32)) (encode-logical-immediate y 32)) (setf r (32-bit-reg r)) y)
-                     ((load-immediate-word tmp-tn y t))
-                     ;; Use BIC if the inverted constant can be loaded with one instruction
-                     ((let* ((width (or (sb-c::unsigned-type-width (tn-ref-type x-ref))
-                                        64))
-                             (inverted (ldb (byte width 0) (lognot y))))
-                        (when (load-immediate-word tmp-tn inverted t)
-                          (inst bic r x tmp-tn)
-                          (return))))
-                     ((load-immediate-word tmp-tn y nil)))))
+               (flet ((try-imm (y)
+                        (cond ((encode-logical-immediate y) y)
+                              ((and (typep y '(unsigned-byte 32))
+                                    (encode-logical-immediate y 32))
+                               (setf r (32-bit-reg r))
+                               y))))
+                 (cond ((try-imm y))
+                       ((let ((width (sb-c::unsigned-type-width (tn-ref-type x-ref))))
+                          (or (and width
+                                   ;; Try putting 1 where X already has 0
+                                   (let ((extended (dpb -1 (byte (- 64 width) width) y)))
+                                     (or (try-imm extended)
+                                         (and (<= width 32)
+                                              (try-imm (dpb -1 (byte (- 32 width) width) y))))))
+                              (load-immediate-word tmp-tn y t)
+                              ;; Use BIC if the inverted constant can be loaded with one instruction
+                              (let ((inverted (ldb (byte (or width
+                                                             n-fixnum-bits) 0)
+                                                   (lognot y))))
+                                (when (load-immediate-word tmp-tn inverted t)
+                                  (inst bic r x tmp-tn)
+                                  (return))))))
+                       ((load-immediate-word tmp-tn y))))))
         (inst and r x imm)))))
 
 (define-vop (fast-logand-c/unsigned=>unsigned fast-signed-binop-c)

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


hooks/post-receive
-- 
SBCL