- `(progn
- (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM")
- fast-fixnum-binop)
- (:translate ,translate)
- (:generator 2
- (move r x)
- (inst ,op r y)))
- (define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum)
- fast-fixnum-binop-c)
- (:translate ,translate)
- (:generator 1
- (move r x)
- (inst ,op r (fixnumize y))))
- (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED")
- fast-signed-binop)
- (:translate ,translate)
- (:generator ,(1+ untagged-penalty)
- (move r x)
- (inst ,op r y)))
- (define-vop (,(symbolicate 'fast- translate '-c/signed=>signed)
- fast-signed-binop-c)
- (:translate ,translate)
- (:generator ,untagged-penalty
- (move r x)
- (inst ,op r y)))
- (define-vop (,(symbolicate "FAST-"
- translate
- "/UNSIGNED=>UNSIGNED")
- fast-unsigned-binop)
- (:translate ,translate)
- (:generator ,(1+ untagged-penalty)
- (move r x)
- (inst ,op r y)))
- (define-vop (,(symbolicate 'fast-
- translate
- '-c/unsigned=>unsigned)
- fast-unsigned-binop-c)
- (:translate ,translate)
- (:generator ,untagged-penalty
- (move r x)
- ,(if (eq translate 'logand)
- ;; for the -C/UNSIGNED=>UNSIGNED VOP, this case
- ;; is optimized away as an identity somewhere
- ;; along the lines. However, this VOP is used in
- ;; -C/SIGNED=>UNSIGNED, below, when the
- ;; higher-level lisp code can't optimize away the
- ;; non-trivial identity.
- `(unless (= y #.(1- (ash 1 n-word-bits)))
- (inst ,op r y))
- `(inst ,op r y)))))))
+ `(progn
+ (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM")
+ fast-fixnum-binop)
+ (:translate ,translate)
+ (:generator 2
+ (move r x)
+ (inst ,op r y)))
+ (define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum)
+ fast-fixnum-binop-c)
+ (:translate ,translate)
+ (:generator 1
+ (move r x)
+ (inst ,op r (fixnumize y))))
+ (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED")
+ fast-signed-binop)
+ (:translate ,translate)
+ (:generator ,(1+ untagged-penalty)
+ (move r x)
+ (inst ,op r y)))
+ (define-vop (,(symbolicate 'fast- translate '-c/signed=>signed)
+ fast-signed-binop-c)
+ (:translate ,translate)
+ (:generator ,untagged-penalty
+ (move r x)
+ (inst ,op r y)))
+ (define-vop (,(symbolicate "FAST-"
+ translate
+ "/UNSIGNED=>UNSIGNED")
+ fast-unsigned-binop)
+ (:translate ,translate)
+ (:generator ,(1+ untagged-penalty)
+ (move r x)
+ (inst ,op r y)))
+ (define-vop (,(symbolicate 'fast-
+ translate
+ '-c/unsigned=>unsigned)
+ fast-unsigned-binop-c)
+ (:translate ,translate)
+ (:generator ,untagged-penalty
+ (move r x)
+ ,(if (eq translate 'logand)
+ ;; for the -C/UNSIGNED=>UNSIGNED VOP, this case
+ ;; is optimized away as an identity somewhere
+ ;; along the lines. However, this VOP is used in
+ ;; -C/SIGNED=>UNSIGNED, below, when the
+ ;; higher-level lisp code can't optimize away the
+ ;; non-trivial identity.
+ `(unless (= y #.(1- (ash 1 n-word-bits)))
+ (inst ,op r y))
+ `(inst ,op r y)))))))
- (inst lea result (make-ea :dword :index number :scale 2)))
- ((and (= amount 2) (not (location= number result)))
- (inst lea result (make-ea :dword :index number :scale 4)))
- ((and (= amount 3) (not (location= number result)))
- (inst lea result (make-ea :dword :index number :scale 8)))
- (t
- (move result number)
- (cond ((plusp amount)
- ;; We don't have to worry about overflow because of the
- ;; result type restriction.
- (inst shl result amount))
- (t
- ;; If the amount is greater than 31, only shift by 31. We
- ;; have to do this because the shift instructions only look
- ;; at the low five bits of the result.
- (inst sar result (min 31 (- amount)))
- ;; Fixnum correction.
- (inst and result #xfffffffc)))))))
+ (inst lea result (make-ea :dword :base number :index number)))
+ ((and (= amount 2) (not (location= number result)))
+ (inst lea result (make-ea :dword :index number :scale 4)))
+ ((and (= amount 3) (not (location= number result)))
+ (inst lea result (make-ea :dword :index number :scale 8)))
+ (t
+ (move result number)
+ (cond ((< -32 amount 32)
+ ;; this code is used both in ASH and ASH-SMOD30, so
+ ;; be careful
+ (if (plusp amount)
+ (inst shl result amount)
+ (progn
+ (inst sar result (- amount))
+ (inst and result (lognot fixnum-tag-mask)))))
+ ((plusp amount)
+ (if (sc-is result any-reg)
+ (inst xor result result)
+ (inst mov result 0)))
+ (t (inst sar result 31)
+ (inst and result (lognot fixnum-tag-mask))))))))
- (inst lea result (make-ea :dword :index number :scale 2)))
- ((and (= amount 2) (not (location= number result)))
- (inst lea result (make-ea :dword :index number :scale 4)))
- ((and (= amount 3) (not (location= number result)))
- (inst lea result (make-ea :dword :index number :scale 8)))
- (t
- (move result number)
- (cond ((plusp amount) (inst shl result amount))
- (t (inst sar result (min 31 (- amount)))))))))
+ (inst lea result (make-ea :dword :base number :index number)))
+ ((and (= amount 2) (not (location= number result)))
+ (inst lea result (make-ea :dword :index number :scale 4)))
+ ((and (= amount 3) (not (location= number result)))
+ (inst lea result (make-ea :dword :index number :scale 8)))
+ (t
+ (move result number)
+ (cond ((plusp amount) (inst shl result amount))
+ (t (inst sar result (min 31 (- amount)))))))))
- (inst lea result (make-ea :dword :index number :scale 2)))
- ((and (= amount 2) (not (location= number result)))
- (inst lea result (make-ea :dword :index number :scale 4)))
- ((and (= amount 3) (not (location= number result)))
- (inst lea result (make-ea :dword :index number :scale 8)))
- (t
- (move result number)
- (cond ((< -32 amount 32)
+ (inst lea result (make-ea :dword :base number :index number)))
+ ((and (= amount 2) (not (location= number result)))
+ (inst lea result (make-ea :dword :index number :scale 4)))
+ ((and (= amount 3) (not (location= number result)))
+ (inst lea result (make-ea :dword :index number :scale 8)))
+ (t
+ (move result number)
+ (cond ((< -32 amount 32)
- (numeric-type-p index-type))
- (let ((base-lo (numeric-type-low base-type))
- (base-hi (numeric-type-high base-type))
- (index-lo (numeric-type-low index-type))
- (index-hi (numeric-type-high index-type)))
- (make-numeric-type :class 'integer
- :complexp :real
- :low (when (and base-lo index-lo)
- (+ base-lo (* index-lo scale) disp))
- :high (when (and base-hi index-hi)
- (+ base-hi (* index-hi scale) disp))))))))
+ (numeric-type-p index-type))
+ (let ((base-lo (numeric-type-low base-type))
+ (base-hi (numeric-type-high base-type))
+ (index-lo (numeric-type-low index-type))
+ (index-hi (numeric-type-high index-type)))
+ (make-numeric-type :class 'integer
+ :complexp :real
+ :low (when (and base-lo index-lo)
+ (+ base-lo (* index-lo scale) disp))
+ :high (when (and base-hi index-hi)
+ (+ base-hi (* index-hi scale) disp))))))))
- (:temporary (:sc unsigned-reg :from (:argument 0)) temp)
- (:generator 30
+ (:temporary (:sc unsigned-reg) temp)
+ (:generator 14
+ ;; See the comments below for how the algorithm works. The tricks
+ ;; used can be found for example in AMD's software optimization
+ ;; guide or at "http://www.hackersdelight.org/HDcode/pop.cc" in the
+ ;; function "pop1".
+ ;; Calculate 2-bit sums. Note that the value of a two-digit binary
+ ;; number is the sum of the right digit and twice the left digit.
+ ;; Thus we can calculate the sum of the two digits by shifting the
+ ;; left digit to the right position and doing a two-bit subtraction.
+ ;; This subtraction will never create a borrow and thus can be made
+ ;; on all 16 2-digit numbers at once.
+(macrolet ((define-logtest-vops ()
+ `(progn
+ ,@(loop for suffix in '(/fixnum -c/fixnum
+ /signed -c/signed
+ /unsigned -c/unsigned)
+ for cost in '(4 3 6 5 6 5)
+ collect
+ `(define-vop (,(symbolicate "FAST-LOGTEST" suffix)
+ ,(symbolicate "FAST-CONDITIONAL" suffix))
+ (:translate logtest)
+ (:generator ,cost
+ (emit-optimized-test-inst x
+ ,(if (eq suffix '-c/fixnum)
+ '(fixnumize y)
+ 'y))
+ (inst jmp (if not-p :e :ne) target)))))))
+ (define-logtest-vops))
+
+(defknown %logbitp (integer unsigned-byte) boolean
+ (movable foldable flushable always-translatable))
+
+;;; only for constant folding within the compiler
+(defun %logbitp (integer index)
+ (logbitp index integer))
+
+;;; too much work to do the non-constant case (maybe?)
+(define-vop (fast-logbitp-c/fixnum fast-conditional-c/fixnum)
+ (:translate %logbitp)
+ (:arg-types tagged-num (:constant (integer 0 29)))
+ (:generator 4
+ (inst bt x (+ y n-fixnum-tag-bits))
+ (inst jmp (if not-p :nc :c) target)))
+
+(define-vop (fast-logbitp/signed fast-conditional/signed)
+ (:args (x :scs (signed-reg signed-stack))
+ (y :scs (signed-reg)))
+ (:translate %logbitp)
+ (:generator 6
+ (inst bt x y)
+ (inst jmp (if not-p :nc :c) target)))
+
+(define-vop (fast-logbitp-c/signed fast-conditional-c/signed)
+ (:translate %logbitp)
+ (:arg-types signed-num (:constant (integer 0 31)))
+ (:generator 5
+ (inst bt x y)
+ (inst jmp (if not-p :nc :c) target)))
+
+(define-vop (fast-logbitp/unsigned fast-conditional/unsigned)
+ (:args (x :scs (unsigned-reg unsigned-stack))
+ (y :scs (unsigned-reg)))
+ (:translate %logbitp)
+ (:generator 6
+ (inst bt x y)
+ (inst jmp (if not-p :nc :c) target)))
+
+(define-vop (fast-logbitp-c/unsigned fast-conditional-c/unsigned)
+ (:translate %logbitp)
+ (:arg-types unsigned-num (:constant (integer 0 31)))
+ (:generator 5
+ (inst bt x y)
+ (inst jmp (if not-p :nc :c) target)))
- `(progn
- ,@(mapcar
- (lambda (suffix cost signed)
- `(define-vop (;; FIXME: These could be done more
- ;; cleanly with SYMBOLICATE.
- ,(intern (format nil "~:@(FAST-IF-~A~A~)"
- tran suffix))
- ,(intern
- (format nil "~:@(FAST-CONDITIONAL~A~)"
- suffix)))
- (:translate ,tran)
- (:generator ,cost
- (inst cmp x
- ,(if (eq suffix '-c/fixnum)
- '(fixnumize y)
- 'y))
- (inst jmp (if not-p
- ,(if signed
- not-cond
- not-unsigned)
- ,(if signed
- cond
- unsigned))
- target))))
- '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
- '(4 3 6 5 6 5)
- '(t t t t nil nil)))))
+ `(progn
+ ,@(mapcar
+ (lambda (suffix cost signed)
+ `(define-vop (;; FIXME: These could be done more
+ ;; cleanly with SYMBOLICATE.
+ ,(intern (format nil "~:@(FAST-IF-~A~A~)"
+ tran suffix))
+ ,(intern
+ (format nil "~:@(FAST-CONDITIONAL~A~)"
+ suffix)))
+ (:translate ,tran)
+ (:generator ,cost
+ (inst cmp x
+ ,(if (eq suffix '-c/fixnum)
+ '(fixnumize y)
+ 'y))
+ (inst jmp (if not-p
+ ,(if signed
+ not-cond
+ not-unsigned)
+ ,(if signed
+ cond
+ unsigned))
+ target))))
+ '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
+ '(4 3 6 5 6 5)
+ '(t t t t nil nil)))))
(define-mod-binop (,vop32u ,vopu) ,fun32)
(define-vop (,vop32f ,vopf) (:translate ,fun32))
(define-vop (,svop30f ,vopf) (:translate ,sfun30))
(define-mod-binop (,vop32u ,vopu) ,fun32)
(define-vop (,vop32f ,vopf) (:translate ,fun32))
(define-vop (,svop30f ,vopf) (:translate ,sfun30))
-(define-modular-fun logxor-mod32 (x y) logxor :unsigned 32)
-(define-mod-binop (fast-logxor-mod32/word=>unsigned
- fast-logxor/unsigned=>unsigned)
- logxor-mod32)
-(define-mod-binop-c (fast-logxor-mod32-c/word=>unsigned
- fast-logxor-c/unsigned=>unsigned)
- logxor-mod32)
-(define-vop (fast-logxor-mod32/fixnum=>fixnum
- fast-logxor/fixnum=>fixnum)
- (:translate logxor-mod32))
-(define-vop (fast-logxor-mod32-c/fixnum=>fixnum
- fast-logxor-c/fixnum=>fixnum)
- (:translate logxor-mod32))
-