From: Paul Khuong Date: Fri, 28 Jun 2013 06:36:13 +0000 (-0400) Subject: Modular integer %NEGATE on x86oids X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=dacd3fc70cf2fc78677f9a8bbbb5c3b51883f1b7;p=sbcl.git Modular integer %NEGATE on x86oids Forms like (logand (- word) word) now compute the negation in modular arithmetic, without consing an intermediate bignum, just like integer addition, multiplication and subtraction. The VOPs are trivial, and should be easily added on all other platforms, I just don't have access to build hosts. --- diff --git a/NEWS b/NEWS index e578a61..07f5998 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ changes relative to sbcl-1.1.9: * optimization: stack frames are packed more efficiently on x86oids, which ought to reduce the frequency of Methuselahn conservative references (it certainly helps with gc.impure.lisp / BUG-936304 on x86). + * optimization: on x86 and x86-64, integer negation forms like (- x) are now + recognized in modular arithmetic contexts, and compile to native negate, + rather than going through bignums only to keep the low bits. * bug fix: Compiling potential modularic arithmetic forms does not cause type errors when some integer types lack lower or upper bounds. (lp#1199127) * bug fix: Non-trivial modular arithmetic forms are always cut to the right diff --git a/src/compiler/x86-64/arith.lisp b/src/compiler/x86-64/arith.lisp index e1929f1..c50e0dd 100644 --- a/src/compiler/x86-64/arith.lisp +++ b/src/compiler/x86-64/arith.lisp @@ -1505,6 +1505,23 @@ constant shift greater than word length"))) (def - t) (def * t)) +(define-modular-fun %negate-mod64 (x) %negate :untagged nil 64) +(define-vop (%negate-mod64) + (:translate %negate-mod64) + (:policy :fast-safe) + (:args (x :scs (unsigned-reg) :target r)) + (:arg-types unsigned-num) + (:results (r :scs (unsigned-reg))) + (:result-types unsigned-num) + (:generator 3 + (move r x) + (inst neg r))) + +(define-modular-fun %negate-modfx (x) %negate :tagged t #.(- n-word-bits + n-fixnum-tag-bits)) +(define-vop (%negate-modfx fast-negate/fixnum) + (:translate %negate-modfx)) + (define-vop (fast-ash-left-mod64-c/unsigned=>unsigned fast-ash-c/unsigned=>unsigned) (:translate ash-left-mod64)) diff --git a/src/compiler/x86/arith.lisp b/src/compiler/x86/arith.lisp index 79064d0..9a04be9 100644 --- a/src/compiler/x86/arith.lisp +++ b/src/compiler/x86/arith.lisp @@ -1362,6 +1362,22 @@ constant shift greater than word length"))) ;; (no -C variant as x86 MUL instruction doesn't take an immediate) (def * nil)) +(define-modular-fun %negate-mod32 (x) %negate :untagged nil 32) +(define-vop (%negate-mod32) + (:translate %negate-mod32) + (:policy :fast-safe) + (:args (x :scs (unsigned-reg) :target r)) + (:arg-types unsigned-num) + (:results (r :scs (unsigned-reg))) + (:result-types unsigned-num) + (:generator 3 + (move r x) + (inst neg r))) + +(define-modular-fun %negate-modfx (x) %negate :tagged t #.(- n-word-bits + n-fixnum-tag-bits)) +(define-vop (%negate-modfx fast-negate/fixnum) + (:translate %negate-modfx)) (define-vop (fast-ash-left-mod32-c/unsigned=>unsigned fast-ash-c/unsigned=>unsigned)