master: loongarch: Implement integer-length without a loop
snuglas via Sbcl-commits <[email protected]> Tue, 21 Jul 2026 23:38:25 +0000
| Newsgroups | gmane.lisp.steel-bank.cvs |
|---|---|
| Message-ID | <[email protected]> |
The branch "master" has been updated in SBCL:
via 7c1fd2b82f02521736cc8752b2fd7ea1c12f89f2 (commit)
from 5476c17badff5c9891868899b3b6e1a4af4c3275 (commit)
- Log -----------------------------------------------------------------
commit 7c1fd2b82f02521736cc8752b2fd7ea1c12f89f2
Author: Douglas Katzman <[email protected]>
Date: Tue Jul 21 23:38:10 2026 +0000
loongarch: Implement integer-length without a loop
---
src/compiler/constraint.lisp | 5 ++---
src/compiler/loongarch64/arith.lisp | 30 ++++++++++--------------------
src/compiler/loongarch64/insts.lisp | 7 ++++++-
3 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/src/compiler/constraint.lisp b/src/compiler/constraint.lisp
index 6e04e95bc..6c67fe3d9 100644
--- a/src/compiler/constraint.lisp
+++ b/src/compiler/constraint.lisp
@@ -517,10 +517,9 @@
;; Some backends do not implement either count-leading-zeros or count-trailing-zeros
;; efficiently. For those, iterating over all bits of a simple-bit-vector
;; uses potentially fewer cycles than scanning for just the 1 bits.
- ;; - Loongarch supports these in the base architecture but our vop is deficient
;; - Sparc added LZCNT no earlier than V9, but not on all V9 implementations
;; - Risc-v only implements something if the Zbb extension is supported
- #+(and (not sb-xc-host) (not (or sparc loongarch64 riscv)))
+ #+(and (not sb-xc-host) (not (or sparc riscv)))
;; Aligning to word boundaries is valid because MIN and MAX are merely hints about where
;; nonzero bits exist.
(let ((,minword (floor (conset-min ,conset) sb-vm:n-word-bits))
@@ -546,7 +545,7 @@
(* ,index sb-vm:n-word-bits))))))
,@body)))
finally (return ,result)))
- #-(and (not sb-xc-host) (not (or sparc loongarch64 riscv)))
+ #-(and (not sb-xc-host) (not (or sparc riscv)))
(loop for ,index from (conset-min ,conset) below (conset-max ,conset)
do (when (plusp (sbit ,conset-vector ,index))
(let ((,constraint (aref ,universe ,index)))
diff --git a/src/compiler/loongarch64/arith.lisp b/src/compiler/loongarch64/arith.lisp
index f54e91d59..98ce428f7 100644
--- a/src/compiler/loongarch64/arith.lisp
+++ b/src/compiler/loongarch64/arith.lisp
@@ -335,27 +335,17 @@
(:translate integer-length)
(:note #.(format nil "inline (signed-byte ~a) integer-length" n-machine-word-bits))
(:policy :fast-safe)
- (:args (arg :scs (signed-reg) :target shift))
+ (:args (arg :scs (signed-reg)))
(:arg-types signed-num)
- (:results (res :scs (any-reg)))
- (:result-types positive-fixnum)
- (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
- (:generator 30
- (let ((loop (gen-label))
- (test (gen-label)))
- (move shift arg)
- (move res zero-tn)
- (inst bge shift zero-tn test)
-
- (inst s_xori shift shift -1)
- (inst j test)
-
- (emit-label loop)
- (inst srli.d shift shift 1)
- (inst addi.d res res (fixnumize 1))
-
- (emit-label test)
- (inst bne shift zero-tn loop))))
+ (:results (res :scs (unsigned-reg)))
+ (:result-types unsigned-num)
+ (:temporary (:scs (non-descriptor-reg)) temp)
+ (:generator 5
+ (inst srai.d temp arg 63) ; blast the sign bit across the word
+ (inst xor temp temp arg)
+ (inst clz.d res temp)
+ (inst li temp 64)
+ (inst sub.d res temp res)))
(define-vop (unsigned-byte-64-count)
(:translate logcount)
diff --git a/src/compiler/loongarch64/insts.lisp b/src/compiler/loongarch64/insts.lisp
index 39e9fafce..433097932 100644
--- a/src/compiler/loongarch64/insts.lisp
+++ b/src/compiler/loongarch64/insts.lisp
@@ -584,7 +584,12 @@
(define-la-am-instruction llacq.w #b0011100001010111100000)
(define-la-am-instruction screl.w #b0011100001010111100001)
(define-la-am-instruction llacq.d #b0011100001010111100010)
- (define-la-am-instruction screl.d #b0011100001010111100011))
+ (define-la-am-instruction screl.d #b0011100001010111100011)
+ ;; Piggybacking on the atomic memory ops even though these aren't such.
+ (define-la-am-instruction ctz.w #b0000000000000000000111)
+ (define-la-am-instruction ctz.d #b0000000000000000001011)
+ (define-la-am-instruction clz.w #b0000000000000000000101)
+ (define-la-am-instruction clz.d #b0000000000000000001001))
(define-instruction-macro fstore (&optional format fd rj offset)
`(case ,format
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL