0.8.3.55:
[sbcl.git] / src / compiler / typetran.lisp
index 06f0de1..9624814 100644 (file)
 ;;; binds specified by TYPE. BASE is the name of the base type, for
 ;;; declaration. We make SAFETY locally 0 to inhibit any checking of
 ;;; this assertion.
-#!-negative-zero-is-not-zero
 (defun transform-numeric-bound-test (n-object type base)
   (declare (type numeric-type type))
   (let ((low (numeric-type-low type))
        (declare (optimize (safety 0)))
        (and ,@(when low
                (if (consp low)
-                   `((> (the ,base ,n-object) ,(car low)))
-                   `((>= (the ,base ,n-object) ,low))))
+                   `((> (truly-the ,base ,n-object) ,(car low)))
+                   `((>= (truly-the ,base ,n-object) ,low))))
            ,@(when high
                (if (consp high)
-                   `((< (the ,base ,n-object) ,(car high)))
-                   `((<= (the ,base ,n-object) ,high))))))))
-
-#!+negative-zero-is-not-zero
-(defun transform-numeric-bound-test (n-object type base)
-  (declare (type numeric-type type))
-  (let ((low (numeric-type-low type))
-       (high (numeric-type-high type))
-       (float-type-p (csubtypep type (specifier-type 'float)))
-       (x (gensym))
-       (y (gensym)))
-    `(locally
-       (declare (optimize (safety 0)))
-       (and ,@(when low
-               (if (consp low)
-                   `((let ((,x (the ,base ,n-object))
-                           (,y ,(car low)))
-                       ,(if (not float-type-p)
-                           `(> ,x ,y)
-                           `(if (and (zerop ,x) (zerop ,y))
-                                (> (float-sign ,x) (float-sign ,y))
-                                (> ,x ,y)))))
-                   `((let ((,x (the ,base ,n-object))
-                           (,y ,low))
-                       ,(if (not float-type-p)
-                           `(>= ,x ,y)
-                           `(if (and (zerop ,x) (zerop ,y))
-                                (>= (float-sign ,x) (float-sign ,y))
-                                (>= ,x ,y)))))))
-           ,@(when high
-               (if (consp high)
-                   `((let ((,x (the ,base ,n-object))
-                           (,y ,(car high)))
-                       ,(if (not float-type-p)
-                            `(< ,x ,y)
-                            `(if (and (zerop ,x) (zerop ,y))
-                                 (< (float-sign ,x) (float-sign ,y))
-                                 (< ,x ,y)))))
-                   `((let ((,x (the ,base ,n-object))
-                           (,y ,high))
-                       ,(if (not float-type-p)
-                            `(<= ,x ,y)
-                            `(if (and (zerop ,x) (zerop ,y))
-                                 (<= (float-sign ,x) (float-sign ,y))
-                                 (<= ,x ,y)))))))))))
+                   `((< (truly-the ,base ,n-object) ,(car high)))
+                   `((<= (truly-the ,base ,n-object) ,high))))))))
 
 ;;; Do source transformation of a test of a known numeric type. We can
 ;;; assume that the type doesn't have a corresponding predicate, since
 (defun source-transform-numeric-typep (object type)
   (let* ((class (numeric-type-class type))
         (base (ecase class
-                (integer (containing-integer-type type))
+                (integer (containing-integer-type
+                           (if (numeric-type-complexp type)
+                               (modified-numeric-type type
+                                                      :complexp :real)
+                               type)))
                 (rational 'rational)
                 (float (or (numeric-type-format type) 'float))
                 ((nil) 'real))))
               ,(transform-numeric-bound-test n-object type base)))
        (:complex
         `(and (complexp ,n-object)
-              ,(once-only ((n-real `(realpart (the complex ,n-object)))
-                           (n-imag `(imagpart (the complex ,n-object))))
+              ,(once-only ((n-real `(realpart (truly-the complex ,n-object)))
+                           (n-imag `(imagpart (truly-the complex ,n-object))))
                  `(progn
                     ,n-imag ; ignorable
                     (and (typep ,n-real ',base)
   (let ((spec (hairy-type-specifier type)))
     (cond ((unknown-type-p type)
           (when (policy *lexenv* (> speed inhibit-warnings))
-            (compiler-note "can't open-code test of unknown type ~S"
-                           (type-specifier type)))
+            (compiler-notify "can't open-code test of unknown type ~S"
+                             (type-specifier type)))
           `(%typep ,object ',spec))
          (t
           (ecase (first spec)
 ;;; trying to optimize it.
 (defun source-transform-union-typep (object type)
   (let* ((types (union-type-types type))
-        (ltype (specifier-type 'list))
-        (mtype (find-if #'member-type-p types)))
-    (if (and mtype (csubtypep ltype type))
-       (let ((members (member-type-members mtype)))
-         (once-only ((n-obj object))
-           `(or (listp ,n-obj)
-                (typep ,n-obj
-                       '(or ,@(mapcar #'type-specifier
-                                      (remove (specifier-type 'cons)
-                                              (remove mtype types)))
-                            (member ,@(remove nil members)))))))
+        (type-list (specifier-type 'list))
+         (type-cons (specifier-type 'cons))
+        (mtype (find-if #'member-type-p types))
+         (members (when mtype (member-type-members mtype))))
+    (if (and mtype
+             (memq nil members)
+             (memq type-cons types))
+       (once-only ((n-obj object))
+          `(or (listp ,n-obj)
+               (typep ,n-obj
+                      '(or ,@(mapcar #'type-specifier
+                                     (remove type-cons
+                                             (remove mtype types)))
+                        (member ,@(remove nil members))))))
        (once-only ((n-obj object))
          `(or ,@(mapcar (lambda (x)
                           `(typep ,n-obj ',(type-specifier x)))
 (defun source-transform-cons-typep (object type)
   (let* ((car-type (cons-type-car-type type))
         (cdr-type (cons-type-cdr-type type)))
-    (let ((car-test-p (not (or (type= car-type *wild-type*)
-                              (type= car-type (specifier-type t)))))
-         (cdr-test-p (not (or (type= cdr-type *wild-type*)
-                              (type= cdr-type (specifier-type t))))))
+    (let ((car-test-p (not (type= car-type *universal-type*)))
+         (cdr-test-p (not (type= cdr-type *universal-type*))))
       (if (and (not car-test-p) (not cdr-test-p))
          `(consp ,object)
          (once-only ((n-obj object))
             ((csubtypep tspec (specifier-type 'float))
              '(%single-float x))
             ((and (csubtypep tspec (specifier-type 'simple-vector))
-                  (policy node (< safety 3)))
+                  ;; Can we avoid checking for dimension issues like
+                  ;; (COERCE FOO '(SIMPLE-VECTOR 5)) returning a
+                  ;; vector of length 6?
+                  (or (policy node (< safety 3)) ; no need in unsafe code
+                      (and (array-type-p tspec) ; no need when no dimensions
+                           (equal (array-type-dimensions tspec) '(*)))))
              `(if (simple-vector-p x)
                   x
                   (replace (make-array (length x)) x)))
             (t
              (give-up-ir1-transform)))))))
 
+