0.7.7.35:
authorAlexey Dejneka <adejneka@comail.ru>
Sat, 21 Sep 2002 10:24:08 +0000 (10:24 +0000)
committerAlexey Dejneka <adejneka@comail.ru>
Sat, 21 Sep 2002 10:24:08 +0000 (10:24 +0000)
        New ir1 attribute: UNSAFELY-FLUSHABLE. Functions, which must
        signal errors, are no longer (UNSAFELY-)FLUSHABLE. Those,
        which signal errors in safe mode code, are UNSAFELY-FLUSHABLE.

NEWS
src/compiler/fndb.lisp
src/compiler/ir1opt.lisp
src/compiler/ir1util.lisp
src/compiler/knownfun.lisp
src/compiler/macros.lisp
tests/compiler.pure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index f8da51f..64a04a7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1277,6 +1277,7 @@ changes in sbcl-0.7.8 relative to sbcl-0.7.7:
     in several ways. (thanks to Alexey Dejneka)
   * fixed bug 181: compiler checks validity of user supplied type
     specifiers
+  * functions, which must signal errors, are no longer flushable
 
 planned incompatible changes in 0.7.x:
 * When the profiling interface settles down, maybe in 0.7.x, maybe
index 64e584a..6614a44 100644 (file)
@@ -48,7 +48,7 @@
 ;;; These can be affected by type definitions, so they're not FOLDABLE.
 (defknown (upgraded-complex-part-type upgraded-array-element-type)
          (type-specifier) type-specifier
-  (flushable))
+  (unsafely-flushable))
 \f
 ;;;; from the "Predicates" chapter:
 
@@ -59,7 +59,6 @@
 ;;; this property should be protected by #-SB-XC-HOST? Perhaps we need
 ;;; 3-stage bootstrapping after all? (Ugh! It's *so* slow already!)
 (defknown typep (t type-specifier) t
-  (flushable
    ;; Unlike SUBTYPEP or UPGRADED-ARRAY-ELEMENT-TYPE and friends, this
    ;; seems to be FOLDABLE. Like SUBTYPEP, it's affected by type
    ;; definitions, but unlike SUBTYPEP, there should be no way to make
    ;;
    ;; (UPGRADED-ARRAY-ELEMENT-TYPE and UPGRADED-COMPLEX-PART-TYPE have
    ;; behavior like SUBTYPEP in this respect, not like TYPEP.)
-   foldable))
-(defknown subtypep (type-specifier type-specifier) (values boolean boolean) 
+   (foldable))
+(defknown subtypep (type-specifier type-specifier) (values boolean boolean)
   ;; This is not FOLDABLE because its value is affected by type
   ;; definitions.
   ;;
   ;; FIXME: Is it OK to fold this when the types have already been
   ;; defined? Does the code inherited from CMU CL already do this?
-  (flushable)) 
+  (unsafely-flushable))
 
 (defknown (null symbolp atom consp listp numberp integerp rationalp floatp
                complexp characterp stringp bit-vector-p vectorp
 (defknown (symbol-value symbol-function) (symbol) t ())
 
 (defknown boundp (symbol) boolean (flushable))
-(defknown fboundp ((or symbol cons)) boolean (flushable explicit-check))
+(defknown fboundp ((or symbol cons)) boolean (unsafely-flushable explicit-check))
 (defknown special-operator-p (symbol) t
   ;; The set of special operators never changes.
-  (movable foldable flushable)) 
+  (movable foldable flushable))
 (defknown set (symbol t) t (unsafe)
   :derive-type #'result-type-last-arg)
 (defknown fdefinition ((or symbol cons)) function (unsafe explicit-check))
 ;;; it into VALUES. VALUES is not foldable, since MV constants are
 ;;; represented by a call to VALUES.
 (defknown values (&rest t) * (movable flushable unsafe))
-(defknown values-list (list) * (movable foldable flushable))
+(defknown values-list (list) * (movable foldable unsafely-flushable))
 \f
 ;;;; from the "Macros" chapter:
 
 (defknown find-package (package-designator) (or sb!xc:package null)
   (flushable))
 (defknown package-name (package-designator) (or simple-string null)
-  (flushable))
-(defknown package-nicknames (package-designator) list (flushable))
+  (unsafely-flushable))
+(defknown package-nicknames (package-designator) list (unsafely-flushable))
 (defknown rename-package (package-designator package-designator &optional list)
   sb!xc:package)
-(defknown package-use-list (package-designator) list (flushable))
-(defknown package-used-by-list (package-designator) list (flushable))
-(defknown package-shadowing-symbols (package-designator) list (flushable))
+(defknown package-use-list (package-designator) list (unsafely-flushable))
+(defknown package-used-by-list (package-designator) list (unsafely-flushable))
+(defknown package-shadowing-symbols (package-designator) list (unsafely-flushable))
 (defknown list-all-packages () list (flushable))
 (defknown intern (string &optional package-designator)
   (values symbol (member :internal :external :inherited nil))
 
 (defknown atan
   (number &optional real) irrational
-  (movable foldable flushable explicit-check recursive)
+  (movable foldable unsafely-flushable explicit-check recursive)
   :derive-type #'result-type-float-contagion)
 
 (defknown (tan sinh cosh tanh asinh)
 
 (defknown atan
   (number &optional real) irrational
-  (movable foldable flushable explicit-check recursive))
+  (movable foldable unsafely-flushable explicit-check recursive))
 
 (defknown (tan sinh cosh tanh asinh)
   (number) irrational (movable foldable flushable explicit-check recursive))
                 char-lessp char-greaterp char-not-greaterp char-not-lessp)
   (character &rest character) boolean (movable foldable flushable))
 
-(defknown character (t) character (movable foldable flushable))
+(defknown character (t) character (movable foldable unsafely-flushable))
 (defknown char-code (character) char-code (movable foldable flushable))
 (defknown (char-upcase char-downcase) (character) character
   (movable foldable flushable))
 \f
 ;;;; from the "Sequences" chapter:
 
-(defknown elt (sequence index) t (foldable flushable))
+(defknown elt (sequence index) t (foldable unsafely-flushable))
 
 (defknown subseq (sequence index &optional sequence-end) consed-sequence
   (flushable)
                                        &key
                                        (:initial-element t))
   consed-sequence
-  (movable flushable unsafe)
+  (movable unsafe)
   :derive-type (result-type-specifier-nth-arg 1))
 
 (defknown concatenate (type-specifier &rest sequence) consed-sequence
-  (flushable)
+  ()
   :derive-type (result-type-specifier-nth-arg 1))
 
 (defknown (map %map) (type-specifier callable sequence &rest sequence)
   consed-sequence
-  (flushable call)
+  (call)
 ; :DERIVE-TYPE 'TYPE-SPEC-ARG1 ? Nope... (MAP NIL ...) returns NULL, not NIL.
   )
 (defknown %map-to-list-arity-1 (callable sequence) list (flushable call))
 
 ;;; returns the result from the predicate...
 (defknown some (callable sequence &rest sequence) t
-  (foldable flushable call))
+  (foldable unsafely-flushable call))
 
 (defknown (every notany notevery) (callable sequence &rest sequence) boolean
-  (foldable flushable call))
+  (foldable unsafely-flushable call))
 
 ;;; unsafe for :INITIAL-VALUE...
 (defknown reduce (callable
   (sequence &key (:test callable) (:test-not callable) (:start index)
            (:from-end t) (:end sequence-end) (:key callable))
   consed-sequence
-  (flushable call)
+  (unsafely-flushable call)
   :derive-type (sequence-result-nth-arg 1))
 
 (defknown delete-duplicates
   (sequence &key (:test callable) (:test-not callable) (:start index)
            (:from-end t) (:end sequence-end) (:key callable))
   sequence
-  (flushable call)
+  (unsafely-flushable call)
   :derive-type (sequence-result-nth-arg 1))
 
 (defknown find (t sequence &key (:test callable) (:test-not callable)
 (defknown merge (type-specifier sequence sequence callable
                                &key (:key callable))
   sequence
-  (flushable call)
+  (call)
   :derive-type (result-type-specifier-nth-arg 1))
 
 ;;; not FLUSHABLE, despite what CMU CL's DEFKNOWN said..
   :derive-type (sequence-result-nth-arg 1))
 \f
 ;;;; from the "Manipulating List Structure" chapter:
-(defknown (car cdr caar cadr cdar cddr
-              caaar caadr cadar caddr cdaar cdadr cddar cdddr
-              caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
-              cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
-              first second third fourth fifth sixth seventh eighth ninth tenth
-              rest)
+(defknown (car cdr first rest)
   (list)
   t
   (foldable flushable))
 
+(defknown (caar cadr cdar cddr
+                caaar caadr cadar caddr cdaar cdadr cddar cdddr
+                caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
+                cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
+                second third fourth fifth sixth seventh eighth ninth tenth)
+  (list)
+  t
+  (foldable unsafely-flushable))
+
 (defknown cons (t t) cons (movable flushable unsafe))
 
 (defknown tree-equal (t t &key (:test callable) (:test-not callable)) boolean
   (foldable flushable call))
-(defknown endp (t) boolean (foldable flushable movable))
-(defknown list-length (list) (or index null) (foldable flushable))
-(defknown (nth nthcdr) (index list) t (foldable flushable))
+(defknown endp (t) boolean (foldable unsafely-flushable movable))
+(defknown list-length (list) (or index null) (foldable unsafely-flushable))
+(defknown nth (index list) t (foldable flushable))
+(defknown nthcdr (index list) t (foldable unsafely-flushable))
 (defknown last (list &optional index) list (foldable flushable))
 (defknown list (&rest t) list (movable flushable unsafe))
 (defknown list* (t &rest t) t (movable flushable unsafe))
 
 (defknown array-has-fill-pointer-p (array) boolean
   (movable foldable flushable))
-(defknown fill-pointer (vector) index (foldable flushable))
+(defknown fill-pointer (vector) index (foldable unsafely-flushable))
 (defknown vector-push (t vector) (or index null) ())
 (defknown vector-push-extend (t vector &optional index) index ())
 (defknown vector-pop (vector) t ())
 ;;;; from the "Streams" chapter:
 
 (defknown make-synonym-stream (symbol) stream (flushable))
-(defknown make-broadcast-stream (&rest stream) stream (flushable))
-(defknown make-concatenated-stream (&rest stream) stream (flushable))
-(defknown make-two-way-stream (stream stream) stream (flushable))
+(defknown make-broadcast-stream (&rest stream) stream (unsafely-flushable))
+(defknown make-concatenated-stream (&rest stream) stream (unsafely-flushable))
+(defknown make-two-way-stream (stream stream) stream (unsafely-flushable))
 (defknown make-echo-stream (stream stream) stream (flushable))
 (defknown make-string-input-stream (string &optional index index) stream
   (flushable unsafe))
 (defknown load-logical-pathname-translations (string) t ())
 (defknown logical-pathname-translations (logical-host-designator) list ())
 
-(defknown pathname (pathname-designator) pathname ())
+(defknown pathname (pathname-designator) pathname (unsafely-flushable))
 (defknown truename (pathname-designator) pathname ())
 
 (defknown parse-namestring
 (defknown merge-pathnames
   (pathname-designator &optional pathname-designator pathname-version)
   pathname
-  ())
+  (unsafely-flushable))
 
 (defknown make-pathname
  (&key (:defaults pathname-designator)
        (:name (or pathname-name string (member :wild)))
        (:type (or pathname-type string (member :wild)))
        (:version pathname-version) (:case (member :local :common)))
-  pathname ())
+  pathname (unsafely-flushable))
 
 (defknown pathnamep (t) boolean (movable flushable))
 
 (defknown pathname-host (pathname-designator
                         &key (:case (member :local :common)))
-  pathname-host ())
+  pathname-host (flushable))
 (defknown pathname-device (pathname-designator
                           &key (:case (member :local :common)))
-  pathname-device ())
+  pathname-device (flushable))
 (defknown pathname-directory (pathname-designator
                              &key (:case (member :local :common)))
-  pathname-directory ())
+  pathname-directory (flushable))
 (defknown pathname-name (pathname-designator
                         &key (:case (member :local :common)))
-  pathname-name ())
+  pathname-name (flushable))
 (defknown pathname-type (pathname-designator
                         &key (:case (member :local :common)))
-  pathname-type ())
+  pathname-type (flushable))
 (defknown pathname-version (pathname-designator)
-  pathname-version ())
+  pathname-version (flushable))
 
 (defknown (namestring file-namestring directory-namestring host-namestring)
   (pathname-designator) simple-string
-  ())
+  (unsafely-flushable))
 
 (defknown enough-namestring (pathname-designator &optional pathname-designator)
   simple-string
-  ())
+  (unsafely-flushable))
 
 (defknown user-homedir-pathname (&optional t) pathname (flushable))
 
 (defknown file-position (stream &optional
                                (or unsigned-byte (member :start :end)))
   (or unsigned-byte (member t nil)))
-(defknown file-length (stream) (or unsigned-byte null) (flushable))
+(defknown file-length (stream) (or unsigned-byte null) (unsafely-flushable))
 
 (defknown load
   ((or filename stream)
index edd5cc4..98f4d9b 100644 (file)
         (let ((info (combination-kind node)))
           (when (fun-info-p info)
             (let ((attr (fun-info-attributes info)))
-              (when (and (ir1-attributep attr flushable)
+              (when (and (not (ir1-attributep attr call))
                          ;; ### For now, don't delete potentially
                          ;; flushable calls when they have the CALL
                          ;; attribute. Someday we should look at the
                          ;; functional args to determine if they have
                          ;; any side effects.
-                         (not (ir1-attributep attr call)))
+                          (if (policy node (= safety 3))
+                              (and (ir1-attributep attr flushable)
+                                   (every (lambda (arg)
+                                            (member (continuation-type-check arg)
+                                                    '(nil :deleted)))
+                                          (basic-combination-args node))
+                                   (valid-fun-use node
+                                                  (info :function :type
+                                                        (leaf-source-name (ref-leaf (continuation-use (basic-combination-fun node)))))
+                                                  :result-test #'always-subtypep
+                                                  :lossage-fun nil
+                                                  :unwinnage-fun nil))
+                              (ir1-attributep attr unsafely-flushable)))
                 (flush-dest (combination-fun node))
                 (dolist (arg (combination-args node))
                   (flush-dest arg))
index 926e183..e6637c1 100644 (file)
                      `(when (eq (,slot last) old)
                         (setf (,slot last) new))))
           (frob if-consequent)
-          (frob if-alternative))))
+          (frob if-alternative)
+           (when (eq (if-consequent last)
+                     (if-alternative last))
+             (setf (component-reoptimize (block-component block)) t)))))
       (t
        (unless (member new (block-succ block) :test #'eq)
         (link-blocks block new)))))
index ea1ec4a..78433e0 100644 (file)
   ;; mark these functions as foldable in this database.
   foldable
   ;; may be eliminated if value is unused. The function has no side
-  ;; effects except possibly CONS. If a function is defined to signal
-  ;; errors, then it is not flushable even if it is movable or
-  ;; foldable.
+  ;; effects except possibly cons. If a function might signal errors,
+  ;; then it is not flushable even if it is movable, foldable or
+  ;; unsafely-flushable. Implies UNSAFELY-FLUSHABLE.
   flushable
+  ;; unsafe call may be eliminated if value is unused. The function
+  ;; has no side effects except possibly cons and signalling an error
+  ;; in the safe code. If a function MUST signal errors, then it is
+  ;; not unsafely-flushable even if it is movable or foldable.
+  unsafely-flushable
   ;; may be moved with impunity. Has no side effects except possibly
   ;; consing, and is affected only by its arguments.
   movable
   ;; The function is a true predicate likely to be open-coded. Convert
-  ;; any non-conditional uses into (IF <pred> T NIL).
+  ;; any non-conditional uses into (IF <pred> T NIL). Not usually
+  ;; specified to DEFKNOWN, since this is implementation dependent,
+  ;; and is usually automatically set by the DEFINE-VOP :CONDITIONAL
+  ;; option.
   predicate
   ;; Inhibit any warning for compiling a recursive definition.
   ;; (Normally the compiler warns when compiling a recursive
index 0a5d134..197ffbe 100644 (file)
 ;;; Declare the function NAME to be a known function. We construct a
 ;;; type specifier for the function by wrapping (FUNCTION ...) around
 ;;; the ARG-TYPES and RESULT-TYPE. ATTRIBUTES is an unevaluated list
-;;; of boolean attributes of the function. These attributes are
-;;; meaningful here:
-;;;
-;;;     CALL
-;;;        May call functions that are passed as arguments. In order
-;;;        to determine what other effects are present, we must find
-;;;        the effects of all arguments that may be functions.
-;;;
-;;;     UNSAFE
-;;;        May incorporate arguments in the result or somehow pass
-;;;        them upward.
-;;;
-;;;     UNWIND
-;;;        May fail to return during correct execution. Errors
-;;;        are O.K.
-;;;
-;;;     ANY
-;;;        The (default) worst case. Includes all the other bad
-;;;        things, plus any other possible bad thing.
-;;;
-;;;     FOLDABLE
-;;;        May be constant-folded. The function has no side effects,
-;;;        but may be affected by side effects on the arguments. E.g.
-;;;        SVREF, MAPC.
-;;;
-;;;     FLUSHABLE
-;;;        May be eliminated if value is unused. The function has
-;;;        no side effects except possibly CONS. If a function is
-;;;        defined to signal errors, then it is not flushable even
-;;;        if it is movable or foldable.
-;;;
-;;;     MOVABLE
-;;;        May be moved with impunity. Has no side effects except
-;;;        possibly CONS, and is affected only by its arguments.
-;;;
-;;;     PREDICATE
-;;;         A true predicate likely to be open-coded. This is a
-;;;         hint to IR1 conversion that it should ensure calls always
-;;;         appear as an IF test. Not usually specified to DEFKNOWN,
-;;;         since this is implementation dependent, and is usually
-;;;         automatically set by the DEFINE-VOP :CONDITIONAL option.
-;;;
-;;; NAME may also be a list of names, in which case the same
-;;; information is given to all the names. The keywords specify the
-;;; initial values for various optimizers that the function might
-;;; have.
+;;; of boolean attributes of the function. See their description in
+;;; (DEF-BOOLEAN-ATTRIBUTE IR1). NAME may also be a list of names, in
+;;; which case the same information is given to all the names. The
+;;; keywords specify the initial values for various optimizers that
+;;; the function might have.
 (defmacro defknown (name arg-types result-type &optional (attributes '(any))
                         &rest keys)
   (when (and (intersection attributes '(any call unwind))
             (intersection attributes '(movable)))
     (error "function cannot have both good and bad attributes: ~S" attributes))
 
+  (when (member 'any attributes)
+    (setf attributes (union '(call unsafe unwind) attributes)))
+  (when (member 'flushable attributes)
+    (pushnew 'unsafely-flushable attributes))
+
   `(%defknown ',(if (and (consp name)
                         (not (eq (car name) 'setf)))
                    name
                    (list name))
              '(function ,arg-types ,result-type)
-             (ir1-attributes ,@(if (member 'any attributes)
-                                   (union '(call unsafe unwind) attributes)
-                                   attributes))
+             (ir1-attributes ,@attributes)
              ,@keys))
 
 ;;; Create a function which parses combination args according to WHAT
index c54e61e..07872ae 100644 (file)
 (let ((f (compile nil '(lambda (x)
                         (make-array 1 :element-type '(0))))))
   (assert (null (ignore-errors (funcall f)))))
+
+;;; the following functions must not be flushable
+(dolist (form '((make-sequence 'fixnum 10)
+                (concatenate 'fixnum nil)
+                (map 'fixnum #'identity nil)
+                (merge 'fixnum nil nil #'<)))
+  (assert (not (eval `(locally (declare (optimize (safety 0)))
+                        (ignore-errors (progn ,form t)))))))
+
+(dolist (form '(#+nil(values-list '(1 . 2)) ; This case still fails
+                (fboundp '(set bet))
+                (atan #c(1 1) (car (list #c(2 2))))
+                (nthcdr (car (list (floor (cos 3)))) '(1 2 3 4 5))
+                (nthcdr (car (list 5)) '(1 2 . 3))))
+  (assert (not (eval `(locally (declare (optimize (safety 3)))
+                        (ignore-errors (progn ,form t)))))))
index a977e77..0488bbc 100644 (file)
@@ -18,4 +18,4 @@
 ;;; internal versions off the main CVS branch, it gets hairier, e.g.
 ;;; "0.pre7.14.flaky4.13".)
 
-"0.7.7.34"
+"0.7.7.35"