0.8.3.45.modular1:
authorChristophe Rhodes <csr21@cam.ac.uk>
Mon, 8 Sep 2003 15:47:45 +0000 (15:47 +0000)
committerChristophe Rhodes <csr21@cam.ac.uk>
Mon, 8 Sep 2003 15:47:45 +0000 (15:47 +0000)
Implement modular function optimization for PPC.
... Haven't implemented modular - or *; they could be TODO.
... probably doesn't build on anything but PPC currently, so
onto a branch it goes.

NEWS
package-data-list.lisp-expr
src/code/numbers.lisp
src/compiler/generic/vm-tran.lisp
src/compiler/ppc/arith.lisp
src/compiler/ppc/parms.lisp
src/compiler/srctran.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index fbbdb39..94f413c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2029,6 +2029,9 @@ changes in sbcl-0.8.4 relative to sbcl-0.8.3:
     performance of the compiler by about 20%.
   * optimization: performance of FILL (and :INITIAL-ELEMENT) on
     simple-base-strings and simple-bit-vectors is improved.
+  * optimization: the optimization of 32-bit logical and arithmetic
+    functions introduced in version 0.8.3 on the x86 has been
+    implemented on the ppc.
   * microoptimization: the compiler is better able to make use of the
     x86 LEA instruction for multiplication by constants.
   * bug fix: in some situations compiler did not report usage of
index 6abfe48..739f076 100644 (file)
@@ -1294,7 +1294,7 @@ is a good idea, but see SB-SYS re. blurring of boundaries."
              "TWO-ARG-/" "TWO-ARG-/=" "TWO-ARG-<"
              "TWO-ARG-<=" "TWO-ARG-="
              "TWO-ARG->" "TWO-ARG->=" "TWO-ARG-AND"
-             "TWO-ARG-GCD" "TWO-ARG-IOR"
+             "TWO-ARG-EQV" "TWO-ARG-GCD" "TWO-ARG-IOR"
              "TWO-ARG-LCM" "TWO-ARG-XOR"
              "TYPE-DIFFERENCE" "TYPE-EXPAND"
              "TYPE-INTERSECTION" "TYPE-INTERSECTION2"
index c2a1a6b..f3adc3b 100644 (file)
        (declare (integer result)))
       -1))
 
-(defun lognand (integer1 integer2)
-  #!+sb-doc
-  "Return the complement of the logical AND of integer1 and integer2."
-  (lognand integer1 integer2))
-
-(defun lognor (integer1 integer2)
-  #!+sb-doc
-  "Return the complement of the logical OR of integer1 and integer2."
-  (lognor integer1 integer2))
-
-(defun logandc1 (integer1 integer2)
-  #!+sb-doc
-  "Return the logical AND of (LOGNOT integer1) and integer2."
-  (logandc1 integer1 integer2))
-
-(defun logandc2 (integer1 integer2)
-  #!+sb-doc
-  "Return the logical AND of integer1 and (LOGNOT integer2)."
-  (logandc2 integer1 integer2))
-
-(defun logorc1 (integer1 integer2)
-  #!+sb-doc
-  "Return the logical OR of (LOGNOT integer1) and integer2."
-  (logorc1 integer1 integer2))
-
-(defun logorc2 (integer1 integer2)
-  #!+sb-doc
-  "Return the logical OR of integer1 and (LOGNOT integer2)."
-  (logorc2 integer1 integer2))
-
 (defun lognot (number)
   #!+sb-doc
   "Return the bit-wise logical not of integer."
     (fixnum (lognot (truly-the fixnum number)))
     (bignum (bignum-logical-not number))))
 
-(macrolet ((def (name op big-op)
-            `(defun ,name (x y)
-              (number-dispatch ((x integer) (y integer))
-                (bignum-cross-fixnum ,op ,big-op)))))
+(macrolet ((def (name op big-op &optional doc)
+            `(defun ,name (integer1 integer2)
+               ,@(when doc
+                   (list doc))
+               (let ((x integer1)
+                     (y integer2))
+                 (number-dispatch ((x integer) (y integer))
+                   (bignum-cross-fixnum ,op ,big-op))))))
   (def two-arg-and logand bignum-logical-and)
   (def two-arg-ior logior bignum-logical-ior)
-  (def two-arg-xor logxor bignum-logical-xor))
+  (def two-arg-xor logxor bignum-logical-xor)
+  ;; BIGNUM-LOGICAL-{AND,IOR,XOR} need not return a bignum, so must
+  ;; call the generic LOGNOT...
+  (def two-arg-eqv logeqv (lambda (x y) (lognot (bignum-logical-xor x y))))
+  (def lognand lognand 
+       (lambda (x y) (lognot (bignum-logical-and x y))) 
+       #!+sb-doc "Complement the logical AND of INTEGER1 and INTEGER2.")
+  (def lognor lognor
+       (lambda (x y) (lognot (bignum-logical-ior x y)))
+       #!+sb-doc "Complement the logical AND of INTEGER1 and INTEGER2.")
+  ;; ... but BIGNUM-LOGICAL-NOT on a bignum will always return a bignum
+  (def logandc1 logandc1
+       (lambda (x y) (bignum-logical-and (bignum-logical-not x) y))
+       #!+sb-doc "Bitwise AND (LOGNOT INTEGER1) with INTEGER2.")
+  (def logandc2 logandc2
+       (lambda (x y) (bignum-logical-and x (bignum-logical-not y)))
+       #!+sb-doc "Bitwise AND INTEGER1 with (LOGNOT INTEGER2).")
+  (def logorc1 logorc1
+       (lambda (x y) (bignum-logical-ior (bignum-logical-not x) y))
+       #!+sb-doc "Bitwise OR (LOGNOT INTEGER1) with INTEGER2.")
+  (def logorc2 logorc2
+       (lambda (x y) (bignum-logical-ior x (bignum-logical-not y)))
+       #!+sb-doc "Bitwise OR INTEGER1 with (LOGNOT INTEGER2)."))
 
 (defun logcount (integer)
   #!+sb-doc
index 4bb3a9f..e74749a 100644 (file)
 
 \f
 ;;;; 32-bit operations
-#!-x86 ; on X86 it is a modular function
+#!-(or ppc x86) ; on X86 it is a modular function
 (deftransform lognot ((x) ((unsigned-byte 32)) *
                       :node node
                       :result result)
index 91f23bf..abba8aa 100644 (file)
 
 (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)
 (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)
       (emit-label done))))
 
 \f
+;;;; Modular functions:
+(define-modular-fun lognot-mod32 (x) lognot 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)))
+
+(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))))))))
+  (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))
+\f
 ;;;; Binary conditional VOPs:
 
 (define-vop (fast-conditional)
       (emit-label done)
       (move result res))))
 
+(define-source-transform 32bit-logical-not (x)
+  `(logand (lognot (the (unsigned-byte 32) ,x)) #.(1- (ash 1 32))))
 
-(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)))
+(deftransform 32bit-logical-and ((x y))
+  '(logand x y))
 
-(define-vop (32bit-logical-or 32bit-logical)
-  (:translate 32bit-logical-or)
-  (:generator 1
-    (inst or r x y)))
+(deftransform 32bit-logical-nand ((x y))
+  '(logand (lognand x y) #.(1- (ash 1 32))))
 
-(deftransform 32bit-logical-nor ((x y) (* *))
-  '(32bit-logical-not (32bit-logical-or x y)))
+(deftransform 32bit-logical-or ((x y))
+  '(logior x y))
 
-(define-vop (32bit-logical-xor 32bit-logical)
-  (:translate 32bit-logical-xor)
-  (:generator 1
-    (inst xor r x y)))
+(deftransform 32bit-logical-nor ((x y))
+  '(logand (lognor x y) #.(1- (ash 1 32))))
 
-(define-vop (32bit-logical-eqv 32bit-logical)
-  (:translate 32bit-logical-eqv)
-  (:generator 1
-    (inst eqv r x y)))
+(deftransform 32bit-logical-xor ((x y))
+  '(logxor x y))
 
-(define-vop (32bit-logical-orc2 32bit-logical)
-  (:translate 32bit-logical-orc2)
-  (:generator 1
-    (inst orc r x y)))
+(deftransform 32bit-logical-eqv ((x y))
+  '(logand (logeqv x y) #.(1- (ash 1 32))))
 
-(deftransform 32bit-logical-orc1 ((x y) (* *))
-  '(32bit-logical-orc2 y x))
+(deftransform 32bit-logical-orc1 ((x y))
+  '(logand (logorc1 x y) #.(1- (ash 1 32))))
 
-(define-vop (32bit-logical-andc2 32bit-logical)
-  (:translate 32bit-logical-andc2)
-  (:generator 1
-    (inst andc r x y)))
+(deftransform 32bit-logical-orc2 ((x y))
+  '(logand (logorc2 x y) #.(1- (ash 1 32))))
 
-(deftransform 32bit-logical-andc1 ((x y) (* *))
-  '(32bit-logical-andc2 y x))
+(deftransform 32bit-logical-andc1 ((x y))
+  '(logand (logandc1 x y) #.(1- (ash 1 32))))
 
+(deftransform 32bit-logical-andc2 ((x y))
+  '(logand (logandc2 x y) #.(1- (ash 1 32))))
 
 (define-vop (shift-towards-someplace)
   (:policy :fast-safe)
   (:generator 1
     (inst rlwinm amount amount 0 27 31)
     (inst srw r num amount)))
-
-
-
 \f
 ;;;; Bignum stuff.
 
     (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)
 (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)
 \f
 (in-package "SB!C")
 
index 9a784d3..6a1377f 100644 (file)
     sb!kernel:two-arg-and
     sb!kernel:two-arg-ior
     sb!kernel:two-arg-xor
+    sb!kernel:two-arg-eqv
     sb!kernel:two-arg-gcd
     sb!kernel:two-arg-lcm))
 
index adb1dc2..a435801 100644 (file)
   #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
   (deffrob ceiling))
 
-(define-source-transform lognand (x y) `(lognot (logand ,x ,y)))
-(define-source-transform lognor (x y) `(lognot (logior ,x ,y)))
-(define-source-transform logandc1 (x y) `(logand (lognot ,x) ,y))
-(define-source-transform logandc2 (x y) `(logand ,x (lognot ,y)))
-(define-source-transform logorc1 (x y) `(logior (lognot ,x) ,y))
-(define-source-transform logorc2 (x y) `(logior ,x (lognot ,y)))
 (define-source-transform logtest (x y) `(not (zerop (logand ,x ,y))))
 (define-source-transform logbitp (index integer)
   `(not (zerop (logand (ash 1 ,index) ,integer))))
 ;;; the types of both X and Y are integer types, then we compute a new
 ;;; integer type with bounds determined Fun when applied to X and Y.
 ;;; Otherwise, we use Numeric-Contagion.
+(defun derive-integer-type-aux (x y fun)
+  (declare (type function fun))
+  (if (and (numeric-type-p x) (numeric-type-p y)
+          (eq (numeric-type-class x) 'integer)
+          (eq (numeric-type-class y) 'integer)
+          (eq (numeric-type-complexp x) :real)
+          (eq (numeric-type-complexp y) :real))
+      (multiple-value-bind (low high) (funcall fun x y)
+       (make-numeric-type :class 'integer
+                          :complexp :real
+                          :low low
+                          :high high))
+      (numeric-contagion x y)))
 (defun derive-integer-type (x y fun)
   (declare (type continuation x y) (type function fun))
   (let ((x (continuation-type x))
        (y (continuation-type y)))
-    (if (and (numeric-type-p x) (numeric-type-p y)
-            (eq (numeric-type-class x) 'integer)
-            (eq (numeric-type-class y) 'integer)
-            (eq (numeric-type-complexp x) :real)
-            (eq (numeric-type-complexp y) :real))
-       (multiple-value-bind (low high) (funcall fun x y)
-         (make-numeric-type :class 'integer
-                            :complexp :real
-                            :low low
-                            :high high))
-       (numeric-contagion x y))))
+    (derive-integer-type-aux x y fun)))
 
 ;;; simple utility to flatten a list
 (defun flatten-list (x)
   (defoptimizer (%negate derive-type) ((num))
     (derive-integer-type num num (frob -))))
 
+(defun lognot-derive-type-aux (int)
+  (derive-integer-type-aux int int
+                          (lambda (type type2)
+                            (declare (ignore type2))
+                            (let ((lo (numeric-type-low type))
+                                  (hi (numeric-type-high type)))
+                              (values (if hi (lognot hi) nil)
+                                      (if lo (lognot lo) nil)
+                                      (numeric-type-class type)
+                                      (numeric-type-format type))))))
+
 (defoptimizer (lognot derive-type) ((int))
-  (derive-integer-type int int
-                      (lambda (type type2)
-                        (declare (ignore type2))
-                        (let ((lo (numeric-type-low type))
-                              (hi (numeric-type-high type)))
-                          (values (if hi (lognot hi) nil)
-                                  (if lo (lognot lo) nil)
-                                  (numeric-type-class type)
-                                  (numeric-type-format type))))))
+  (lognot-derive-type-aux (continuation-type int)))
 
 #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.)
 (defoptimizer (%negate derive-type) ((num))
                                             '*)))))
        ((or (and (not x-pos) (not y-neg))
            (and (not y-neg) (not y-pos)))
-       ;; Either X is negative and Y is positive of vice-versa. The
+       ;; Either X is negative and Y is positive or vice-versa. The
        ;; result will be negative.
        (specifier-type `(integer ,(if (and x-len y-len)
                                       (ash -1 (max x-len y-len))
   (deffrob logand)
   (deffrob logior)
   (deffrob logxor))
+
+;;; FIXME: could actually do stuff with SAME-LEAF
+(defoptimizer (logeqv derive-type) ((x y))
+  (two-arg-derive-type x y (lambda (x y same-leaf)
+                            (lognot-derive-type-aux 
+                             (logxor-derive-type-aux x y same-leaf))) 
+                      #'logeqv))
+(defoptimizer (lognand derive-type) ((x y))
+  (two-arg-derive-type x y (lambda (x y same-leaf)
+                            (lognot-derive-type-aux
+                             (logand-derive-type-aux x y same-leaf)))
+                      #'lognand))
+(defoptimizer (lognor derive-type) ((x y))
+  (two-arg-derive-type x y (lambda (x y same-leaf)
+                            (lognot-derive-type-aux
+                             (logior-derive-type-aux x y same-leaf)))
+                      #'lognor))
+(defoptimizer (logandc1 derive-type) ((x y))
+  (two-arg-derive-type x y (lambda (x y same-leaf)
+                            (logand-derive-type-aux
+                             (lognot-derive-type-aux x) y nil))
+                      #'logandc1))
+(defoptimizer (logandc2 derive-type) ((x y))
+  (two-arg-derive-type x y (lambda (x y same-leaf)
+                            (logand-derive-type-aux
+                             x (lognot-derive-type-aux y) nil))
+                      #'logandc2))
+(defoptimizer (logorc1 derive-type) ((x y))
+  (two-arg-derive-type x y (lambda (x y same-leaf)
+                            (logior-derive-type-aux
+                             (lognot-derive-type-aux x) y nil))
+                      #'logorc1))
+(defoptimizer (logorc2 derive-type) ((x y))
+  (two-arg-derive-type x y (lambda (x y same-leaf)
+                            (logior-derive-type-aux
+                             x (lognot-derive-type-aux y) nil))
+                      #'logorc2))
 \f
 ;;;; miscellaneous derive-type methods
 
   (source-transform-transitive 'logxor args 0 'integer))
 (define-source-transform logand (&rest args)
   (source-transform-transitive 'logand args -1 'integer))
-
 (define-source-transform logeqv (&rest args)
-  (if (evenp (length args))
-      `(lognot (logxor ,@args))
-      `(logxor ,@args)))
+  (source-transform-transitive 'logeqv args -1 'integer))
 
 ;;; Note: we can't use SOURCE-TRANSFORM-TRANSITIVE for GCD and LCM
 ;;; because when they are given one argument, they return its absolute
index cefce68..57b4440 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.3.45"
+"0.8.3.45.modular1"