X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fppc%2Farith.lisp;h=28d4acbd6db77763bc8130b7f95ae76a15c06729;hb=cb79d726de3e18c660f84c58a43f00d22b459037;hp=56910ac5b8a67ccaa1ee260dd4081b61522644d6;hpb=0db7f91050aeb2dc2f98946eefa251ffd6b96402;p=sbcl.git diff --git a/src/compiler/ppc/arith.lisp b/src/compiler/ppc/arith.lisp index 56910ac..28d4acb 100644 --- a/src/compiler/ppc/arith.lisp +++ b/src/compiler/ppc/arith.lisp @@ -18,7 +18,6 @@ (:effects) (:affected)) - (define-vop (fixnum-unop fast-safe-arith-op) (:args (x :scs (any-reg))) (:results (res :scs (any-reg))) @@ -52,8 +51,6 @@ (:translate lognot) (:generator 1 (inst not res x))) - - ;;;; Binary fixnum operations. @@ -83,7 +80,6 @@ (:result-types signed-num) (:note "inline (signed-byte 32) arithmetic")) - (define-vop (fast-fixnum-binop-c fast-safe-arith-op) (:args (x :target r :scs (any-reg zero))) (:info y) @@ -141,23 +137,36 @@ (eval-when (:compile-toplevel :load-toplevel :execute) -(defmacro define-var-binop (translate untagged-penalty op) +(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) + ,@(when restore-fixnum-mask + `((:temporary (:sc non-descriptor-reg) temp))) (:translate ,translate) (:generator 2 - (inst ,op r x y))) + ,(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) (:translate ,translate) (:generator ,(1+ untagged-penalty) - (inst ,op r x y))) + ,(if arg-swap + `(inst ,op r y x) + `(inst ,op r x y)))) (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED") fast-unsigned-binop) (:translate ,translate) (:generator ,(1+ untagged-penalty) - (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) @@ -203,11 +212,15 @@ (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 logorc2 2 orc) +(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) +(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) @@ -226,7 +239,7 @@ (:note "safe inline fixnum arithmetic") (:generator 4 (let* ((no-overflow (gen-label))) - (inst mcrxr :cr0) + (inst mtxer zero-tn) (inst addo. r x y) (inst bns no-overflow) (inst unimp (logior (ash (reg-tn-encoding r) 5) @@ -241,53 +254,126 @@ (:note "safe inline fixnum arithmetic") (:generator 4 (let* ((no-overflow (gen-label))) - (inst mcrxr :cr0) + (inst mtxer zero-tn) (inst subo. r x y) (inst bns no-overflow) (inst unimp (logior (ash (reg-tn-encoding r) 5) fixnum-additive-overflow-trap)) (emit-label no-overflow)))) +(define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop) + (:temporary (:scs (non-descriptor-reg)) temp) + (:translate *) + (:generator 2 + (inst srawi temp y 2) + (inst mullw r x temp))) + +(define-vop (fast-*-c/fixnum=>fixnum fast-fixnum-binop-c) + (:translate *) + (: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))))) + (:temporary (:scs (non-descriptor-reg)) temp) + (:generator 1 + (inst lr temp y) + (inst mullw r x temp))) + +(define-vop (fast-*/signed=>signed fast-signed-binop) + (:translate *) + (:generator 4 + (inst mullw r x y))) + +(define-vop (fast-*-c/signed=>signed fast-signed-binop-c) + (:translate *) + (:generator 3 + (inst mulli r x y))) +(define-vop (fast-*/unsigned=>unsigned fast-unsigned-binop) + (:translate *) + (:generator 4 + (inst mullw r x y))) + +(define-vop (fast-*-c/unsigned=>unsigned fast-unsigned-binop-c) + (:translate *) + (:generator 3 + (inst mulli r x y))) + ;;; 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)))))))) + ;; 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) + (def fast-ash-left/signed=>signed signed-reg signed-num signed-reg 3) + (def fast-ash-left/unsigned=>unsigned unsigned-reg unsigned-num unsigned-reg 3)) + (define-vop (fast-ash/unsigned=>unsigned) (:note "inline ASH") (:args (number :scs (unsigned-reg) :to :save) - (amount :scs (signed-reg immediate))) + (amount :scs (signed-reg))) (:arg-types (:or unsigned-num) signed-num) (:results (result :scs (unsigned-reg))) (:result-types unsigned-num) (:translate ash) (:policy :fast-safe) (:temporary (:sc non-descriptor-reg) ndesc) - (:generator 3 - (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 srw result number ndesc) - (inst ble done) - (inst srwi 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 srwi result number amount)) - (inst slwi result number amount))))))) + (:generator 5 + (let ((positive (gen-label)) + (done (gen-label))) + (inst cmpwi amount 0) + (inst neg ndesc amount) + (inst bge positive) + (inst cmpwi ndesc 31) + (inst srw result number ndesc) + (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) + (:note "inline constant ASH") + (:args (number :scs (unsigned-reg))) + (:info amount) + (:arg-types unsigned-num (:constant integer)) + (:results (result :scs (unsigned-reg))) + (:result-types unsigned-num) + (:translate ash) + (:policy :fast-safe) + (:generator 4 + (cond + ((and (minusp amount) (< amount -31)) (move result zero-tn)) + ((minusp amount) (inst srwi result number (- amount))) + ;; possible because this is used in the modular version too + ((> amount 31) (move result zero-tn)) + (t (inst slwi result number amount))))) (define-vop (fast-ash/signed=>signed) (:note "inline ASH") @@ -373,6 +459,56 @@ (emit-label done)))) +;;;; Modular functions: +(define-modular-fun lognot-mod32 (x) lognot :unsigned 32) +(define-vop (lognot-mod32/unsigned=>unsigned) + (:translate lognot-mod32) + (:args (x :scs (unsigned-reg))) + (:arg-types unsigned-num) + (:results (res :scs (unsigned-reg))) + (:result-types unsigned-num) + (:policy :fast-safe) + (:generator 1 + (inst not res x))) + +(define-vop (fast-ash-left-mod32-c/unsigned=>unsigned + fast-ash-c/unsigned=>unsigned) + (:translate ash-left-mod32)) + +(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 :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) + (define-modular-backend logxor t) + (define-modular-backend logeqv) + (define-modular-backend lognand) + (define-modular-backend lognor) + (define-modular-backend logandc1) + (define-modular-backend logandc2) + (define-modular-backend logorc1) + (define-modular-backend logorc2)) + ;;;; Binary conditional VOPs: (define-vop (fast-conditional) @@ -575,65 +711,6 @@ (emit-label done) (move result res)))) - -(define-vop (32bit-logical) - (:args (x :scs (unsigned-reg zero)) - (y :scs (unsigned-reg zero))) - (:arg-types unsigned-num unsigned-num) - (:results (r :scs (unsigned-reg))) - (:result-types unsigned-num) - (:policy :fast-safe)) - -(define-vop (32bit-logical-not 32bit-logical) - (:translate 32bit-logical-not) - (:args (x :scs (unsigned-reg zero))) - (:arg-types unsigned-num) - (:generator 1 - (inst not r x))) - -(define-vop (32bit-logical-and 32bit-logical) - (:translate 32bit-logical-and) - (:generator 1 - (inst and r x y))) - -(deftransform 32bit-logical-nand ((x y) (* *)) - '(32bit-logical-not (32bit-logical-and x y))) - -(define-vop (32bit-logical-or 32bit-logical) - (:translate 32bit-logical-or) - (:generator 1 - (inst or r x y))) - -(deftransform 32bit-logical-nor ((x y) (* *)) - '(32bit-logical-not (32bit-logical-or x y))) - -(define-vop (32bit-logical-xor 32bit-logical) - (:translate 32bit-logical-xor) - (:generator 1 - (inst xor r x y))) - -(define-vop (32bit-logical-eqv 32bit-logical) - (:translate 32bit-logical-eqv) - (:generator 1 - (inst eqv r x y))) - -(define-vop (32bit-logical-orc2 32bit-logical) - (:translate 32bit-logical-orc2) - (:generator 1 - (inst orc r x y))) - -(deftransform 32bit-logical-orc1 ((x y) (* *)) - '(32bit-logical-orc2 y x)) - -(define-vop (32bit-logical-andc2 32bit-logical) - (:translate 32bit-logical-andc2) - (:generator 1 - (inst andc r x y))) - -(deftransform 32bit-logical-andc1 ((x y) (* *)) - '(32bit-logical-andc2 y x)) - - (define-vop (shift-towards-someplace) (:policy :fast-safe) (:args (num :scs (unsigned-reg)) @@ -655,29 +732,26 @@ (:generator 1 (inst rlwinm amount amount 0 27 31) (inst srw r num amount))) - - - ;;;; Bignum stuff. (define-vop (bignum-length get-header-data) - (:translate sb!bignum::%bignum-length) + (:translate sb!bignum:%bignum-length) (:policy :fast-safe)) (define-vop (bignum-set-length set-header-data) - (:translate sb!bignum::%bignum-set-length) + (:translate sb!bignum:%bignum-set-length) (:policy :fast-safe)) (define-vop (bignum-ref word-index-ref) - (:variant sb!vm:bignum-digits-offset sb!vm:other-pointer-lowtag) - (:translate sb!bignum::%bignum-ref) + (:variant bignum-digits-offset other-pointer-lowtag) + (:translate sb!bignum:%bignum-ref) (:results (value :scs (unsigned-reg))) (:result-types unsigned-num)) (define-vop (bignum-set word-index-set) - (:variant sb!vm:bignum-digits-offset sb!vm:other-pointer-lowtag) - (:translate sb!bignum::%bignum-set) + (:variant bignum-digits-offset other-pointer-lowtag) + (:translate sb!bignum:%bignum-set) (:args (object :scs (descriptor-reg)) (index :scs (any-reg immediate zero)) (value :scs (unsigned-reg))) @@ -686,7 +760,7 @@ (:result-types unsigned-num)) (define-vop (digit-0-or-plus) - (:translate sb!bignum::%digit-0-or-plusp) + (:translate sb!bignum:%digit-0-or-plusp) (:policy :fast-safe) (:args (digit :scs (unsigned-reg))) (:arg-types unsigned-num) @@ -700,7 +774,7 @@ (emit-label done)))) (define-vop (add-w/carry) - (:translate sb!bignum::%add-with-carry) + (:translate sb!bignum:%add-with-carry) (:policy :fast-safe) (:args (a :scs (unsigned-reg)) (b :scs (unsigned-reg)) @@ -716,7 +790,7 @@ (inst addze carry zero-tn))) (define-vop (sub-w/borrow) - (:translate sb!bignum::%subtract-with-borrow) + (:translate sb!bignum:%subtract-with-borrow) (:policy :fast-safe) (:args (a :scs (unsigned-reg)) (b :scs (unsigned-reg)) @@ -732,7 +806,7 @@ (inst addze borrow zero-tn))) (define-vop (bignum-mult-and-add-3-arg) - (:translate sb!bignum::%multiply-and-add) + (:translate sb!bignum:%multiply-and-add) (:policy :fast-safe) (:args (x :scs (unsigned-reg)) (y :scs (unsigned-reg)) @@ -751,7 +825,7 @@ (inst addze hi hi-temp))) (define-vop (bignum-mult-and-add-4-arg) - (:translate sb!bignum::%multiply-and-add) + (:translate sb!bignum:%multiply-and-add) (:policy :fast-safe) (:args (x :scs (unsigned-reg)) (y :scs (unsigned-reg)) @@ -773,30 +847,23 @@ (inst addze hi hi-temp))) (define-vop (bignum-mult) - (:translate sb!bignum::%multiply) + (:translate sb!bignum:%multiply) (:policy :fast-safe) - (:args (x :scs (unsigned-reg) :to (:result 1)) - (y :scs (unsigned-reg) :to (:result 1))) + (:args (x :scs (unsigned-reg) :to (:eval 1)) + (y :scs (unsigned-reg) :to (:eval 1))) (:arg-types unsigned-num unsigned-num) - (:results (hi :scs (unsigned-reg)) - (lo :scs (unsigned-reg))) + (:results (hi :scs (unsigned-reg) :from (:eval 1)) + (lo :scs (unsigned-reg) :from (:eval 0))) (:result-types unsigned-num unsigned-num) (:generator 40 (inst mullw lo x y) (inst mulhwu hi x y))) -(define-vop (bignum-lognot) - (:translate sb!bignum::%lognot) - (:policy :fast-safe) - (:args (x :scs (unsigned-reg))) - (:arg-types unsigned-num) - (:results (r :scs (unsigned-reg))) - (:result-types unsigned-num) - (:generator 1 - (inst not r x))) +(define-vop (bignum-lognot lognot-mod32/unsigned=>unsigned) + (:translate sb!bignum:%lognot)) (define-vop (fixnum-to-digit) - (:translate sb!bignum::%fixnum-to-digit) + (:translate sb!bignum:%fixnum-to-digit) (:policy :fast-safe) (:args (fixnum :scs (any-reg))) (:arg-types tagged-num) @@ -807,7 +874,7 @@ (define-vop (bignum-floor) - (:translate sb!bignum::%floor) + (:translate sb!bignum:%floor) (:policy :fast-safe) (:args (num-high :scs (unsigned-reg) :target rem) (num-low :scs (unsigned-reg) :target rem-low) @@ -845,7 +912,7 @@ #| (define-vop (bignum-floor) - (:translate sb!bignum::%floor) + (:translate sb!bignum:%floor) (:policy :fast-safe) (:args (div-high :scs (unsigned-reg) :target rem) (div-low :scs (unsigned-reg) :target quo) @@ -861,7 +928,7 @@ |# (define-vop (signify-digit) - (:translate sb!bignum::%fixnum-digit-with-correct-sign) + (:translate sb!bignum:%fixnum-digit-with-correct-sign) (:policy :fast-safe) (:args (digit :scs (unsigned-reg) :target res)) (:arg-types unsigned-num) @@ -876,7 +943,7 @@ (define-vop (digit-ashr) - (:translate sb!bignum::%ashr) + (:translate sb!bignum:%ashr) (:policy :fast-safe) (:args (digit :scs (unsigned-reg)) (count :scs (unsigned-reg))) @@ -887,12 +954,12 @@ (inst sraw result digit count))) (define-vop (digit-lshr digit-ashr) - (:translate sb!bignum::%digit-logical-shift-right) + (:translate sb!bignum:%digit-logical-shift-right) (:generator 1 (inst srw result digit count))) (define-vop (digit-ashl digit-ashr) - (:translate sb!bignum::%ashl) + (:translate sb!bignum:%ashl) (:generator 1 (inst slw result digit count))) @@ -919,3 +986,26 @@ (define-static-fun two-arg-and (x y) :translate logand) (define-static-fun two-arg-ior (x y) :translate logior) (define-static-fun two-arg-xor (x y) :translate logxor) +(define-static-fun two-arg-eqv (x y) :translate logeqv) + +(in-package "SB!C") + +(deftransform * ((x y) + ((unsigned-byte 32) (constant-arg (unsigned-byte 32))) + (unsigned-byte 32)) + "recode as shifts and adds" + (let ((y (lvar-value y))) + (multiple-value-bind (result adds shifts) + (ub32-strength-reduce-constant-multiply 'x y) + (cond + ((typep y '(signed-byte 16)) + ;; 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)))) + (or result 0))))