X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fsrctran.lisp;h=95dfbab9c2f9e62a0d33a9d4473efc8e3a3c760e;hb=071afc96281a1dac1938268b1cf35d7e92c7e2c0;hp=150cb3a936d122c37532af818c1f6733b7e2a822;hpb=3bc5fbfb7f1528cb2c2e49b2d15fcaa6c62f5b49;p=sbcl.git diff --git a/src/compiler/srctran.lisp b/src/compiler/srctran.lisp index 150cb3a..95dfbab 100644 --- a/src/compiler/srctran.lisp +++ b/src/compiler/srctran.lisp @@ -179,8 +179,14 @@ (define-source-transform logorc1 (x y) `(logior (lognot ,x) ,y)) (define-source-transform logorc2 (x y) `(logior ,x (lognot ,y))) (define-source-transform logtest (x y) `(not (zerop (logand ,x ,y)))) -(define-source-transform logbitp (index integer) - `(not (zerop (logand (ash 1 ,index) ,integer)))) + +(deftransform logbitp + ((index integer) (unsigned-byte (or (signed-byte #.sb!vm:n-word-bits) + (unsigned-byte #.sb!vm:n-word-bits)))) + `(if (>= index #.sb!vm:n-word-bits) + (minusp integer) + (not (zerop (logand integer (ash 1 index)))))) + (define-source-transform byte (size position) `(cons ,size ,position)) (define-source-transform byte-size (spec) `(car ,spec)) @@ -219,6 +225,21 @@ ;;;; numeric-type has everything we want to know. Reason 2 wins for ;;;; now. +;;; Support operations that mimic real arithmetic comparison +;;; operators, but imposing a total order on the floating points such +;;; that negative zeros are strictly less than positive zeros. +(macrolet ((def (name op) + `(defun ,name (x y) + (declare (real x y)) + (if (and (floatp x) (floatp y) (zerop x) (zerop y)) + (,op (float-sign x) (float-sign y)) + (,op x y))))) + (def signed-zero->= >=) + (def signed-zero-> >) + (def signed-zero-= =) + (def signed-zero-< <) + (def signed-zero-<= <=)) + ;;; The basic interval type. It can handle open and closed intervals. ;;; A bound is open if it is a list containing a number, just like ;;; Lisp says. NIL means unbounded. @@ -318,16 +339,8 @@ (make-interval :low (type-bound-number (interval-low x)) :high (type-bound-number (interval-high x)))) -(defun signed-zero->= (x y) - (declare (real x y)) - (or (> x y) - (and (= x y) - (>= (float-sign (float x)) - (float-sign (float y)))))) - ;;; For an interval X, if X >= POINT, return '+. If X <= POINT, return ;;; '-. Otherwise return NIL. -#+nil (defun interval-range-info (x &optional (point 0)) (declare (type interval x)) (let ((lo (interval-low x)) @@ -338,20 +351,6 @@ '-) (t nil)))) -(defun interval-range-info (x &optional (point 0)) - (declare (type interval x)) - (labels ((signed->= (x y) - (if (and (zerop x) (zerop y) (floatp x) (floatp y)) - (>= (float-sign x) (float-sign y)) - (>= x y)))) - (let ((lo (interval-low x)) - (hi (interval-high x))) - (cond ((and lo (signed->= (type-bound-number lo) point)) - '+) - ((and hi (signed->= point (type-bound-number hi))) - '-) - (t - nil))))) ;;; Test to see whether the interval X is bounded. HOW determines the ;;; test, and should be either ABOVE, BELOW, or BOTH. @@ -365,32 +364,6 @@ (both (and (interval-low x) (interval-high x))))) -;;; signed zero comparison functions. Use these functions if we need -;;; to distinguish between signed zeroes. -(defun signed-zero-< (x y) - (declare (real x y)) - (or (< x y) - (and (= x y) - (< (float-sign (float x)) - (float-sign (float y)))))) -(defun signed-zero-> (x y) - (declare (real x y)) - (or (> x y) - (and (= x y) - (> (float-sign (float x)) - (float-sign (float y)))))) -(defun signed-zero-= (x y) - (declare (real x y)) - (and (= x y) - (= (float-sign (float x)) - (float-sign (float y))))) -(defun signed-zero-<= (x y) - (declare (real x y)) - (or (< x y) - (and (= x y) - (<= (float-sign (float x)) - (float-sign (float y)))))) - ;;; See whether the interval X contains the number P, taking into ;;; account that the interval might not be closed. (defun interval-contains-p (p x) @@ -992,10 +965,13 @@ (member (first members)) (member-type (type-of member))) (aver (not (rest members))) - (specifier-type `(,(if (subtypep member-type 'integer) - 'integer - member-type) - ,member ,member)))) + (specifier-type (cond ((typep member 'integer) + `(integer ,member ,member)) + ((memq member-type '(short-float single-float + double-float long-float)) + `(,member-type ,member ,member)) + (t + member-type))))) ;;; This is used in defoptimizers for computing the resulting type of ;;; a function. @@ -2128,27 +2104,19 @@ ;; They must both be positive. (cond ((or (null x-len) (null y-len)) (specifier-type 'unsigned-byte)) - ((or (zerop x-len) (zerop y-len)) - (specifier-type '(integer 0 0))) (t - (specifier-type `(unsigned-byte ,(min x-len y-len))))) + (specifier-type `(unsigned-byte* ,(min x-len y-len))))) ;; X is positive, but Y might be negative. (cond ((null x-len) (specifier-type 'unsigned-byte)) - ((zerop x-len) - (specifier-type '(integer 0 0))) (t - (specifier-type `(unsigned-byte ,x-len))))) + (specifier-type `(unsigned-byte* ,x-len))))) ;; X might be negative. (if (not y-neg) ;; Y must be positive. (cond ((null y-len) (specifier-type 'unsigned-byte)) - ((zerop y-len) - (specifier-type '(integer 0 0))) - (t - (specifier-type - `(unsigned-byte ,y-len)))) + (t (specifier-type `(unsigned-byte* ,y-len)))) ;; Either might be negative. (if (and x-len y-len) ;; The result is bounded. @@ -2163,11 +2131,9 @@ (cond ((and (not x-neg) (not y-neg)) ;; Both are positive. - (if (and x-len y-len (zerop x-len) (zerop y-len)) - (specifier-type '(integer 0 0)) - (specifier-type `(unsigned-byte ,(if (and x-len y-len) - (max x-len y-len) - '*))))) + (specifier-type `(unsigned-byte* ,(if (and x-len y-len) + (max x-len y-len) + '*)))) ((not x-pos) ;; X must be negative. (if (not y-pos) @@ -2206,11 +2172,9 @@ (and (not x-pos) (not y-pos))) ;; Either both are negative or both are positive. The result ;; will be positive, and as long as the longer. - (if (and x-len y-len (zerop x-len) (zerop y-len)) - (specifier-type '(integer 0 0)) - (specifier-type `(unsigned-byte ,(if (and x-len y-len) - (max x-len y-len) - '*))))) + (specifier-type `(unsigned-byte* ,(if (and x-len y-len) + (max x-len y-len) + '*)))) ((or (and (not x-pos) (not y-neg)) (and (not y-neg) (not y-pos))) ;; Either X is negative and Y is positive of vice-versa. The @@ -2318,7 +2282,7 @@ (csubtypep size (specifier-type 'integer))) (let ((size-high (numeric-type-high size))) (if (and size-high (<= size-high sb!vm:n-word-bits)) - (specifier-type `(unsigned-byte ,size-high)) + (specifier-type `(unsigned-byte* ,size-high)) (specifier-type 'unsigned-byte))) *universal-type*))) @@ -2333,57 +2297,46 @@ (posn-high (numeric-type-high posn))) (if (and size-high posn-high (<= (+ size-high posn-high) sb!vm:n-word-bits)) - (specifier-type `(unsigned-byte ,(+ size-high posn-high))) + (specifier-type `(unsigned-byte* ,(+ size-high posn-high))) (specifier-type 'unsigned-byte))) *universal-type*))) -(defoptimizer (%dpb derive-type) ((newbyte size posn int)) +(defun %deposit-field-derive-type-aux (size posn int) (let ((size (continuation-type size)) (posn (continuation-type posn)) (int (continuation-type int))) - (if (and (numeric-type-p size) - (csubtypep size (specifier-type 'integer)) - (numeric-type-p posn) - (csubtypep posn (specifier-type 'integer)) - (numeric-type-p int) - (csubtypep int (specifier-type 'integer))) - (let ((size-high (numeric-type-high size)) - (posn-high (numeric-type-high posn)) - (high (numeric-type-high int)) - (low (numeric-type-low int))) - (if (and size-high posn-high high low - (<= (+ size-high posn-high) sb!vm:n-word-bits)) - (specifier-type - (list (if (minusp low) 'signed-byte 'unsigned-byte) - (max (integer-length high) - (integer-length low) - (+ size-high posn-high)))) - *universal-type*)) - *universal-type*))) + (when (and (numeric-type-p size) + (numeric-type-p posn) + (numeric-type-p int)) + (let ((size-high (numeric-type-high size)) + (posn-high (numeric-type-high posn)) + (high (numeric-type-high int)) + (low (numeric-type-low int))) + (when (and size-high posn-high high low + ;; KLUDGE: we need this cutoff here, otherwise we + ;; will merrily derive the type of %DPB as + ;; (UNSIGNED-BYTE 1073741822), and then attempt to + ;; canonicalize this type to (INTEGER 0 (1- (ASH 1 + ;; 1073741822))), with hilarious consequences. We + ;; cutoff at 4*SB!VM:N-WORD-BITS to allow inference + ;; over a reasonable amount of shifting, even on + ;; the alpha/32 port, where N-WORD-BITS is 32 but + ;; machine integers are 64-bits. -- CSR, + ;; 2003-09-12 + (<= (+ size-high posn-high) (* 4 sb!vm:n-word-bits))) + (let ((raw-bit-count (max (integer-length high) + (integer-length low) + (+ size-high posn-high)))) + (specifier-type + (if (minusp low) + `(signed-byte ,(1+ raw-bit-count)) + `(unsigned-byte* ,raw-bit-count))))))))) + +(defoptimizer (%dpb derive-type) ((newbyte size posn int)) + (%deposit-field-derive-type-aux size posn int)) (defoptimizer (%deposit-field derive-type) ((newbyte size posn int)) - (let ((size (continuation-type size)) - (posn (continuation-type posn)) - (int (continuation-type int))) - (if (and (numeric-type-p size) - (csubtypep size (specifier-type 'integer)) - (numeric-type-p posn) - (csubtypep posn (specifier-type 'integer)) - (numeric-type-p int) - (csubtypep int (specifier-type 'integer))) - (let ((size-high (numeric-type-high size)) - (posn-high (numeric-type-high posn)) - (high (numeric-type-high int)) - (low (numeric-type-low int))) - (if (and size-high posn-high high low - (<= (+ size-high posn-high) sb!vm:n-word-bits)) - (specifier-type - (list (if (minusp low) 'signed-byte 'unsigned-byte) - (max (integer-length high) - (integer-length low) - (+ size-high posn-high)))) - *universal-type*)) - *universal-type*))) + (%deposit-field-derive-type-aux size posn int)) (deftransform %ldb ((size posn int) (fixnum fixnum integer) @@ -2772,7 +2725,19 @@ ;; multiplication and division for small integral powers. (unless (not-more-contagious y x) (give-up-ir1-transform)) - (cond ((zerop val) '(float 1 x)) + (cond ((zerop val) + (let ((x-type (continuation-type x))) + (cond ((csubtypep x-type (specifier-type '(or rational + (complex rational)))) + '1) + ((csubtypep x-type (specifier-type 'real)) + `(if (rationalp x) + 1 + (float 1 x))) + ((csubtypep x-type (specifier-type 'complex)) + ;; both parts are float + `(1+ (* x ,val))) + (t (give-up-ir1-transform))))) ((= val 2) '(* x x)) ((= val -2) '(/ (* x x))) ((= val 3) '(* x x x))