0.7.5.15:
[sbcl.git] / src / compiler / generic / vm-tran.lisp
index 8b24413..7031de3 100644 (file)
 
 (in-package "SB!C")
 
-;;; FIXME: It would be good to implement SB!XC:DEFCONSTANT, and use
-;;; use that here, so that the compiler is born knowing this value.
-;;; FIXME: Add a comment telling whether this holds for all vectors
-;;; or only for vectors based on simple arrays (non-adjustable, etc.).
-(defconstant vector-data-bit-offset
-  (* sb!vm:vector-data-offset sb!vm:n-word-bits))
-
 ;;; We need to define these predicates, since the TYPEP source
 ;;; transform picks whichever predicate was defined last when there
 ;;; are multiple predicates for equivalent types.
     ;; to hand-expand it ourselves.)
     (let ((element-type-specifier (type-specifier element-ctype)))
       `(multiple-value-bind (array index)
-          ;; FIXME: All this noise should move into a
-          ;; %DATA-VECTOR-AND-INDEX function, and there should be
-          ;; DEFTRANSFORMs for %DATA-VECTOR-AND-INDEX to optimize the
-          ;; function call away when the array is known to be simple,
-          ;; and to specialize to
-          ;; %DATA-VECTOR-AND-INDEX-IN-VECTOR-CASE when the array is
-          ;; known to have only one dimension.
-          (if (array-header-p array)
-              (%with-array-data array index nil)
-              (let ((array array))
-                (declare (type (simple-array ,element-type-specifier 1)
-                               array))
-                (%check-bound array 0 index)
-                (values array index)))
+          (%data-vector-and-index array index)
         (declare (type (simple-array ,element-type-specifier 1) array))
         (data-vector-ref array index)))))
 
@@ -86,7 +66,7 @@
     (let ((dims (array-type-dimensions array-type)))
       (when (or (atom dims) (= (length dims) 1))
         (give-up-ir1-transform))
-      (let ((el-type (array-type-element-type array-type))
+      (let ((el-type (array-type-specialized-element-type array-type))
             (total-size (if (member '* dims)
                             '*
                             (reduce #'* dims))))
        "Upgraded element type of array is not known at compile time."))
     (let ((element-type-specifier (type-specifier element-ctype)))
       `(multiple-value-bind (array index)
-          ;; FIXME: All this noise should move into a
-          ;; %DATA-VECTOR-AND-INDEX function, and there should be
-          ;; DEFTRANSFORMs for %DATA-VECTOR-AND-INDEX to optimize the
-          ;; function call away when the array is known to be simple,
-          ;; and to specialize to
-          ;; %DATA-VECTOR-AND-INDEX-IN-VECTOR-CASE when the array is
-          ;; known to have only one dimension.
-          (if (array-header-p array)
-              (%with-array-data array index nil)
-              (let ((array array))
-                (declare (type (simple-array ,element-type-specifier 1)
-                               array))
-                (%check-bound array 0 index)
-                (values array index)))
-        (data-vector-set (truly-the (simple-array ,element-type-specifier 1)
-                                    array)
+          (%data-vector-and-index array index)
+        (declare (type (simple-array ,element-type-specifier 1) array)
+                 (type ,element-type-specifier new-value))
+        (data-vector-set array
                          index
                          new-value)))))
 
     (let ((dims (array-type-dimensions array-type)))
       (when (or (atom dims) (= (length dims) 1))
         (give-up-ir1-transform))
-      (let ((el-type (array-type-element-type array-type))
+      (let ((el-type (array-type-specialized-element-type array-type))
             (total-size (if (member '* dims)
                             '*
                             (reduce #'* dims))))
                           index
                           new-value)))))
 
+(defoptimizer (%data-vector-and-index derive-type) ((array index))
+  (let ((atype (continuation-type array)))
+    (when (array-type-p atype)
+      (values-specifier-type
+       `(values (simple-array ,(type-specifier
+                                (array-type-specialized-element-type atype))
+                              (*))
+                index)))))
+
+(deftransform %data-vector-and-index ((array index)
+                                     (simple-array t)
+                                     *
+                                     :important t)
+
+  ;; We do this solely for the -OR-GIVE-UP side effect, since we want
+  ;; to know that the type can be figured out in the end before we
+  ;; proceed, but we don't care yet what the type will turn out to be.
+  (upgraded-element-type-specifier-or-give-up array)
+
+  '(if (array-header-p array)
+       (values (%array-data-vector array) index)
+       (values array index)))
+
 ;;; transforms for getting at simple arrays of (UNSIGNED-BYTE N) when (< N 8)
 ;;;
 ;;; FIXME: In CMU CL, these were commented out with #+NIL. Why? Should
                                         bit-array-1
                                        bit-array-2
                                        result-bit-array))))
-                  (do ((index sb!vm:vector-data-offset (1+ index))
-                       (end (+ sb!vm:vector-data-offset
-                               (truncate (the index
-                                           (+ (length bit-array-1)
-                                              sb!vm:n-word-bits -1))
-                                         sb!vm:n-word-bits))))
-                      ((= index end) result-bit-array)
-                    (declare (optimize (speed 3) (safety 0))
-                             (type index index end))
-                    (setf (%raw-bits result-bit-array index)
-                          (,',wordfun (%raw-bits bit-array-1 index)
-                                      (%raw-bits bit-array-2 index))))))))
+                 (let ((length (length result-bit-array)))
+                   (if (= length 0)
+                       ;; We avoid doing anything to 0-length
+                       ;; bit-vectors, or rather, the memory that
+                       ;; follows them. Other divisible-by-32 cases
+                       ;; are handled by the (1- length), below.
+                       ;; CSR, 2002-04-24
+                       result-bit-array
+                       (do ((index sb!vm:vector-data-offset (1+ index))
+                            (end-1 (+ sb!vm:vector-data-offset
+                                      ;; bit-vectors of length 1-32
+                                      ;; need precisely one (SETF
+                                      ;; %RAW-BITS), done here in the
+                                      ;; epilogue. - CSR, 2002-04-24
+                                      (truncate (truly-the index (1- length))
+                                                sb!vm:n-word-bits))))
+                           ((= index end-1)
+                            (setf (%raw-bits result-bit-array index)
+                                  (,',wordfun (%raw-bits bit-array-1 index)
+                                              (%raw-bits bit-array-2 index)))
+                            result-bit-array)
+                         (declare (optimize (speed 3) (safety 0))
+                                  (type index index end-1))
+                         (setf (%raw-bits result-bit-array index)
+                               (,',wordfun (%raw-bits bit-array-1 index)
+                                           (%raw-bits bit-array-2 index))))))))))
  (def bit-and 32bit-logical-and)
  (def bit-ior 32bit-logical-or)
  (def bit-xor 32bit-logical-xor)
             (error "Argument and result bit arrays are not the same length:~
                     ~%  ~S~%  ~S"
                    bit-array result-bit-array))))
-     (do ((index sb!vm:vector-data-offset (1+ index))
-         (end (+ sb!vm:vector-data-offset
-                 (truncate (the index
-                                (+ (length bit-array)
-                                   (1- sb!vm:n-word-bits)))
-                           sb!vm:n-word-bits))))
-        ((= index end) result-bit-array)
-       (declare (optimize (speed 3) (safety 0))
-               (type index index end))
-       (setf (%raw-bits result-bit-array index)
-            (32bit-logical-not (%raw-bits bit-array index))))))
+    (let ((length (length result-bit-array)))
+      (if (= length 0)
+         ;; We avoid doing anything to 0-length bit-vectors, or
+         ;; rather, the memory that follows them. Other
+         ;; divisible-by-32 cases are handled by the (1- length),
+         ;; below.  CSR, 2002-04-24
+         result-bit-array
+         (do ((index sb!vm:vector-data-offset (1+ index))
+              (end-1 (+ sb!vm:vector-data-offset
+                        ;; bit-vectors of length 1-32 need precisely
+                        ;; one (SETF %RAW-BITS), done here in the
+                        ;; epilogue. - CSR, 2002-04-24
+                        (truncate (truly-the index (1- length))
+                                  sb!vm:n-word-bits))))
+             ((= index end-1)
+              (setf (%raw-bits result-bit-array index)
+                    (32bit-logical-not (%raw-bits bit-array index)))
+              result-bit-array)
+           (declare (optimize (speed 3) (safety 0))
+                    (type index index end-1))
+           (setf (%raw-bits result-bit-array index)
+                 (32bit-logical-not (%raw-bits bit-array index))))))))
 \f
 ;;;; %BYTE-BLT