0.8.9.16:
[sbcl.git] / src / compiler / srctran.lisp
index fe7f950..71a2313 100644 (file)
 ;;; "goodness" means that the result will not increase (in the
 ;;; (unsigned-byte +infinity) sense). An ordinary modular function is
 ;;; replaced with the version, cutting its result to WIDTH or more
-;;; bits. If we have changed anything, we need to flush old derived
-;;; types, because they have nothing in common with the new code.
+;;; bits. For most functions (e.g. for +) we cut all arguments; for
+;;; others (e.g. for ASH) we have "optimizers", cutting only necessary
+;;; arguments (maybe to a different width) and returning the name of a
+;;; modular version, if it exists, or NIL. If we have changed
+;;; anything, we need to flush old derived types, because they have
+;;; nothing in common with the new code.
 (defun cut-to-width (lvar width)
   (declare (type lvar lvar) (type (integer 0) width))
   (labels ((reoptimize-node (node name)
            (cut-node (node &aux did-something)
              (when (and (not (block-delete-p (node-block node)))
                         (combination-p node)
-                        (fun-info-p (basic-combination-kind node)))
+                       (eq (basic-combination-kind node) :known))
                (let* ((fun-ref (lvar-use (combination-fun node)))
                       (fun-name (leaf-source-name (ref-leaf fun-ref)))
-                      (modular-fun (find-modular-version fun-name width))
-                      (name (and (modular-fun-info-p modular-fun)
-                                 (modular-fun-info-name modular-fun))))
+                      (modular-fun (find-modular-version fun-name width)))
                  (when (and modular-fun
-                            (not (and (eq name 'logand)
+                            (not (and (eq fun-name 'logand)
                                       (csubtypep
                                        (single-value-type (node-derived-type node))
-                                       (specifier-type `(unsigned-byte ,width))))))
-                   (unless (eq modular-fun :good)
-                     (setq did-something t)
-                     (change-ref-leaf
+                                       (specifier-type `(unsigned-byte* ,width))))))
+                   (binding* ((name (etypecase modular-fun
+                                      ((eql :good) fun-name)
+                                      (modular-fun-info
+                                       (modular-fun-info-name modular-fun))
+                                      (function
+                                       (funcall modular-fun node width)))
+                                :exit-if-null))
+                     (unless (eql modular-fun :good)
+                       (setq did-something t)
+                       (change-ref-leaf
                         fun-ref
                         (find-free-fun name "in a strange place"))
                        (setf (combination-kind node) :full))
-                   (dolist (arg (basic-combination-args node))
-                     (when (cut-lvar arg)
-                       (setq did-something t)))
-                   (when did-something
-                     (reoptimize-node node fun-name))
-                   did-something))))
+                     (unless (functionp modular-fun)
+                       (dolist (arg (basic-combination-args node))
+                         (when (cut-lvar arg)
+                           (setq did-something t))))
+                     (when did-something
+                       (reoptimize-node node name))
+                     did-something)))))
            (cut-lvar (lvar &aux did-something)
              (do-uses (node lvar)
                (when (cut-node node)
     (give-up-ir1-transform "BOOLE code is not a constant."))
   (let ((control (lvar-value op)))
     (case control
-      (#.boole-clr 0)
-      (#.boole-set -1)
-      (#.boole-1 'x)
-      (#.boole-2 'y)
-      (#.boole-c1 '(lognot x))
-      (#.boole-c2 '(lognot y))
-      (#.boole-and '(logand x y))
-      (#.boole-ior '(logior x y))
-      (#.boole-xor '(logxor x y))
-      (#.boole-eqv '(logeqv x y))
-      (#.boole-nand '(lognand x y))
-      (#.boole-nor '(lognor x y))
-      (#.boole-andc1 '(logandc1 x y))
-      (#.boole-andc2 '(logandc2 x y))
-      (#.boole-orc1 '(logorc1 x y))
-      (#.boole-orc2 '(logorc2 x y))
+      (#.sb!xc:boole-clr 0)
+      (#.sb!xc:boole-set -1)
+      (#.sb!xc:boole-1 'x)
+      (#.sb!xc:boole-2 'y)
+      (#.sb!xc:boole-c1 '(lognot x))
+      (#.sb!xc:boole-c2 '(lognot y))
+      (#.sb!xc:boole-and '(logand x y))
+      (#.sb!xc:boole-ior '(logior x y))
+      (#.sb!xc:boole-xor '(logxor x y))
+      (#.sb!xc:boole-eqv '(logeqv x y))
+      (#.sb!xc:boole-nand '(lognand x y))
+      (#.sb!xc:boole-nor '(lognor x y))
+      (#.sb!xc:boole-andc1 '(logandc1 x y))
+      (#.sb!xc:boole-andc2 '(logandc2 x y))
+      (#.sb!xc:boole-orc1 '(logorc1 x y))
+      (#.sb!xc:boole-orc2 '(logorc2 x y))
       (t
        (abort-ir1-transform "~S is an illegal control arg to BOOLE."
                            control)))))
     (if (null rest)
        `(values (the real ,arg0))
        `(let ((maxrest (max ,@rest)))
-         (if (> ,arg0 maxrest) ,arg0 maxrest)))))
+         (if (>= ,arg0 maxrest) ,arg0 maxrest)))))
 (define-source-transform min (arg0 &rest rest)
   (once-only ((arg0 arg0))
     (if (null rest)
        `(values (the real ,arg0))
        `(let ((minrest (min ,@rest)))
-         (if (< ,arg0 minrest) ,arg0 minrest)))))
+         (if (<= ,arg0 minrest) ,arg0 minrest)))))
 \f
 ;;;; converting N-arg arithmetic functions
 ;;;;
            (t
             *universal-type*)))))
 
+;;; Like CMU CL, we use HEAPSORT. However, other than that, this code
+;;; isn't really related to the CMU CL code, since instead of trying
+;;; to generalize the CMU CL code to allow START and END values, this
+;;; code has been written from scratch following Chapter 7 of
+;;; _Introduction to Algorithms_ by Corman, Rivest, and Shamir.
 (define-source-transform sb!impl::sort-vector (vector start end predicate key)
+  ;; Like CMU CL, we use HEAPSORT. However, other than that, this code
+  ;; isn't really related to the CMU CL code, since instead of trying
+  ;; to generalize the CMU CL code to allow START and END values, this
+  ;; code has been written from scratch following Chapter 7 of
+  ;; _Introduction to Algorithms_ by Corman, Rivest, and Shamir.
   `(macrolet ((%index (x) `(truly-the index ,x))
              (%parent (i) `(ash ,i -1))
              (%left (i) `(%index (ash ,i 1)))
                                      (%elt largest) i-elt
                                      i largest)))))))))
              (%sort-vector (keyfun &optional (vtype 'vector))
-              `(macrolet (;; KLUDGE: In SBCL ca. 0.6.10, I had trouble getting
-                          ;; type inference to propagate all the way
-                          ;; through this tangled mess of
-                          ;; inlining. The TRULY-THE here works
-                          ;; around that. -- WHN
+              `(macrolet (;; KLUDGE: In SBCL ca. 0.6.10, I had
+                          ;; trouble getting type inference to
+                          ;; propagate all the way through this
+                          ;; tangled mess of inlining. The TRULY-THE
+                          ;; here works around that. -- WHN
                           (%elt (i)
                            `(aref (truly-the ,',vtype ,',',vector)
                              (%index (+ (%index ,i) start-1)))))
-                (let ((start-1 (1- ,',start)) ; Heaps prefer 1-based addressing.
+                (let (;; Heaps prefer 1-based addressing.
+                      (start-1 (1- ,',start)) 
                       (current-heap-size (- ,',end ,',start))
                       (keyfun ,keyfun))
                   (declare (type (integer -1 #.(1- most-positive-fixnum))