X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fppc%2Farith.lisp;h=c633a1332170292d282e3f0c09c0f56856e64417;hb=d319b944d934f3efbb01a2a345c46bafd40857d0;hp=8141ec4076203778c6737320366ef7dadd388fbb;hpb=ace140856e6b3f92bb06597092a59753f1e59142;p=sbcl.git diff --git a/src/compiler/ppc/arith.lisp b/src/compiler/ppc/arith.lisp index 8141ec4..c633a13 100644 --- a/src/compiler/ppc/arith.lisp +++ b/src/compiler/ppc/arith.lisp @@ -58,7 +58,7 @@ (define-vop (fast-fixnum-binop fast-safe-arith-op) (:args (x :target r :scs (any-reg zero)) - (y :target r :scs (any-reg zero))) + (y :target r :scs (any-reg zero))) (:arg-types tagged-num tagged-num) (:results (r :scs (any-reg))) (:result-types tagged-num) @@ -66,7 +66,7 @@ (define-vop (fast-unsigned-binop fast-safe-arith-op) (:args (x :target r :scs (unsigned-reg zero)) - (y :target r :scs (unsigned-reg zero))) + (y :target r :scs (unsigned-reg zero))) (:arg-types unsigned-num unsigned-num) (:results (r :scs (unsigned-reg))) (:result-types unsigned-num) @@ -74,7 +74,7 @@ (define-vop (fast-signed-binop fast-safe-arith-op) (:args (x :target r :scs (signed-reg zero)) - (y :target r :scs (signed-reg zero))) + (y :target r :scs (signed-reg zero))) (:arg-types signed-num signed-num) (:results (r :scs (signed-reg))) (:result-types signed-num) @@ -84,7 +84,16 @@ (:args (x :target r :scs (any-reg zero))) (:info y) (:arg-types tagged-num - (:constant (and (signed-byte 14) (not (integer 0 0))))) + (:constant (and (signed-byte 14) (not (integer 0 0))))) + (:results (r :scs (any-reg))) + (:result-types tagged-num) + (:note "inline fixnum arithmetic")) + +(define-vop (fast-fixnum-binop30-c fast-safe-arith-op) + (:args (x :target r :scs (any-reg zero))) + (:info y) + (:arg-types tagged-num + (:constant (and (signed-byte 30) (not (integer 0 0))))) (:results (r :scs (any-reg))) (:result-types tagged-num) (:note "inline fixnum arithmetic")) @@ -93,7 +102,16 @@ (:args (x :target r :scs (any-reg zero))) (:info y) (:arg-types tagged-num - (:constant (and (unsigned-byte 14) (not (integer 0 0))))) + (:constant (and (unsigned-byte 14) (not (integer 0 0))))) + (:results (r :scs (any-reg))) + (:result-types tagged-num) + (:note "inline fixnum logical op")) + +(define-vop (fast-fixnum-logop30-c fast-safe-arith-op) + (:args (x :target r :scs (any-reg zero))) + (:info y) + (:arg-types tagged-num + (:constant (and (unsigned-byte 16) (not (integer 0 0))))) (:results (r :scs (any-reg))) (:result-types tagged-num) (:note "inline fixnum logical op")) @@ -102,25 +120,61 @@ (:args (x :target r :scs (unsigned-reg zero))) (:info y) (:arg-types unsigned-num - (:constant (and (signed-byte 16) (not (integer 0 0))))) + (:constant (and (signed-byte 16) (not (integer 0 0))))) + (:results (r :scs (unsigned-reg))) + (:result-types unsigned-num) + (:note "inline (unsigned-byte 32) arithmetic")) + +(define-vop (fast-unsigned-binop32-c fast-safe-arith-op) + (:args (x :target r :scs (unsigned-reg zero))) + (:info y) + (:arg-types unsigned-num + (:constant (and (unsigned-byte 32) (not (integer 0 0))))) (:results (r :scs (unsigned-reg))) (:result-types unsigned-num) (:note "inline (unsigned-byte 32) arithmetic")) +(define-vop (fast-signed-binop32-c fast-safe-arith-op) + (:args (x :target r :scs (signed-reg zero))) + (:info y) + (:arg-types signed-num + (:constant (and (signed-byte 32) (not (integer 0 0))))) + (:results (r :scs (signed-reg))) + (:result-types signed-num) + (:note "inline (signed-byte 32) arithmetic")) + (define-vop (fast-unsigned-logop-c fast-safe-arith-op) (:args (x :target r :scs (unsigned-reg zero))) (:info y) (:arg-types unsigned-num - (:constant (and (unsigned-byte 16) (not (integer 0 0))))) + (:constant (and (unsigned-byte 16) (not (integer 0 0))))) (:results (r :scs (unsigned-reg))) (:result-types unsigned-num) (:note "inline (unsigned-byte 32) logical op")) +(define-vop (fast-unsigned-logop32-c fast-safe-arith-op) + (:args (x :target r :scs (unsigned-reg zero))) + (:info y) + (:arg-types unsigned-num + (:constant (and (unsigned-byte 32) (not (integer 0 0))))) + (:results (r :scs (unsigned-reg))) + (:result-types unsigned-num) + (:note "inline (unsigned-byte 32) logical op")) + +(define-vop (fast-signed-logop32-c fast-safe-arith-op) + (:args (x :target r :scs (signed-reg zero))) + (:info y) + (:arg-types signed-num + (:constant (and (unsigned-byte 32) (not (integer 0 0))))) + (:results (r :scs (signed-reg))) + (:result-types signed-num) + (:note "inline (signed-byte 32) logical op")) + (define-vop (fast-signed-binop-c fast-safe-arith-op) (:args (x :target r :scs (signed-reg zero))) (:info y) (:arg-types signed-num - (:constant (and (signed-byte 16) (not (integer 0 0))))) + (:constant (and (signed-byte 16) (not (integer 0 0))))) (:results (r :scs (signed-reg))) (:result-types signed-num) (:note "inline (signed-byte 32) arithmetic")) @@ -129,104 +183,245 @@ (:args (x :target r :scs (signed-reg zero))) (:info y) (:arg-types signed-num - (:constant (and (unsigned-byte 16) (not (integer 0 0))))) + (:constant (and (unsigned-byte 16) (not (integer 0 0))))) (:results (r :scs (signed-reg))) (:result-types signed-num) - (:note "inline (signed-byte 32) arithmetic")) - + (:note "inline (signed-byte 32) logical op")) (eval-when (:compile-toplevel :load-toplevel :execute) -(defmacro define-var-binop (translate untagged-penalty op - &optional arg-swap restore-fixnum-mask) +(defmacro !define-var-binop (translate untagged-penalty op + &optional arg-swap restore-fixnum-mask) `(progn (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM") - fast-fixnum-binop) + fast-fixnum-binop) ,@(when restore-fixnum-mask - `((:temporary (:sc non-descriptor-reg) temp))) + `((:temporary (:sc non-descriptor-reg) temp))) (:translate ,translate) (:generator 2 - ,(if arg-swap - `(inst ,op ,(if restore-fixnum-mask 'temp 'r) y x) - `(inst ,op ,(if restore-fixnum-mask 'temp 'r) x y)) - ;; FIXME: remind me what convention we used for 64bitizing - ;; stuff? -- CSR, 2003-08-27 - ,@(when restore-fixnum-mask - `((inst clrrwi r temp (1- n-lowtag-bits)))))) + ,(if arg-swap + `(inst ,op ,(if restore-fixnum-mask 'temp 'r) y x) + `(inst ,op ,(if restore-fixnum-mask 'temp 'r) x y)) + ;; FIXME: remind me what convention we used for 64bitizing + ;; stuff? -- CSR, 2003-08-27 + ,@(when restore-fixnum-mask + `((inst clrrwi r temp (1- n-lowtag-bits)))))) (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED") - fast-signed-binop) + fast-signed-binop) (:translate ,translate) (:generator ,(1+ untagged-penalty) ,(if arg-swap - `(inst ,op r y x) - `(inst ,op r x y)))) + `(inst ,op r y x) + `(inst ,op r x y)))) (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED") - fast-unsigned-binop) + fast-unsigned-binop) (:translate ,translate) (:generator ,(1+ untagged-penalty) - ,(if arg-swap - `(inst ,op r y x) - `(inst ,op r x y)))))) - + ,(if arg-swap + `(inst ,op r y x) + `(inst ,op r x y)))))) -(defmacro define-const-binop (translate untagged-penalty op) +;;; FIXME: the code has really only been checked for adds; we could do +;;; subtracts, too, but my brain is not up to the task of figuring out +;;; signs and borrows. +(defmacro !define-const-binop (translate untagged-penalty op &optional (shifted-op nil)) `(progn - (define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum) - fast-fixnum-binop-c) + ,(if shifted-op + 'fast-fixnum-binop30-c + 'fast-fixnum-binop-c)) (:translate ,translate) + ,@(when shifted-op + `((:temporary (:sc any-reg :target r) temp))) (:generator 1 - (inst ,op r x (fixnumize y)))) + ,(if shifted-op + `(let* ((y (fixnumize y)) + (high-half (ldb (byte 16 16) y)) + (low-half (ldb (byte 16 0) y))) + ;; Compare %LR in insts.lisp. + (cond + ((and (logbitp 15 low-half) (= high-half #xffff)) + ;; Let sign-extension do the work for us, but make sure + ;; to turn LOW-HALF into a signed integer. + (inst ,op r x (dpb low-half (byte 16 0) -1))) + ((and (not (logbitp 15 low-half)) (zerop high-half)) + (inst ,op r x low-half)) + ((zerop low-half) + (inst ,shifted-op r x (if (logbitp 15 high-half) + (dpb high-half (byte 16 0) -1) + high-half))) + (t + ;; Check to see whether compensating for the sign bit + ;; of LOW-HALF is necessary. + (let ((high-half (let ((top (if (logbitp 15 low-half) + (ldb (byte 16 0) + (1+ high-half)) + high-half))) + (if (logbitp 15 top) + (dpb top (byte 16 0) -1) + top)))) + (inst ,shifted-op temp x high-half) + (inst ,op r temp low-half))))) + `(inst ,op r x (fixnumize y))))) (define-vop (,(symbolicate 'fast- translate '-c/signed=>signed) - fast-signed-binop-c) + ,(if shifted-op + 'fast-signed-binop32-c + 'fast-signed-binop-c)) (:translate ,translate) + ,@(when shifted-op + `((:temporary (:sc non-descriptor-reg :target r) temp))) (:generator ,untagged-penalty - (inst ,op r x y))) + ,(if shifted-op + `(let ((high-half (ldb (byte 16 16) y)) + (low-half (ldb (byte 16 0) y))) + ;; Compare %LR in insts.lisp. + (cond + ((and (logbitp 15 low-half) (= high-half #xffff)) + ;; Let sign-extension do the work for us, but make sure + ;; to turn LOW-HALF into a signed integer. + (inst ,op r x (dpb low-half (byte 16 0) -1))) + ((and (not (logbitp 15 low-half)) (zerop high-half)) + (inst ,op r x low-half)) + ((zerop low-half) + (inst ,shifted-op r x (if (logbitp 15 high-half) + (dpb high-half (byte 16 0) -1) + high-half))) + (t + ;; Check to see whether compensating for the sign bit + ;; of LOW-HALF is necessary. + (let ((high-half (let ((top (if (logbitp 15 low-half) + (ldb (byte 16 0) + (1+ high-half)) + high-half))) + (if (logbitp 15 top) + (dpb top (byte 16 0) -1) + top)))) + (inst ,shifted-op temp x high-half) + (inst ,op r temp low-half))))) + `(inst ,op r x y)))) (define-vop (,(symbolicate 'fast- translate '-c/unsigned=>unsigned) - fast-unsigned-binop-c) + ,(if shifted-op + 'fast-unsigned-binop32-c + 'fast-unsigned-binop-c)) (:translate ,translate) + ,@(when shifted-op + `((:temporary (:sc non-descriptor-reg :target r) temp))) (:generator ,untagged-penalty - (inst ,op r x y))))) - -(defmacro define-const-logop (translate untagged-penalty op) + ,(if shifted-op + `(let ((high-half (ldb (byte 16 16) y)) + (low-half (ldb (byte 16 0) y))) + ;; Compare %LR in insts.lisp. + (cond + ((and (logbitp 15 low-half) (= high-half #xffff)) + ;; Let sign-extension do the work for us, but make sure + ;; to turn LOW-HALF into a signed integer. + (inst ,op r x (dpb low-half (byte 16 0) -1))) + ((and (not (logbitp 15 low-half)) (zerop high-half)) + (inst ,op r x low-half)) + ((zerop low-half) + (inst ,shifted-op r x (if (logbitp 15 high-half) + (dpb high-half (byte 16 0) -1) + high-half))) + (t + ;; Check to see whether compensating for the sign bit + ;; of LOW-HALF is necessary. + (let ((high-half (let ((top (if (logbitp 15 low-half) + (ldb (byte 16 0) + (1+ high-half)) + high-half))) + (if (logbitp 15 top) + (dpb top (byte 16 0) -1) + top)))) + (inst ,shifted-op temp x high-half) + (inst ,op r temp low-half))))) + `(inst ,op r x y)))))) + +;;; For logical operations, we don't have to worry about signed bit +;;; propagation from the lower half of a 32-bit operand. +(defmacro !define-const-logop (translate untagged-penalty op &optional (shifted-op nil)) `(progn - (define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum) - fast-fixnum-logop-c) + ,(if shifted-op + 'fast-fixnum-logop30-c + 'fast-fixnum-logop-c)) (:translate ,translate) + ,@(when shifted-op + `((:temporary (:sc any-reg :target r) temp))) (:generator 1 - (inst ,op r x (fixnumize y)))) + ,(if shifted-op + `(let* ((y (fixnumize y)) + (high-half (ldb (byte 16 16) y)) + (low-half (ldb (byte 16 0) y))) + (cond + ((zerop high-half) (inst ,op r x low-half)) + ((zerop low-half) (inst ,shifted-op r x high-half)) + (t + (inst ,shifted-op temp x high-half) + (inst ,op r temp low-half)))) + `(inst ,op r x (fixnumize y))))) (define-vop (,(symbolicate 'fast- translate '-c/signed=>signed) - fast-signed-logop-c) + ,(if shifted-op + 'fast-signed-logop32-c + 'fast-signed-logop-c)) (:translate ,translate) + ,@(when shifted-op + `((:temporary (:sc non-descriptor-reg :target r) temp))) (:generator ,untagged-penalty - (inst ,op r x y))) + ,(if shifted-op + `(let ((high-half (ldb (byte 16 16) y)) + (low-half (ldb (byte 16 0) y))) + (cond + ((zerop high-half) (inst ,op r x low-half)) + ((zerop low-half) (inst ,shifted-op r x high-half)) + (t + (inst ,shifted-op temp x high-half) + (inst ,op r temp low-half)))) + `(inst ,op r x y)))) (define-vop (,(symbolicate 'fast- translate '-c/unsigned=>unsigned) - fast-unsigned-logop-c) + ,(if shifted-op + 'fast-unsigned-logop32-c + 'fast-unsigned-logop-c)) (:translate ,translate) + ,@(when shifted-op + `((:temporary (:sc non-descriptor-reg :target r) temp))) (:generator ,untagged-penalty - (inst ,op r x y))))) + ,(if shifted-op + `(let ((high-half (ldb (byte 16 16) y)) + (low-half (ldb (byte 16 0) y))) + (cond + ((zerop high-half) (inst ,op r x low-half)) + ((zerop low-half) (inst ,shifted-op r x high-half)) + (t + (inst ,shifted-op temp x high-half) + (inst ,op r temp low-half)))) + `(inst ,op r x y)))))) ); eval-when -(define-var-binop + 4 add) -(define-var-binop - 4 sub) -(define-var-binop logand 2 and) -(define-var-binop logandc1 2 andc t) -(define-var-binop logandc2 2 andc) -(define-var-binop logior 2 or) -(define-var-binop logorc1 2 orc t t) -(define-var-binop logorc2 2 orc nil t) -(define-var-binop logxor 2 xor) -(define-var-binop logeqv 2 eqv nil t) -(define-var-binop lognand 2 nand nil t) -(define-var-binop lognor 2 nor nil t) - -(define-const-binop + 4 addi) -(define-const-binop - 4 subi) -(define-const-logop logand 2 andi.) -(define-const-logop logior 2 ori) -(define-const-logop logxor 2 xori) +(!define-var-binop + 4 add) +(!define-var-binop - 4 sub) +(!define-var-binop logand 2 and) +(!define-var-binop logandc1 2 andc t) +(!define-var-binop logandc2 2 andc) +(!define-var-binop logior 2 or) +(!define-var-binop logorc1 2 orc t t) +(!define-var-binop logorc2 2 orc nil t) +(!define-var-binop logxor 2 xor) +(!define-var-binop logeqv 2 eqv nil t) +(!define-var-binop lognand 2 nand nil t) +(!define-var-binop lognor 2 nor nil t) + +(!define-const-binop + 4 addi addis) +(!define-const-binop - 4 subi) +;;; Implementing a 32-bit immediate version of LOGAND wouldn't be any +;;; better than loading the 32-bit constant via LR and then performing +;;; an /AND/. So don't bother. (It would be better in some cases, such +;;; as when one half of the word is zeros--we save a register--but we +;;; would have specified one temporary register in the VOP, so we lose +;;; any possible advantage.) +(!define-const-logop logand 2 andi.) +(!define-const-logop logior 2 ori oris) +(!define-const-logop logxor 2 xori xoris) ;;; Special case fixnum + and - that trap on overflow. Useful when we @@ -243,10 +438,9 @@ (inst addo. r x y) (inst bns no-overflow) (inst unimp (logior (ash (reg-tn-encoding r) 5) - fixnum-additive-overflow-trap)) + fixnum-additive-overflow-trap)) (emit-label no-overflow)))) - (define-vop (-/fixnum fast--/fixnum=>fixnum) (:policy :safe) (:results (r :scs (any-reg descriptor-reg))) @@ -258,7 +452,7 @@ (inst subo. r x y) (inst bns no-overflow) (inst unimp (logior (ash (reg-tn-encoding r) 5) - fixnum-additive-overflow-trap)) + fixnum-additive-overflow-trap)) (emit-label no-overflow)))) (define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop) @@ -270,15 +464,15 @@ (define-vop (fast-*-c/fixnum=>fixnum fast-fixnum-binop-c) (:translate *) - (:arg-types tagged-num - (:constant (and (signed-byte 16) (not (integer 0 0))))) + (:arg-types tagged-num + (:constant (and (signed-byte 16) (not (integer 0 0))))) (:generator 1 (inst mulli r x y))) (define-vop (fast-*-bigc/fixnum=>fixnum fast-fixnum-binop-c) (:translate *) (:arg-types tagged-num - (:constant (and fixnum (not (signed-byte 16))))) + (:constant (and fixnum (not (signed-byte 16))))) (:temporary (:scs (non-descriptor-reg)) temp) (:generator 1 (inst lr temp y) @@ -307,23 +501,23 @@ ;;; Shifting (macrolet ((def (name sc-type type result-type cost) - `(define-vop (,name) - (:note "inline ASH") - (:translate ash) - (:args (number :scs (,sc-type)) - (amount :scs (signed-reg unsigned-reg immediate))) - (:arg-types ,type positive-fixnum) - (:results (result :scs (,result-type))) - (:result-types ,type) - (:policy :fast-safe) - (:generator ,cost - (sc-case amount - ((signed-reg unsigned-reg) - (inst slw result number amount)) - (immediate - (let ((amount (tn-value amount))) - (aver (> amount 0)) - (inst slwi result number amount)))))))) + `(define-vop (,name) + (:note "inline ASH") + (:translate ash) + (:args (number :scs (,sc-type)) + (amount :scs (signed-reg unsigned-reg immediate))) + (:arg-types ,type positive-fixnum) + (:results (result :scs (,result-type))) + (:result-types ,type) + (:policy :fast-safe) + (:generator ,cost + (sc-case amount + ((signed-reg unsigned-reg) + (inst slw result number amount)) + (immediate + (let ((amount (tn-value amount))) + (aver (> amount 0)) + (inst slwi result number amount)))))))) ;; FIXME: There's the opportunity for a sneaky optimization here, I ;; think: a FAST-ASH-LEFT-C/FIXNUM=>SIGNED vop. -- CSR, 2003-09-03 (def fast-ash-left/fixnum=>fixnum any-reg tagged-num any-reg 2) @@ -333,7 +527,7 @@ (define-vop (fast-ash/unsigned=>unsigned) (:note "inline ASH") (:args (number :scs (unsigned-reg) :to :save) - (amount :scs (signed-reg))) + (amount :scs (signed-reg))) (:arg-types (:or unsigned-num) signed-num) (:results (result :scs (unsigned-reg))) (:result-types unsigned-num) @@ -342,7 +536,7 @@ (:temporary (:sc non-descriptor-reg) ndesc) (:generator 5 (let ((positive (gen-label)) - (done (gen-label))) + (done (gen-label))) (inst cmpwi amount 0) (inst neg ndesc amount) (inst bge positive) @@ -351,11 +545,11 @@ (inst ble done) (move result zero-tn) (inst b done) - + (emit-label positive) ;; The result-type assures us that this shift will not overflow. (inst slw result number amount) - + (emit-label done)))) (define-vop (fast-ash-c/unsigned=>unsigned) @@ -378,7 +572,7 @@ (define-vop (fast-ash/signed=>signed) (:note "inline ASH") (:args (number :scs (signed-reg) :to :save) - (amount :scs (signed-reg immediate))) + (amount :scs (signed-reg immediate))) (:arg-types (:or signed-num) signed-num) (:results (result :scs (signed-reg))) (:result-types (:or signed-num)) @@ -389,28 +583,28 @@ (sc-case amount (signed-reg (let ((positive (gen-label)) - (done (gen-label))) - (inst cmpwi amount 0) - (inst neg ndesc amount) - (inst bge positive) - (inst cmpwi ndesc 31) - (inst sraw result number ndesc) - (inst ble done) - (inst srawi result number 31) - (inst b done) - - (emit-label positive) - ;; The result-type assures us that this shift will not overflow. - (inst slw result number amount) - - (emit-label done))) + (done (gen-label))) + (inst cmpwi amount 0) + (inst neg ndesc amount) + (inst bge positive) + (inst cmpwi ndesc 31) + (inst sraw result number ndesc) + (inst ble done) + (inst srawi result number 31) + (inst b done) + + (emit-label positive) + ;; The result-type assures us that this shift will not overflow. + (inst slw result number amount) + + (emit-label done))) (immediate (let ((amount (tn-value amount))) - (if (minusp amount) - (let ((amount (min 31 (- amount)))) - (inst srawi result number amount)) - (inst slwi result number amount))))))) + (if (minusp amount) + (let ((amount (min 31 (- amount)))) + (inst srawi result number amount)) + (inst slwi result number amount))))))) @@ -420,19 +614,29 @@ (:policy :fast-safe) (:args (arg :scs (signed-reg))) (:arg-types signed-num) - (:results (res :scs (any-reg))) - (:result-types positive-fixnum) - (:temporary (:scs (non-descriptor-reg) :to (:argument 0)) shift) + (:results (res :scs (unsigned-reg))) + (:result-types unsigned-num) (:generator 6 ; (integer-length arg) = (- 32 (cntlz (if (>= arg 0) arg (lognot arg)))) (let ((nonneg (gen-label))) - (inst cntlzw. shift arg) + (inst cntlzw. res arg) (inst bne nonneg) - (inst not shift arg) - (inst cntlzw shift shift) + (inst not res arg) + (inst cntlzw res res) (emit-label nonneg) - (inst slwi shift shift 2) - (inst subfic res shift (fixnumize 32))))) + (inst subfic res res 32)))) + +(define-vop (unsigned-byte-32-len) + (:translate integer-length) + (:note "inline (unsigned-byte 32) integer-length") + (:policy :fast-safe) + (:args (arg :scs (unsigned-reg))) + (:arg-types unsigned-num) + (:results (res :scs (unsigned-reg))) + (:result-types unsigned-num) + (:generator 4 + (inst cntlzw res arg) + (inst subfic res res 32))) (define-vop (unsigned-byte-32-count) (:translate logcount) @@ -445,7 +649,7 @@ (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift temp) (:generator 30 (let ((loop (gen-label)) - (done (gen-label))) + (done (gen-label))) (inst add. shift zero-tn arg) (move res zero-tn) (inst beq done) @@ -460,7 +664,7 @@ ;;;; Modular functions: -(define-modular-fun lognot-mod32 (x) lognot 32) +(define-modular-fun lognot-mod32 (x) lognot :unsigned 32) (define-vop (lognot-mod32/unsigned=>unsigned) (:translate lognot-mod32) (:args (x :scs (unsigned-reg))) @@ -472,23 +676,31 @@ (inst not res x))) (define-vop (fast-ash-left-mod32-c/unsigned=>unsigned - fast-ash-c/unsigned=>unsigned) + fast-ash-c/unsigned=>unsigned) (:translate ash-left-mod32)) -(macrolet +(define-vop (fast-ash-left-mod32/unsigned=>unsigned + fast-ash-left/unsigned=>unsigned)) +(deftransform ash-left-mod32 ((integer count) + ((unsigned-byte 32) (unsigned-byte 5))) + (when (sb!c::constant-lvar-p count) + (sb!c::give-up-ir1-transform)) + '(%primitive fast-ash-left-mod32/unsigned=>unsigned integer count)) + +(macrolet ((define-modular-backend (fun &optional constantp) (let ((mfun-name (symbolicate fun '-mod32)) - (modvop (symbolicate 'fast- fun '-mod32/unsigned=>unsigned)) - (modcvop (symbolicate 'fast- fun 'mod32-c/unsigned=>unsigned)) - (vop (symbolicate 'fast- fun '/unsigned=>unsigned)) - (cvop (symbolicate 'fast- fun '-c/unsigned=>unsigned))) - `(progn - (define-modular-fun ,mfun-name (x y) ,fun 32) - (define-vop (,modvop ,vop) - (:translate ,mfun-name)) - ,@(when constantp - `((define-vop (,modcvop ,cvop) - (:translate ,mfun-name)))))))) + (modvop (symbolicate 'fast- fun '-mod32/unsigned=>unsigned)) + (modcvop (symbolicate 'fast- fun 'mod32-c/unsigned=>unsigned)) + (vop (symbolicate 'fast- fun '/unsigned=>unsigned)) + (cvop (symbolicate 'fast- fun '-c/unsigned=>unsigned))) + `(progn + (define-modular-fun ,mfun-name (x y) ,fun :unsigned 32) + (define-vop (,modvop ,vop) + (:translate ,mfun-name)) + ,@(when constantp + `((define-vop (,modcvop ,cvop) + (:translate ,mfun-name)))))))) (define-modular-backend + t) (define-modular-backend - t) (define-modular-backend * t) @@ -512,7 +724,7 @@ (define-vop (fast-conditional/fixnum fast-conditional) (:args (x :scs (any-reg zero)) - (y :scs (any-reg zero))) + (y :scs (any-reg zero))) (:arg-types tagged-num tagged-num) (:note "inline fixnum comparison")) @@ -523,7 +735,7 @@ (define-vop (fast-conditional/signed fast-conditional) (:args (x :scs (signed-reg zero)) - (y :scs (signed-reg zero))) + (y :scs (signed-reg zero))) (:arg-types signed-num signed-num) (:note "inline (signed-byte 32) comparison")) @@ -534,7 +746,7 @@ (define-vop (fast-conditional/unsigned fast-conditional) (:args (x :scs (unsigned-reg zero)) - (y :scs (unsigned-reg zero))) + (y :scs (unsigned-reg zero))) (:arg-types unsigned-num unsigned-num) (:note "inline (unsigned-byte 32) comparison")) @@ -543,7 +755,6 @@ (:arg-types unsigned-num (:constant (unsigned-byte 16))) (:info target not-p y)) - (define-vop (fast-if- (+ adds shifts) 4) - (give-up-ir1-transform))) + ;; a mulli instruction has a latency of 5. + (when (> (+ adds shifts) 4) + (give-up-ir1-transform))) (t - ;; a mullw instruction also has a latency of 5, plus two - ;; instructions (in general) to load the immediate into a - ;; register. - (when (> (+ adds shifts) 6) - (give-up-ir1-transform)))) + ;; a mullw instruction also has a latency of 5, plus two + ;; instructions (in general) to load the immediate into a + ;; register. + (when (> (+ adds shifts) 6) + (give-up-ir1-transform)))) (or result 0))))