(INTEGERP (CAR (MAKE-SEQUENCE '(CONS INTEGER *) 2)))
can erroneously return T.
-214:
- SBCL 0.6.12.43 fails to compile
-
- (locally
- (declare (optimize (inhibit-warnings 0) (compilation-speed 2)))
- (flet ((foo (&key (x :vx x-p)) (list x x-p)))
- (foo 1 2)))
-
- or a more simple example:
-
- (locally
- (declare (optimize (inhibit-warnings 0) (compilation-speed 2)))
- (lambda (x) (declare (fixnum x)) (if (< x 0) 0 (1- x))))
-
215: ":TEST-NOT handling by functions"
a. FIND and POSITION currently signal errors when given non-NIL for
both their :TEST and (deprecated) :TEST-NOT arguments, but by
The issue seems to be that construction of a discriminating function
calls COMPUTE-EFFECTIVE-METHOD with methods that are not all applicable.
-282: "type checking in full calls"
- In current (0.8.3.6) implementation a CAST in a full call argument
- is not checked; but the continuation between the CAST and the
- combination has the "checked" type and CAST performs unsafe
- coercion; this may lead to errors: if FOO is declared to take a
- FIXNUM, this code will produce garbage on a machine with 30-bit
- fixnums:
-
- (foo (aref (the (array (unsigned-byte 32)) x)))
-
283: Thread safety: libc functions
There are places that we call unsafe-for-threading libc functions
that we should find alternatives for, or put locks around. Known or
the control word; however, this clobbers any change the user might
have made.
-293:
- From Paul Dietz:
-
- (defparameter *f1*
- (compile nil '(LAMBDA (C)
- (TRUNCATE (LOGORC1 -996082 C) -2))))
-
- (defparameter *f2*
- (compile nil '(LAMBDA (C) (DECLARE (NOTINLINE TRUNCATE))
- (TRUNCATE (LOGORC1 -996082 C) -2))))
-
- (print (funcall *f1* 25337234)) ==> 13099002
- (print (funcall *f2* 25337234)) ==> -13099001
-
-294:
- From Paul Dietz:
-
- * (funcall (compile nil `(lambda (c)
- (declare (optimize (speed 3))
- (type (integer 23062188 149459656) c))
- (mod c (min -2 0))))
- 95019853)
-
- debugger invoked on condition of type SB-INT:SIMPLE-PROGRAM-ERROR:
- invalid number of arguments: 1
-
- [...]
-
- * (funcall (compile nil `(lambda (b)
- (declare (optimize (speed 3))
- (type (integer 2 152044363) b))
- (rem b (min -16 0))))
- 108251912)
-
- debugger invoked on condition of type SB-INT:SIMPLE-PROGRAM-ERROR:
- invalid number of arguments: 1
-
295:
From Paul Dietz:
been incremented (because of the changes to internal compiler
data structures referred to above).
+changes in sbcl-0.8.5 relative to sbcl-0.8.4:
+ * in full calls compiler does not generate checks for declared
+ argument types for all arguments.
+ * fix bug 282: compiler does not trust type assertions while passing
+ arguments to a full call.
+ * fix bug 261: compiler allows NIL or "no value" to be accepted for
+ &OPTIONAL VALUES type parameter.
+ * fix bug 214: algorithm for noting rejected templates is now more
+ similar to that of template seletion. (also reported by rydis on
+ #lisp)
+ * fixed some bugs revealed by Paul Dietz' test suite:
+ ** incorrect optimization of TRUNCATE for a positive first
+ argument and negative second.
+ ** compiler failure in let-convertion during flushing dead code.
+ ** compiler failure while deriving type of TRUNCATE on an
+ interval, containing 0.
+
planned incompatible changes in 0.8.x:
* (not done yet, but planned:) When the profiling interface settles
down, it might impact TRACE. They both encapsulate functions, and
;;; templates in the VM definition.
(defun type-test-cost (type)
(declare (type ctype type))
- (or (let ((check (type-check-template type)))
+ (or (when (eq type *universal-type*)
+ 0)
+ (when (eq type *empty-type*)
+ 0)
+ (let ((check (type-check-template type)))
(if check
(template-cost check)
(let ((found (cdr (assoc type *backend-type-predicates*
;;; FIXME: I don't quite understand this, but it looks as though
;;; that means type checks are weakened when SPEED=3 regardless of
;;; the SAFETY level, which is not the right thing to do.
-(defun maybe-negate-check (lvar types original-types force-hairy)
- (declare (type lvar lvar) (list types))
- (multiple-value-bind (ptypes count)
- (no-fun-values-types (lvar-derived-type lvar))
- (if (eq count :unknown)
- (if (and (every #'type-check-template types) (not force-hairy))
- (values :simple types)
- (values :hairy (mapcar (lambda (x) (list nil x x)) types)))
- (let ((res (mapcar (lambda (p c a)
- (let ((diff (type-difference p c)))
- (if (and diff
- (< (type-test-cost diff)
- (type-test-cost c))
- *complement-type-checks*)
- (list t diff a)
- (list nil c a))))
- ptypes types original-types)))
- (cond ((or force-hairy (find-if #'first res))
- (values :hairy res))
- ((every #'type-check-template types)
- (values :simple types))
- (t
- (values :hairy res)))))))
+(defun maybe-negate-check (lvar types original-types force-hairy n-required)
+ (declare (type lvar lvar) (list types original-types))
+ (let ((ptypes (values-type-out (lvar-derived-type lvar) (length types))))
+ (multiple-value-bind (hairy-res simple-res)
+ (loop for p in ptypes
+ and c in types
+ and a in original-types
+ and i from 0
+ for cc = (if (>= i n-required)
+ (type-union c (specifier-type 'null))
+ c)
+ for diff = (type-difference p cc)
+ collect (if (and diff
+ (< (type-test-cost diff)
+ (type-test-cost cc))
+ *complement-type-checks*)
+ (list t diff a)
+ (list nil cc a))
+ into hairy-res
+ collect cc into simple-res
+ finally (return (values hairy-res simple-res)))
+ (cond ((or force-hairy (find-if #'first hairy-res))
+ (values :hairy hairy-res))
+ ((every #'type-check-template simple-res)
+ (values :simple simple-res))
+ (t
+ (values :hairy hairy-res))))))
;;; Determines whether CAST's assertion is:
;;; -- checkable by the back end (:SIMPLE), or
;;; test in type check conversion (:HAIRY), or
;;; -- not reasonably checkable at all (:TOO-HAIRY).
;;;
-;;; A type is checkable if it either represents a fixed number of
-;;; values (as determined by VALUES-TYPES), or it is the assertion for
-;;; an MV-BIND. A type is simply checkable if all the type assertions
-;;; have a TYPE-CHECK-TEMPLATE. In this :SIMPLE case, the second value
-;;; is a list of the type restrictions specified for the leading
-;;; positional values.
+;;; We may check only fixed number of values; in any case the number
+;;; of generated values is trusted. If we know the number of produced
+;;; values, all of them are checked; otherwise if we know the number
+;;; of consumed -- only they are checked; otherwise the check is not
+;;; performed.
;;;
-;;; We force a check to be hairy even when there are fixed values if
-;;; we are in a context where we may be forced to use the unknown
-;;; values convention anyway. This is because IR2tran can't generate
-;;; type checks for unknown values lvars but people could still be
-;;; depending on the check being done. We only care about EXIT and
-;;; RETURN (not MV-COMBINATION) since these are the only contexts
-;;; where the ultimate values receiver
+;;; A type is simply checkable if all the type assertions have a
+;;; TYPE-CHECK-TEMPLATE. In this :SIMPLE case, the second value is a
+;;; list of the type restrictions specified for the leading positional
+;;; values.
+;;;
+;;; Old comment:
+;;;
+;;; We force a check to be hairy even when there are fixed values
+;;; if we are in a context where we may be forced to use the
+;;; unknown values convention anyway. This is because IR2tran can't
+;;; generate type checks for unknown values lvars but people could
+;;; still be depending on the check being done. We only care about
+;;; EXIT and RETURN (not MV-COMBINATION) since these are the only
+;;; contexts where the ultimate values receiver
;;;
;;; In the :HAIRY case, the second value is a list of triples of
;;; the form:
(declare (type cast cast))
(let* ((ctype (coerce-to-values (cast-type-to-check cast)))
(atype (coerce-to-values (cast-asserted-type cast)))
+ (dtype (node-derived-type cast))
(value (cast-value cast))
- (vtype (lvar-derived-type value))
(lvar (node-lvar cast))
- (dest (and lvar (lvar-dest lvar))))
+ (dest (and lvar (lvar-dest lvar)))
+ (n-consumed (cond ((not lvar)
+ nil)
+ ((lvar-single-value-p lvar)
+ 1)
+ ((and (mv-combination-p dest)
+ (eq (mv-combination-kind dest) :local))
+ (let ((fun-ref (lvar-use (mv-combination-fun dest))))
+ (length (lambda-vars (ref-leaf fun-ref)))))))
+ (n-required (length (values-type-required dtype))))
(aver (not (eq ctype *wild-type*)))
- (multiple-value-bind (ctypes count) (no-fun-values-types ctype)
- (multiple-value-bind (atypes acount) (no-fun-values-types atype)
- (multiple-value-bind (vtypes vcount) (values-types vtype)
- (declare (ignore vtypes))
- (aver (eq count acount))
- (cond ((not (eq count :unknown))
- (if (or (exit-p dest)
- (and (return-p dest)
- (multiple-value-bind (ignore count)
- (values-types (return-result-type dest))
- (declare (ignore ignore))
- (eq count :unknown))))
- (maybe-negate-check value ctypes atypes t)
- (maybe-negate-check value ctypes atypes force-hairy)))
- ((and (lvar-single-value-p lvar)
- (or (not (args-type-rest ctype))
- (eq (args-type-rest ctype) *universal-type*)))
- (principal-lvar-single-valuify lvar)
- (let ((creq (car (args-type-required ctype))))
- (multiple-value-setq (ctype atype)
- (if creq
- (values creq (car (args-type-required atype)))
- (values (car (args-type-optional ctype))
- (car (args-type-optional atype)))))
- (maybe-negate-check value
- (list ctype) (list atype)
- force-hairy)))
- ((and (mv-combination-p dest)
- (eq (mv-combination-kind dest) :local))
- (let* ((fun-ref (lvar-use (mv-combination-fun dest)))
- (length (length (lambda-vars (ref-leaf fun-ref)))))
- (maybe-negate-check value
- ;; FIXME
- (adjust-list (values-type-types ctype)
- length
- *universal-type*)
- (adjust-list (values-type-types atype)
- length
- *universal-type*)
- force-hairy)))
- ((not (eq vcount :unknown))
- (maybe-negate-check value
- (values-type-out ctype vcount)
- (values-type-out atype vcount)
- t))
- (t
- (values :too-hairy nil))))))))
+ (cond ((and (null (values-type-optional dtype))
+ (not (values-type-rest dtype)))
+ ;; we [almost] know how many values are produced
+ (maybe-negate-check value
+ (values-type-out ctype n-required)
+ (values-type-out atype n-required)
+ ;; backend checks only consumed values
+ (not (eql n-required n-consumed))
+ n-required))
+ ((lvar-single-value-p lvar)
+ ;; exactly one value is consumed
+ (principal-lvar-single-valuify lvar)
+ (let ((creq (car (args-type-required ctype))))
+ (multiple-value-setq (ctype atype)
+ (if creq
+ (values creq (car (args-type-required atype)))
+ (values (car (args-type-optional ctype))
+ (car (args-type-optional atype)))))
+ (maybe-negate-check value
+ (list ctype) (list atype)
+ force-hairy
+ n-required)))
+ ((and (mv-combination-p dest)
+ (eq (mv-combination-kind dest) :local))
+ ;; we know the number of consumed values
+ (maybe-negate-check value
+ (adjust-list (values-type-types ctype)
+ n-consumed
+ *universal-type*)
+ (adjust-list (values-type-types atype)
+ n-consumed
+ *universal-type*)
+ force-hairy
+ n-required))
+ (t
+ (values :too-hairy nil)))))
;;; Do we want to do a type check?
-(defun worth-type-check-p (cast)
+(defun cast-externally-checkable-p (cast)
(declare (type cast cast))
(let* ((lvar (node-lvar cast))
(dest (and lvar (lvar-dest lvar))))
- (cond ((not (cast-type-check cast))
- nil)
- ((and (combination-p dest)
- (call-full-like-p dest)
- ;; The theory is that the type assertion is
- ;; from a declaration in (or on) the callee,
- ;; so the callee should be able to do the
- ;; check. We want to let the callee do the
- ;; check, because it is possible that by the
- ;; time of call that declaration will be
- ;; changed and we do not want to make people
- ;; recompile all calls to a function when they
- ;; were originally compiled with a bad
- ;; declaration. (See also bug 35.)
- (immediately-used-p lvar cast)
- (values-subtypep (lvar-externally-checkable-type lvar)
- (cast-type-to-check cast)))
- nil)
- (t
- t))))
+ (and (combination-p dest)
+ ;; The theory is that the type assertion is from a
+ ;; declaration in (or on) the callee, so the callee should be
+ ;; able to do the check. We want to let the callee do the
+ ;; check, because it is possible that by the time of call
+ ;; that declaration will be changed and we do not want to
+ ;; make people recompile all calls to a function when they
+ ;; were originally compiled with a bad declaration. (See also
+ ;; bug 35.)
+ (or (immediately-used-p lvar cast)
+ (binding* ((ctran (node-next cast) :exit-if-null)
+ (next (ctran-next ctran)))
+ (and (cast-p next)
+ (eq (node-dest next) dest)
+ (eq (cast-type-check next) :external))))
+ (values-subtypep (lvar-externally-checkable-type lvar)
+ (cast-type-to-check cast)))))
;;; Return true if CAST's value is an lvar whose type the back end is
;;; likely to want to check. Since we don't know what template the
(collect ((casts))
(do-blocks (block component)
(when (block-type-check block)
- (do-nodes (node nil block)
+ ;; CAST-EXTERNALLY-CHECKABLE-P wants the backward pass
+ (do-nodes-backwards (node nil block)
(when (and (cast-p node)
(cast-type-check node))
(cast-check-uses node)
- (cond ((worth-type-check-p node)
- (casts (cons node (not (probable-type-check-p node)))))
+ (cond ((cast-externally-checkable-p node)
+ (setf (cast-%type-check node) :external))
(t
- (setf (cast-%type-check node) nil)
- (setf (cast-type-to-check node) *wild-type*)))))
+ ;; it is possible that NODE was marked :EXTERNAL by
+ ;; the previous pass
+ (setf (cast-%type-check node) t)
+ (casts (cons node (not (probable-type-check-p node))))))))
(setf (block-type-check block) nil)))
(dolist (cast (casts))
(destructuring-bind (cast . force-hairy) cast
(do ((ctran (block-start block) (node-next (ctran-next ctran))))
((not ctran))
(let ((node (ctran-next ctran)))
- (format t "~:[ ~;~:*~3D:~] "
+ (format t "~3D>~:[ ~;~:*~3D:~] "
+ (cont-num ctran)
(when (and (valued-node-p node) (node-lvar node))
(cont-num (node-lvar node))))
(etypecase node
(setq atype (note-fun-use dest atype)))))
(setf (info :function :assumed-type name) atype))))
+;;; Merge CASTs with preceding/following nodes.
+(defun ir1-merge-casts (component)
+ (do-blocks-backwards (block component)
+ (do-nodes-backwards (node lvar block)
+ (let ((dest (when lvar (lvar-dest lvar))))
+ (cond ((and (cast-p dest)
+ (not (cast-type-check dest))
+ (immediately-used-p lvar node))
+ (derive-node-type node (cast-asserted-type dest)))
+ ((and (cast-p node)
+ (eq (cast-type-check node) :external))
+ (aver (basic-combination-p dest))
+ (delete-filter node lvar (cast-value node))))))))
+
;;; Do miscellaneous things that we want to do once all optimization
;;; has been done:
;;; -- Record the derived result type before the back-end trashes the
(maphash (lambda (k v)
(note-assumed-types component k v))
*free-funs*)
+
+ (ir1-merge-casts component)
+
(values))
;; LET-converted functionals are even worse.
(eql (functional-kind functional) :deleted)))
(throw 'locall-already-let-converted functional)))
+
+(defun call-full-like-p (call)
+ (declare (type combination call))
+ (let ((kind (basic-combination-kind call)))
+ (or (eq kind :full)
+ (and (fun-info-p kind)
+ (not (fun-info-ir2-convert kind))
+ (dolist (template (fun-info-templates kind) t)
+ (when (eq (template-ltn-policy template) :fast-safe)
+ (multiple-value-bind (val win)
+ (valid-fun-use call (template-type template))
+ (when (or val (not win)) (return nil)))))))))
\f
;;;; careful call
(when (and (or (not guard) (funcall guard))
(or (not safe-p)
(ltn-policy-safe-p (template-ltn-policy try)))
+ ;; :SAFE is also considered to be :SMALL-SAFE,
+ ;; while the template cost describes time cost;
+ ;; so the fact that (< (t-cost try) (t-cost
+ ;; template)) does not mean that TRY is better
+ (not (and (eq ltn-policy :safe)
+ (eq (template-ltn-policy try) :fast-safe)))
(or verbose-p
(and (template-note try)
(valid-fun-use
(ctran-next ctran))
(ctran (node-next node) (node-next node)))
(nil)
- (let* ((lvar (when (valued-node-p node)
- (node-lvar node)))
- (dest (and lvar (lvar-dest lvar))))
- (when (and (cast-p dest)
- (not (cast-type-check dest))
- (immediately-used-p lvar node))
- (derive-node-type node (cast-asserted-type dest))))
(etypecase node
(ref)
(combination
`((when (block-delete-p ,n-block)
(return)))))))
-;;; like DO-NODES, only iterating in reverse order
+;;; Like DO-NODES, only iterating in reverse order. Should be careful
+;;; with block being split under us.
(defmacro do-nodes-backwards ((node-var lvar block) &body body)
(let ((n-block (gensym))
- (n-start (gensym))
(n-prev (gensym)))
- `(do* ((,n-block ,block)
- (,n-start (block-start ,n-block))
- (,node-var (block-last ,n-block) (ctran-use ,n-prev))
- (,n-prev (node-prev ,node-var) (node-prev ,node-var))
- (,lvar #1=(when (valued-node-p ,node-var) (node-lvar ,node-var))
- #1#))
- (nil)
- ,@body
- (when (eq ,n-prev ,n-start)
- (return nil)))))
+ `(loop with ,n-block = ,block
+ for ,node-var = (block-last ,n-block) then (ctran-use ,n-prev)
+ while ,node-var ; FIXME: this is non-ANSI
+ for ,n-prev = (node-prev ,node-var)
+ and ,lvar = (when (valued-node-p ,node-var) (node-lvar ,node-var))
+ do (progn
+ ,@body))))
(defmacro do-nodes-carefully ((node-var block) &body body)
(with-unique-names (n-block n-ctran)
"<deleted>"))
args)))
-(defun call-full-like-p (call)
- (declare (type combination call))
- (let ((kind (basic-combination-kind call)))
- (or (eq kind :full)
- (and (fun-info-p kind)
- (null (fun-info-templates kind))
- (not (fun-info-ir2-convert kind))))))
-
;;; An MV-COMBINATION is to MULTIPLE-VALUE-CALL as a COMBINATION is to
;;; FUNCALL. This is used to implement all the multiple-value
;;; receiving forms.
;; NIL
;; No type check is necessary (VALUE type is a subtype of the TYPE-TO-CHECK.)
;;
+ ;; :EXTERNAL
+ ;; Type check will be performed by NODE-DEST.
+ ;;
;; T
;; A type check is needed.
- (%type-check t :type (member t nil))
+ (%type-check t :type (member t :external nil))
;; the lvar which is checked
(value (missing-arg) :type lvar))
(defprinter (cast :identity t)
;;; a utility for defining derive-type methods of integer operations. If
;;; 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.
+;;; 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)
;;; simple utility to flatten a list
(defun flatten-list (x)
- (labels ((flatten-helper (x r);; 'r' is the stuff to the 'right'.
- (cond ((null x) r)
- ((atom x)
- (cons x r))
- (t (flatten-helper (car x)
- (flatten-helper (cdr x) r))))))
- (flatten-helper x nil)))
+ (labels ((flatten-and-append (tree list)
+ (cond ((null tree) list)
+ ((atom tree) (cons tree list))
+ (t (flatten-and-append
+ (car tree) (flatten-and-append (cdr tree) list))))))
+ (flatten-and-append x nil)))
;;; Take some type of lvar and massage it so that we get a list of the
;;; constituent types. If ARG is *EMPTY-TYPE*, return NIL to indicate
(cond ((and (member-type-p x) (member-type-p y))
(let* ((x (first (member-type-members x)))
(y (first (member-type-members y)))
- (result (with-float-traps-masked
- (:underflow :overflow :divide-by-zero
- :invalid)
- (funcall fun x y))))
- (cond ((null result))
+ (result (ignore-errors
+ (with-float-traps-masked
+ (:underflow :overflow :divide-by-zero
+ :invalid)
+ (funcall fun x y)))))
+ (cond ((null result) *empty-type*)
((and (floatp result) (float-nan-p result))
(make-numeric-type :class 'float
:format (type-of result)
`(- (ash (- x) ,shift)))
(- (logand (- x) ,mask)))
(values ,(if (minusp y)
- `(- (ash (- x) ,shift))
+ `(ash (- ,mask x) ,shift)
`(ash x ,shift))
(logand x ,mask))))))
;;; (CEILING x 2^k) was optimized incorrectly
(loop for divisor in '(-4 4)
- for ceiler = (compile nil `(lambda (x)
- (declare (fixnum x))
- (declare (optimize (speed 3)))
- (ceiling x ,divisor)))
- do (loop for i from -5 to 5
- for exact-q = (/ i divisor)
- do (multiple-value-bind (q r)
- (funcall ceiler i)
- (assert (= (+ (* q divisor) r) i))
- (assert (<= exact-q q))
- (assert (< q (1+ exact-q))))))
+ for ceiler = (compile nil `(lambda (x)
+ (declare (fixnum x))
+ (declare (optimize (speed 3)))
+ (ceiling x ,divisor)))
+ do (loop for i from -5 to 5
+ for exact-q = (/ i divisor)
+ do (multiple-value-bind (q r)
+ (funcall ceiler i)
+ (assert (= (+ (* q divisor) r) i))
+ (assert (<= exact-q q))
+ (assert (< q (1+ exact-q))))))
+
+;;; (TRUNCATE x 2^k) was optimized incorrectly
+(loop for divisor in '(-4 4)
+ for truncater = (compile nil `(lambda (x)
+ (declare (fixnum x))
+ (declare (optimize (speed 3)))
+ (truncate x ,divisor)))
+ do (loop for i from -9 to 9
+ for exact-q = (/ i divisor)
+ do (multiple-value-bind (q r)
+ (funcall truncater i)
+ (assert (= (+ (* q divisor) r) i))
+ (assert (<= (abs q) (abs exact-q)))
+ (assert (< (abs exact-q) (1+ (abs q)))))))
;;; CEILING had a corner case, spotted by Paul Dietz
(assert (= (ceiling most-negative-fixnum (1+ most-positive-fixnum)) -1))
(stub avecname))
(paip avecname)))))
:eexpr (lambda (south east))))
+(in-package :cl-user)
(delete-package :bug254)
;;; bug 255
(multiple-value-prog1
(progn (%pu avecname))
(frob)))))))
+(in-package :cl-user)
(delete-package :bug255)
;;; bug 148
(assert (equal (eval '(bug148-4 '(1 2 3)))
'((1 2 3) (7 14 21) (21 14 7))))
+(in-package :cl-user)
(delete-package :bug148)
;;; bug 258
(assert (equal (u-b-sra '(4 9 7))
'((4 9 7) (3 8 6) (6 8 3))))
-(delete-package :bug258)
-
(in-package :cl-user)
+(delete-package :bug258)
;;;
(defun bug233a (x)
(deposit-field (%f2) (byte 11 8) -3)
c)))
+;;; bug 214: compiler failure
+(defun bug214a1 ()
+ (declare (optimize (sb-ext:inhibit-warnings 0) (compilation-speed 2)))
+ (flet ((foo (&key (x :vx x-p)) (list x x-p)))
+ (foo :x 2)))
+
+(defun bug214a2 ()
+ (declare (optimize (sb-ext:inhibit-warnings 0) (compilation-speed 2)))
+ (lambda (x) (declare (fixnum x)) (if (< x 0) 0 (1- x))))
+
+;;; this one was reported by rydis on #lisp
+(defun 214b (n)
+ (declare (fixnum n))
+ (declare (optimize (speed 2) (space 3)))
+ (dotimes (k n)
+ (princ k)))
+
\f
(sb-ext:quit :unix-status 104)
;;; Verify type checking policy in full calls: the callee is supposed
;;; to perform check, but the results should not be used before the
;;; check will be actually performed.
-#+nil
(locally
(declare (optimize (safety 3)))
(flet ((bar (f a)
(+ 359749 35728422))))
-24076)))
+;;; bug 294 reported by Paul Dietz: miscompilation of REM and MOD
+(assert (= (funcall (compile nil `(lambda (b)
+ (declare (optimize (speed 3))
+ (type (integer 2 152044363) b))
+ (rem b (min -16 0))))
+ 108251912)
+ 8))
+
+(assert (= (funcall (compile nil `(lambda (c)
+ (declare (optimize (speed 3))
+ (type (integer 23062188 149459656) c))
+ (mod c (min -2 0))))
+ 95019853)
+ -1))
+
+;;; bug reported by Paul Dietz: block splitting inside FLUSH-DEAD-CODE
+(compile nil
+ '(LAMBDA (A B C)
+ (BLOCK B6
+ (LOGEQV (REM C -6758)
+ (REM B (MAX 44 (RETURN-FROM B6 A)))))))
+
+(compile nil '(lambda ()
+ (block nil
+ (flet ((foo (x y) (if (> x y) (print x) (print y))))
+ (foo 1 2)
+ (bar)
+ (foo (return 14) 2)))))
+
;;; bug in Alpha backend: not enough sanity checking of arguments to
;;; instructions
(assert (= (funcall (compile nil
;;; 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.4.1"
+"0.8.4.2"