master: arm64: more optimizable integer-length
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 2e9abed30d94fd4d6050381fa364b9869c486fa4 (commit)
from 94b68202423cf0d220c0c690a9b9ae8a554985f7 (commit)
- Log -----------------------------------------------------------------
commit 2e9abed30d94fd4d6050381fa364b9869c486fa4
Author: Stas Boukarev <[email protected]>
Date: Sun Aug 30 09:45:14 2026 +0300
arm64: more optimizable integer-length
arm64 has leading sign/zeros instructions, to get integer-length they
need to be subtracted from 63/64.
Doing it in VOPs is opaque, move to a lisp transform and two cls/clz VOPs.
That way (- 63 (integer-length x)) is just one instruction.
---
src/compiler/arm64/arith.lisp | 58 ++++++++++++++++++++++++++-----------------
1 file changed, 35 insertions(+), 23 deletions(-)
diff --git a/src/compiler/arm64/arith.lisp b/src/compiler/arm64/arith.lisp
index 14cf63b85..cfbbbdd36 100644
--- a/src/compiler/arm64/arith.lisp
+++ b/src/compiler/arm64/arith.lisp
@@ -162,9 +162,13 @@
`(progn
(define-vop (,(symbolicate 'fast- translate '/fixnum=>fixnum)
fast-fixnum-binop)
+ (:args (x :scs (any-reg))
+ (y :scs (any-reg signed-reg unsigned-reg)))
(:translate ,translate)
(:generator 2
- (inst ,op r x y)))
+ (inst ,op r x (if (sc-is y any-reg)
+ y
+ (lsl y n-fixnum-tag-bits)))))
(define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum)
fast-fixnum-binop-c)
(:arg-types tagged-num
@@ -989,33 +993,41 @@
(define shift-towards-start lsr)
(define shift-towards-end lsl))
-(define-vop (signed-byte-64-len)
- (:translate integer-length)
- (:note "inline (signed-byte 64) integer-length")
+(defknown (cls clz) (integer)
+ (integer 0 #.sb-vm:n-word-bits)
+ (movable foldable flushable))
+
+(defun clz (integer) (- 64 (integer-length integer)))
+(defun cls (integer) (- 63 (integer-length integer)))
+
+;;; Implement via transforms and cls/clz, so that the addition has a
+;;; chance to get associated with some surrounding arithmetic.
+(deftransform integer-length ((integer) (signed-word) * :node node :priority :last)
+ (sb-c::delay-ir1-transform node :ir1-phases)
+ `(- 63 (cls integer)))
+(deftransform integer-length ((integer) (word) fixnum :node node :priority :last)
+ (sb-c::delay-ir1-transform node :ir1-phases)
+ `(- 64 (clz integer)))
+
+(define-vop ()
+ (:translate cls)
(:policy :fast-safe)
- (:args (arg :scs (signed-reg) :target temp))
- (:arg-types signed-num)
- (:results (res :scs (any-reg)))
+ (:args (arg :scs (unsigned-reg signed-reg)))
+ (:arg-types (:or signed-num unsigned-num))
+ (:results (res :scs (unsigned-reg)))
(:result-types positive-fixnum)
- (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) temp)
- (:generator 5
- (inst cls temp arg)
- (inst mov res (fixnumize 63))
- (inst sub res res (lsl temp n-fixnum-tag-bits))))
+ (:generator 1
+ (inst cls res arg)))
-(define-vop (unsigned-byte-64-len)
- (:translate integer-length)
- (:note "inline (unsigned-byte 64) integer-length")
+(define-vop ()
+ (:translate clz)
(:policy :fast-safe)
- (:args (arg :scs (unsigned-reg) :target temp))
- (:arg-types unsigned-num)
- (:results (res :scs (any-reg)))
+ (:args (arg :scs (unsigned-reg signed-reg)))
+ (:arg-types (:or signed-num unsigned-num))
+ (:results (res :scs (unsigned-reg)))
(:result-types positive-fixnum)
- (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) temp)
- (:generator 5
- (inst clz temp arg)
- (inst mov res (fixnumize 64))
- (inst sub res res (lsl temp n-fixnum-tag-bits))))
+ (:generator 1
+ (inst clz res arg)))
(define-vop ()
(:translate count-trailing-zeros)
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL