Modular integer %NEGATE on x86oids
authorPaul Khuong <pvk@pvk.ca>
Fri, 28 Jun 2013 06:36:13 +0000 (02:36 -0400)
committerPaul Khuong <pvk@pvk.ca>
Thu, 18 Jul 2013 21:04:13 +0000 (17:04 -0400)
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.

NEWS
src/compiler/x86-64/arith.lisp
src/compiler/x86/arith.lisp

diff --git a/NEWS b/NEWS
index e578a61..07f5998 100644 (file)
--- 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
index e1929f1..c50e0dd 100644 (file)
@@ -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))
index 79064d0..9a04be9 100644 (file)
@@ -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)