X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=tests%2Fcompiler.pure.lisp;h=755547f57eca889b5295f97d0bc66a74e809d3ee;hb=646a14a9099c3c6bbb60ff09f7fb6a781a030815;hp=bd1ed4706214cba19b761d3c27943ce631d58cb7;hpb=a3d84edc295f60e459ec917e8bc1e3d19829381e;p=sbcl.git diff --git a/tests/compiler.pure.lisp b/tests/compiler.pure.lisp index bd1ed47..755547f 100644 --- a/tests/compiler.pure.lisp +++ b/tests/compiler.pure.lisp @@ -11,8 +11,22 @@ ;;;; absolutely no warranty. See the COPYING and CREDITS files for ;;;; more information. +(cl:in-package :sb-c) + +(defknown compiler-derived-type (t) (values t t) (movable flushable unsafe)) + +(deftransform compiler-derived-type ((x)) + `(values ',(type-specifier (lvar-type x)) t)) + +(defun compiler-derived-type (x) + (values t nil)) + (cl:in-package :cl-user) +;; The tests in this file assume that EVAL will use the compiler +(when (eq sb-ext:*evaluator-mode* :interpret) + (invoke-restart 'run-tests::skip-file)) + ;;; Exercise a compiler bug (by crashing the compiler). ;;; ;;; This test code is from Douglas Crosher's simplified TICKLE-BUG @@ -407,11 +421,12 @@ ;;; Moellmann: CONVERT-MORE-CALL failed on the following call (assert (eq (eval '((lambda (&key) 'u) :allow-other-keys nil)) 'u)) -(raises-error? (multiple-value-bind (a b c) - (eval '(truncate 3 4)) - (declare (integer c)) - (list a b c)) - type-error) +(assert + (raises-error? (multiple-value-bind (a b c) + (eval '(truncate 3 4)) + (declare (integer c)) + (list a b c)) + type-error)) (assert (equal (multiple-value-list (the (values &rest integer) (eval '(values 3)))) @@ -523,11 +538,19 @@ (funcall f y 1) (assert (equal y #*10)))) +;;; use of declared array types (handler-bind ((sb-ext:compiler-note #'error)) (compile nil '(lambda (x) - (declare (type (simple-array (simple-string 3) (5)) x)) + (declare (type (simple-array (simple-string 3) (5)) x) + (optimize speed)) (aref (aref x 0) 0)))) +(handler-bind ((sb-ext:compiler-note #'error)) + (compile nil '(lambda (x) + (declare (type (simple-array (simple-array bit (10)) (10)) x) + (optimize speed)) + (1+ (aref (aref x 0) 0))))) + ;;; compiler failure (let ((f (compile nil '(lambda (x) (typep x '(not (member 0d0))))))) (assert (funcall f 1d0))) @@ -769,6 +792,35 @@ (declare (type (integer 4303063 101130078) a)) (mask-field (byte 18 2) (ash a 77)))) 57132532))) +;;; rewrite the test case to get the unsigned-byte 32/64 +;;; implementation even after implementing some modular arithmetic +;;; with signed-byte 30: +(assert (= 0 (funcall + (compile nil + '(lambda (a) + (declare (type (integer 4303063 101130078) a)) + (mask-field (byte 30 2) (ash a 77)))) + 57132532))) +(assert (= 0 (funcall + (compile nil + '(lambda (a) + (declare (type (integer 4303063 101130078) a)) + (mask-field (byte 64 2) (ash a 77)))) + 57132532))) +;;; and a similar test case for the signed masking extension (not the +;;; final interface, so change the call when necessary): +(assert (= 0 (funcall + (compile nil + '(lambda (a) + (declare (type (integer 4303063 101130078) a)) + (sb-c::mask-signed-field 30 (ash a 77)))) + 57132532))) +(assert (= 0 (funcall + (compile nil + '(lambda (a) + (declare (type (integer 4303063 101130078) a)) + (sb-c::mask-signed-field 61 (ash a 77)))) + 57132532))) ;;; MISC.101 and MISC.103: FLUSH-DEST did not mark the USE's block for ;;; type check regeneration @@ -1370,8 +1422,12 @@ (handler-case (compile nil '(lambda (x) (declare (optimize (speed 3) (safety 0))) (the double-float (sqrt (the double-float x))))) - (sb-ext:compiler-note () - (error "Compiler does not trust result type assertion."))) + (sb-ext:compiler-note (c) + ;; Ignore the note for the float -> pointer conversion of the + ;; return value. + (unless (string= (car (last (sb-c::simple-condition-format-arguments c))) + "") + (error "Compiler does not trust result type assertion.")))) (let ((f (compile nil '(lambda (x) (declare (optimize speed (safety 0))) @@ -1896,14 +1952,15 @@ (compile nil '(lambda (x) (declare (optimize (speed 3))) (1+ x)))) - ;; forced-to-do GENERIC-+, etc - (assert (> count0 0)) + ;; forced-to-do GENERIC-+, etc, possible word -> bignum conversion note + (assert (> count0 1)) (handler-bind ((sb-ext:compiler-note (lambda (c) (incf count1)))) (compile nil '(lambda (x) (declare (optimize (speed 3))) (check-type x fixnum) (1+ x)))) - (assert (= count1 0))) + ;; Only the posssible word -> bignum conversion note + (assert (= count1 1))) ;;; Up to 0.9.8.22 x86-64 had broken return value handling in the ;;; %SET-SAP-REF-DOUBLE/SINGLE VOPs. @@ -1937,7 +1994,7 @@ (bit #*1001101001001 (min 12 (max 0 lv3)))))))))))) -;;; MISC.624: erronous AVER in x86's %LOGBITP VOPs +;;; MISC.624: erroneous AVER in x86's %LOGBITP VOPs (assert (eql 0 (funcall (compile @@ -2012,3 +2069,528 @@ (declare (optimize (speed 3))) (1+ x))))) (compiler-note () (error "The code is not optimized."))))) + +(with-test (:name (:compiler :constraint-propagation :float-bounds-1)) + (handler-case + (compile nil '(lambda (x) + (declare (type (single-float * (3.0)) x)) + (when (<= x 2.0) + (when (<= 2.0 x) + x)))) + (compiler-note () (error "Deleted reachable code.")))) + +(with-test (:name (:compiler :constraint-propagation :float-bounds-2)) + (catch :note + (handler-case + (compile nil '(lambda (x) + (declare (type single-float x)) + (when (< 1.0 x) + (when (<= x 1.0) + (error "This is unreachable."))))) + (compiler-note () (throw :note nil))) + (error "Unreachable code undetected."))) + +(with-test (:name (:compiler :constraint-propagation :var-eql-to-var-1)) + (catch :note + (handler-case + (compile nil '(lambda (x y) + (when (typep y 'fixnum) + (when (eql x y) + (unless (typep x 'fixnum) + (error "This is unreachable")) + (setq y nil))))) + (compiler-note () (throw :note nil))) + (error "Unreachable code undetected."))) + +(with-test (:name (:compiler :constraint-propagation :var-eql-to-var-2)) + (catch :note + (handler-case + (compile nil '(lambda (x y) + (when (typep y 'fixnum) + (when (eql y x) + (unless (typep x 'fixnum) + (error "This is unreachable")) + (setq y nil))))) + (compiler-note () (throw :note nil))) + (error "Unreachable code undetected."))) + +;; Reported by John Wiseman, sbcl-devel +;; Subject: [Sbcl-devel] float type derivation bug? +;; Date: Tue, 4 Apr 2006 15:28:15 -0700 +(with-test (:name (:type-derivation :float-bounds)) + (compile nil '(lambda (bits) + (let* ((s (if (= (ash bits -31) 0) 1 -1)) + (e (logand (ash bits -23) #xff)) + (m (if (= e 0) + (ash (logand bits #x7fffff) 1) + (logior (logand bits #x7fffff) #x800000)))) + (float (* s m (expt 2 (- e 150)))))))) + +;; Reported by James Knight +;; Subject: [Sbcl-devel] AVER: "(EQ (SB-NAME (SC-SB (TN-SC TN))) 'REGISTERS)" +;; Date: Fri, 24 Mar 2006 19:30:00 -0500 +(with-test (:name :logbitp-vop) + (compile nil + '(lambda (days shift) + (declare (type fixnum shift days)) + (let* ((result 0) + (canonicalized-shift (+ shift 1)) + (first-wrapping-day (- 1 canonicalized-shift))) + (declare (type fixnum result)) + (dotimes (source-day 7) + (declare (type (integer 0 6) source-day)) + (when (logbitp source-day days) + (setf result + (logior result + (the fixnum + (if (< source-day first-wrapping-day) + (+ source-day canonicalized-shift) + (- (+ source-day + canonicalized-shift) 7))))))) + result)))) + +;;; MISC.637: incorrect delaying of conversion of optional entries +;;; with hairy constant defaults +(let ((f '(lambda () + (labels ((%f11 (f11-2 &key key1) + (labels ((%f8 (f8-2 &optional (f8-5 (if nil (return-from %f11 0) 0))) + :bad1)) + (%f8 (%f8 0))) + :bad2)) + :good)))) + (assert (eq (funcall (compile nil f)) :good))) + +;;; MISC.555: new reference to an already-optimized local function +(let* ((l '(lambda (p1) + (declare (optimize (speed 1) (safety 2) (debug 2) (space 0)) (type keyword p1)) + (keywordp p1))) + (f (compile nil l))) + (assert (funcall f :good)) + (assert (nth-value 1 (ignore-errors (funcall f 42))))) + +;;; Check that the compiler doesn't munge *RANDOM-STATE*. +(let* ((state (make-random-state)) + (*random-state* (make-random-state state)) + (a (random most-positive-fixnum))) + (setf *random-state* state) + (compile nil `(lambda (x a) + (declare (single-float x) + (type (simple-array double-float) a)) + (+ (loop for i across a + summing i) + x))) + (assert (= a (random most-positive-fixnum)))) + +;;; MISC.641: LET-conversion after physical environment analysis lost NLX-INFOs +(let ((form '(lambda () + (declare (optimize (speed 1) (space 0) (debug 2) + (compilation-speed 0) (safety 1))) + (flet ((%f3 (f3-1 &key (key1 (count (floor 0 (min -74 0)) #()))) + 0)) + (apply #'%f3 0 nil))))) + (assert (zerop (funcall (compile nil form))))) + +;;; size mismatch: # disp=1> is a :DWORD and # is a :QWORD. on x86-64 +(compile nil '(lambda () + (let ((x (make-array '(1) :element-type '(signed-byte 32)))) + (setf (aref x 0) 1)))) + +;;; step instrumentation confusing the compiler, reported by Faré +(handler-bind ((warning #'error)) + (compile nil '(lambda () + (declare (optimize (debug 2))) ; not debug 3! + (let ((val "foobar")) + (map-into (make-array (list (length val)) + :element-type '(unsigned-byte 8)) + #'char-code val))))) + +;;; overconfident primitive type computation leading to bogus type +;;; checking. +(let* ((form1 '(lambda (x) + (declare (type (and condition function) x)) + x)) + (fun1 (compile nil form1)) + (form2 '(lambda (x) + (declare (type (and standard-object function) x)) + x)) + (fun2 (compile nil form2))) + (assert (raises-error? (funcall fun1 (make-condition 'error)))) + (assert (raises-error? (funcall fun1 fun1))) + (assert (raises-error? (funcall fun2 fun2))) + (assert (eq (funcall fun2 #'print-object) #'print-object))) + +;;; LET* + VALUES declaration: while the declaration is a non-standard +;;; and possibly a non-conforming extension, as long as we do support +;;; it, we might as well get it right. +;;; +;;; Bug reported by Kaersten Poeck on sbcl-devel 20061023. +(compile nil '(lambda () (let* () (declare (values list))))) + + +;;; test for some problems with too large immediates in x86-64 modular +;;; arithmetic vops +(compile nil '(lambda (x) (declare (fixnum x)) + (logand most-positive-fixnum (logxor x most-positive-fixnum)))) + +(compile nil '(lambda (x) (declare (fixnum x)) + (logand most-positive-fixnum (+ x most-positive-fixnum)))) + +(compile nil '(lambda (x) (declare (fixnum x)) + (logand most-positive-fixnum (* x most-positive-fixnum)))) + +;;; bug 256.b +(assert (let (warned-p) + (handler-bind ((warning (lambda (w) (setf warned-p t)))) + (compile nil + '(lambda (x) + (list (let ((y (the real x))) + (unless (floatp y) (error "")) + y) + (integer-length x))))) + warned-p)) + +;; Dead / in safe code +(with-test (:name :safe-dead-/) + (assert (eq :error + (handler-case + (funcall (compile nil + '(lambda (x y) + (declare (optimize (safety 3))) + (/ x y) + (+ x y))) + 1 + 0) + (division-by-zero () + :error))))) + +;;; Dead unbound variable (bug 412) +(with-test (:name :dead-unbound) + (assert (eq :error + (handler-case + (funcall (compile nil + '(lambda () + #:unbound + 42))) + (unbound-variable () + :error))))) + +;;; No compiler notes from compiling SUBSEQ SIMPLE-VECTOR. +(handler-bind ((sb-ext:compiler-note 'error)) + (assert + (equalp #(2 3) + (funcall (compile nil `(lambda (s p e) + (declare (optimize speed) + (simple-vector s)) + (subseq s p e))) + (vector 1 2 3 4) + 1 + 3)))) + +;;; No compiler notes from compiling COPY-SEQ SIMPLE-VECTOR. +(handler-bind ((sb-ext:compiler-note 'error)) + (assert + (equalp #(1 2 3 4) + (funcall (compile nil `(lambda (s) + (declare (optimize speed) + (simple-vector s)) + (copy-seq s))) + (vector 1 2 3 4))))) + +;;; bug in adding DATA-VECTOR-REF-WITH-OFFSET to x86-64 +(assert (not (mismatch #(1.0f0 2.0f0) (make-array 2 :element-type 'single-float :initial-contents (list 1.0f0 2.0f0))))) + +;;; bug in interval-arithmetic used by the compiler: needless attempt to coerce too +;;; large bignums to floats +(dolist (op '(* / + -)) + (let ((fun (compile + nil + `(lambda (x) + (declare (type (integer 0 #.(* 2 (truncate most-positive-double-float))) x)) + (,op 0.0d0 x))))) + (loop repeat 10 + do (let ((arg (random (truncate most-positive-double-float)))) + (assert (eql (funcall fun arg) + (funcall op 0.0d0 arg))))))) + +(with-test (:name :high-debug-known-function-inlining) + (let ((fun (compile nil + '(lambda () + (declare (optimize (debug 3)) (inline append)) + (let ((fun (lambda (body) + (append + (first body) + nil)))) + (funcall fun + '((foo (bar))))))))) + (funcall fun))) + +(with-test (:name :high-debug-known-function-transform-with-optional-arguments) + (compile nil '(lambda (x y) + (declare (optimize sb-c::preserve-single-use-debug-variables)) + (if (block nil + (some-unknown-function + (lambda () + (return (member x y)))) + t) + t + (error "~a" y))))) + +;;; Compiling W-P-O when the pinned objects are known to be fixnums +;;; or characters. +(compile nil '(lambda (x y) + (declare (fixnum y) (character x)) + (sb-sys:with-pinned-objects (x y) + (some-random-function)))) + +;;; *CHECK-CONSISTENCY* and TRULY-THE + +(with-test (:name :bug-423) + (let ((sb-c::*check-consistency* t)) + (handler-bind ((warning #'error)) + (flet ((make-lambda (type) + `(lambda (x) + ((lambda (z) + (if (listp z) + (let ((q (truly-the list z))) + (length q)) + (if (arrayp z) + (let ((q (truly-the vector z))) + (length q)) + (error "oops")))) + (the ,type x))))) + (compile nil (make-lambda 'list)) + (compile nil (make-lambda 'vector)))))) + +;;; this caused a momentary regression when an ill-adviced fix to +;;; bug 427 made ANY-REG suitable for primitive-type T: +;;; +;;; no :MOVE-ARG VOP defined to move # (SC SB-VM::SINGLE-REG) to # (SC SB-VM::ANY-REG) +;;; [Condition of type SIMPLE-ERROR] +(compile nil + '(lambda (frob) + (labels + ((%zig (frob) + (typecase frob + (double-float + (setf (sb-alien:deref (sb-alien:cast (sb-alien:sap-alien (unknown1) (* unsigned-char)) + (* double-float))) frob)) + (hash-table + (%zig (the (values (single-float (0.0) 1.0) &optional) (unknown2))) + nil)))) + (%zig)))) + +;;; non-required arguments in HANDLER-BIND +(assert (eq :oops (car (funcall (compile nil + '(lambda (x) + (block nil + (handler-bind ((error (lambda (&rest args) (return (cons :oops args))))) + (/ 2 x))))) + 0)))) + +;;; NIL is a legal function name +(assert (eq 'a (flet ((nil () 'a)) (nil)))) + +;;; misc.528 +(assert (null (let* ((x 296.3066f0) + (y 22717067) + (form `(lambda (r p2) + (declare (optimize speed (safety 1)) + (type (simple-array single-float nil) r) + (type (integer -9369756340 22717335) p2)) + (setf (aref r) (* ,x (the (eql 22717067) p2))) + (values))) + (r (make-array nil :element-type 'single-float)) + (expected (* x y))) + (funcall (compile nil form) r y) + (let ((actual (aref r))) + (unless (eql expected actual) + (list expected actual)))))) +;;; misc.529 +(assert (null (let* ((x -2367.3296f0) + (y 46790178) + (form `(lambda (r p2) + (declare (optimize speed (safety 1)) + (type (simple-array single-float nil) r) + (type (eql 46790178) p2)) + (setf (aref r) (+ ,x (the (integer 45893897) p2))) + (values))) + (r (make-array nil :element-type 'single-float)) + (expected (+ x y))) + (funcall (compile nil form) r y) + (let ((actual (aref r))) + (unless (eql expected actual) + (list expected actual)))))) + +;;; misc.556 +(assert (eql -1 + (funcall + (compile nil '(lambda (p1 p2) + (declare + (optimize (speed 1) (safety 0) + (debug 0) (space 0)) + (type (member 8174.8604) p1) + (type (member -95195347) p2)) + (floor p1 p2))) + 8174.8604 -95195347))) + +;;; misc.557 +(assert (eql -1 + (funcall + (compile + nil + '(lambda (p1) + (declare (optimize (speed 3) (safety 0) (debug 3) (space 1)) + (type (member -94430.086f0) p1)) + (floor (the single-float p1) 19311235))) + -94430.086f0))) + +;;; misc.558 +(assert (eql -1.0f0 + (funcall + (compile + nil + '(lambda (p1) + (declare (optimize (speed 1) (safety 2) + (debug 2) (space 3)) + (type (eql -39466.56f0) p1)) + (ffloor p1 305598613))) + -39466.56f0))) + +;;; misc.559 +(assert (eql 1 + (funcall + (compile + nil + '(lambda (p1) + (declare (optimize (speed 1) (safety 1) (debug 1) (space 2)) + (type (eql -83232.09f0) p1)) + (ceiling p1 -83381228))) + -83232.09f0))) + +;;; misc.560 +(assert (eql 1 + (funcall + (compile + nil + '(lambda (p1) + (declare (optimize (speed 1) (safety 1) + (debug 1) (space 0)) + (type (member -66414.414f0) p1)) + (ceiling p1 -63019173f0))) + -66414.414f0))) + +;;; misc.561 +(assert (eql 1.0f0 + (funcall + (compile + nil + '(lambda (p1) + (declare (optimize (speed 0) (safety 1) + (debug 0) (space 1)) + (type (eql 20851.398f0) p1)) + (fceiling p1 80839863))) + 20851.398f0))) + +;;; misc.581 +(assert (floatp + (funcall + (compile nil '(lambda (x) + (declare (type (eql -5067.2056) x)) + (+ 213734822 x))) + -5067.2056))) + +;;; misc.581a +(assert (typep + (funcall + (compile nil '(lambda (x) (declare (type (eql -1.0) x)) + (+ #x1000001 x))) + -1.0f0) + 'single-float)) + +;;; misc.582 +(assert (plusp (funcall + (compile + nil + ' (lambda (p1) + (declare (optimize (speed 0) (safety 1) (debug 1) (space 1)) + (type (eql -39887.645) p1)) + (mod p1 382352925))) + -39887.645))) + +;;; misc.587 +(assert (let ((result (funcall + (compile + nil + '(lambda (p2) + (declare (optimize (speed 0) (safety 3) (debug 1) (space 0)) + (type (eql 33558541) p2)) + (- 92215.266 p2))) + 33558541))) + (typep result 'single-float))) + +;;; misc.635 +(assert (eql 1 + (let* ((form '(lambda (p2) + (declare (optimize (speed 0) (safety 1) + (debug 2) (space 2)) + (type (member -19261719) p2)) + (ceiling -46022.094 p2)))) + (values (funcall (compile nil form) -19261719))))) + +;;; misc.636 +(assert (let* ((x 26899.875) + (form `(lambda (p2) + (declare (optimize (speed 3) (safety 1) (debug 3) (space 1)) + (type (member ,x #:g5437 char-code #:g5438) p2)) + (* 104102267 p2)))) + (floatp (funcall (compile nil form) x)))) + +;;; misc.622 +(assert (eql + (funcall + (compile + nil + '(lambda (p2) + (declare (optimize (speed 3) (safety 2) (debug 3) (space 0)) + (type real p2)) + (+ 81535869 (the (member 17549.955 #:g35917) p2)))) + 17549.955) + (+ 81535869 17549.955))) + +;;; misc.654 +(assert (eql 2 + (let ((form '(lambda (p2) + (declare (optimize (speed 0) (safety 2) (debug 0) (space 2)) + (type (member integer eql) p2)) + (coerce 2 p2)))) + (funcall (compile nil form) 'integer)))) + +;;; misc.656 +(assert (eql 2 + (let ((form '(lambda (p2) + (declare (optimize (speed 0) (safety 2) (debug 0) (space 2)) + (type (member integer mod) p2)) + (coerce 2 p2)))) + (funcall (compile nil form) 'integer)))) + +;;; misc.657 +(assert (eql 2 + (let ((form '(lambda (p2) + (declare (optimize (speed 0) (safety 2) (debug 0) (space 2)) + (type (member integer values) p2)) + (coerce 2 p2)))) + (funcall (compile nil form) 'integer)))) + +(with-test (:name :string-aref-type) + (assert (eq 'character + (funcall (compile nil + '(lambda (s) + (sb-c::compiler-derived-type (aref (the string s) 0)))) + "foo")))) + +(with-test (:name :base-string-aref-type) + (assert (eq 'base-char + (funcall (compile nil + '(lambda (s) + (sb-c::compiler-derived-type (aref (the base-string s) 0)))) + (coerce "foo" 'base-string)))))