(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))
;;;; 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.
(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))
'-)
(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.
(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)
(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.
;; 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.
(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)
(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
(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*)))
(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)
;; 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))