Remove the member-fun from two-arg-derive-type.

Float zeros are no longer hiding in member types.
This commit is contained in:
Stas Boukarev 2025-09-12 00:43:03 +03:00
parent 8c81d9c770
commit 528fdf09a1
4 changed files with 103 additions and 204 deletions

View file

@ -369,12 +369,12 @@
(macrolet ((deffrob (logfun)
(let ((fun-aux (symbolicate logfun "-DERIVE-TYPE-AUX")))
`(defoptimizer (,logfun derive-type) ((x y))
(two-arg-derive-type x y #',fun-aux #',logfun)))))
(two-arg-derive-type x y #',fun-aux)))))
(deffrob logand)
(deffrob logior))
(defoptimizer (logxor derive-type) ((x y))
(let ((type (two-arg-derive-type x y #'logxor-derive-type-aux #'logxor)))
(let ((type (two-arg-derive-type x y #'logxor-derive-type-aux)))
(flet ((try (x y)
;; If it's (logxor x (1- x)) then it will be a positive number,
;; except for 0 => -1. This is used to count unset bits.
@ -408,43 +408,36 @@
(defoptimizer (logeqv derive-type) ((x y))
(two-arg-derive-type x y (lambda (x y same-leaf)
(lognot-derive-type-aux
(logxor-derive-type-aux x y same-leaf)))
#'logeqv))
(logxor-derive-type-aux x y same-leaf)))))
(defoptimizer (lognand derive-type) ((x y))
(two-arg-derive-type x y (lambda (x y same-leaf)
(lognot-derive-type-aux
(logand-derive-type-aux x y same-leaf)))
#'lognand))
(logand-derive-type-aux x y same-leaf)))))
(defoptimizer (lognor derive-type) ((x y))
(two-arg-derive-type x y (lambda (x y same-leaf)
(lognot-derive-type-aux
(logior-derive-type-aux x y same-leaf)))
#'lognor))
(logior-derive-type-aux x y same-leaf)))))
(defoptimizer (logandc1 derive-type) ((x y))
(two-arg-derive-type x y (lambda (x y same-leaf)
(if same-leaf
(specifier-type '(eql 0))
(logand-derive-type-aux
(lognot-derive-type-aux x) y)))
#'logandc1))
(lognot-derive-type-aux x) y)))))
(defoptimizer (logandc2 derive-type) ((x y))
(two-arg-derive-type x y (lambda (x y same-leaf)
(if same-leaf
(specifier-type '(eql 0))
(logand-derive-type-aux
x (lognot-derive-type-aux y))))
#'logandc2))
x (lognot-derive-type-aux y))))))
(defoptimizer (logorc1 derive-type) ((x y))
(two-arg-derive-type x y (lambda (x y same-leaf)
(if same-leaf
(specifier-type '(eql -1))
(logior-derive-type-aux
(lognot-derive-type-aux x) y)))
#'logorc1))
(lognot-derive-type-aux x) y)))))
(defoptimizer (logorc2 derive-type) ((x y))
(two-arg-derive-type x y (lambda (x y same-leaf)
(if same-leaf
(specifier-type '(eql -1))
(logior-derive-type-aux
x (lognot-derive-type-aux y))))
#'logorc2))
x (lognot-derive-type-aux y))))))

View file

@ -335,11 +335,9 @@
:low new-lo
:high new-hi)))))
(defoptimizer (scale-single-float derive-type) ((f ex))
(two-arg-derive-type f ex #'scale-float-derive-type-aux
#'scale-float))
(two-arg-derive-type f ex #'scale-float-derive-type-aux))
(defoptimizer (scale-double-float derive-type) ((f ex))
(two-arg-derive-type f ex #'scale-float-derive-type-aux
#'scale-float))
(two-arg-derive-type f ex #'scale-float-derive-type-aux))
;;; DEFOPTIMIZERs for %SINGLE-FLOAT and %DOUBLE-FLOAT. This makes the
;;; FLOAT function return the correct ranges if the input has some
@ -372,7 +370,7 @@
(defoptimizer (,fun derive-type) ((num))
(handler-case
(one-arg-derive-type num #',aux-name (lambda (x) (,fun x)))
(one-arg-derive-type num #',aux-name)
(type-error ()
nil)))))))
(frob %single-float single-float
@ -386,10 +384,8 @@
(csubtypep type (specifier-type 'single-float)))
(handler-case
(type-union
(one-arg-derive-type number #'%single-float-derive-type-aux
(lambda (x) (%single-float x)))
(one-arg-derive-type number #'%double-float-derive-type-aux
(lambda (x) (%double-float x))))
(one-arg-derive-type number #'%single-float-derive-type-aux)
(one-arg-derive-type number #'%double-float-derive-type-aux))
(type-error ()
nil)))))
@ -834,8 +830,7 @@
(elfun-derive-type-simple arg #',name
,domain-low ,domain-high
,def-low-bnd ,def-high-bnd
,increasingp))
#',name)))))
,increasingp)))))))
;; These functions are easy because they are defined for the whole
;; real line.
(frob exp nil nil 0 nil)
@ -1110,7 +1105,7 @@
(float-or-complex-float-type (numeric-contagion x y)))))
(defoptimizer (expt derive-type) ((x y))
(two-arg-derive-type x y #'expt-derive-type-aux #'expt))
(two-arg-derive-type x y #'expt-derive-type-aux))
;;; Note we must assume that a type including 0.0 may also include
;;; -0.0 and thus the result may be complex -infinity + i*pi.
@ -1136,16 +1131,8 @@
(defoptimizer (log derive-type) ((x &optional y))
(if y
(two-arg-derive-type x y #'log-derive-type-aux-2 nil)
(one-arg-derive-type x #'log-derive-type-aux-1
(lambda (n)
(case n
(0f0
single-float-negative-infinity)
(0d0
double-float-negative-infinity)
(t
(log n)))))))
(two-arg-derive-type x y #'log-derive-type-aux-2)
(one-arg-derive-type x #'log-derive-type-aux-1)))
(defun atan-derive-type-aux-1 (y)
(elfun-derive-type-simple y #'atan nil nil (sb-xc:- (sb-xc:/ pi 2)) (sb-xc:/ pi 2)))
@ -1173,8 +1160,8 @@
(defoptimizer (atan derive-type) ((y &optional x))
(if x
(two-arg-derive-type y x #'atan-derive-type-aux-2 #'atan)
(one-arg-derive-type y #'atan-derive-type-aux-1 #'atan)))
(two-arg-derive-type y x #'atan-derive-type-aux-2)
(one-arg-derive-type y #'atan-derive-type-aux-1)))
(defun cosh-derive-type-aux (x)
(%one-arg-derive-type
@ -1182,11 +1169,10 @@
(if (numeric-type-real-p x)
(abs-derive-type-aux x)
x)
(lambda (x) (elfun-derive-type-simple x #'cosh nil nil 0 nil))
#'cosh))
(lambda (x) (elfun-derive-type-simple x #'cosh nil nil 0 nil))))
(defoptimizer (cosh derive-type) ((num))
(one-arg-derive-type num #'cosh-derive-type-aux #'cosh))
(one-arg-derive-type num #'cosh-derive-type-aux))
(defun phase-derive-type-aux (arg)
(let* ((format (case (numeric-type-class arg)
@ -1233,7 +1219,7 @@
:high (coerce pi bound-type))))))
(defoptimizer (phase derive-type) ((num))
(one-arg-derive-type num #'phase-derive-type-aux #'phase))
(one-arg-derive-type num #'phase-derive-type-aux))
(deftransform realpart ((x) ((complex rational)) * :important nil)
'(%realpart x))
@ -1271,7 +1257,7 @@
:high (numeric-type-high type))))))
(defoptimizer (realpart derive-type) ((num))
(one-arg-derive-type num #'realpart-derive-type-aux #'realpart))
(one-arg-derive-type num #'realpart-derive-type-aux))
(defun imagpart-derive-type-aux (type)
(let ((class (numeric-type-class type))
@ -1296,7 +1282,7 @@
:high (numeric-type-high type))))))
(defoptimizer (imagpart derive-type) ((num))
(one-arg-derive-type num #'imagpart-derive-type-aux #'imagpart))
(one-arg-derive-type num #'imagpart-derive-type-aux))
(defun complex-derive-type-aux-1 (re-type)
(if (numeric-type-p re-type)
@ -1344,8 +1330,8 @@
(defoptimizer (complex derive-type) ((re &optional im))
(if im
(two-arg-derive-type re im #'complex-derive-type-aux-2 #'complex)
(one-arg-derive-type re #'complex-derive-type-aux-1 #'complex)))
(two-arg-derive-type re im #'complex-derive-type-aux-2)
(one-arg-derive-type re #'complex-derive-type-aux-1)))
;;; Define some transforms for complex operations in lieu of complex operation
;;; VOPs for most backends. If vops exist, they must support the following
@ -1648,8 +1634,7 @@
arg
(specifier-type `(float ,(sb-xc:- (sb-xc:/ pi 2)) ,(sb-xc:/ pi 2)))
#'sin
-1 1))
#'sin))
-1 1))))
(defoptimizer (cos derive-type) ((num))
(one-arg-derive-type
@ -1660,8 +1645,7 @@
(specifier-type `(float 0d0 ,pi))
#'cos
-1 1
nil))
#'cos))
nil))))
(defoptimizer (tan derive-type) ((num))
(one-arg-derive-type
@ -1674,8 +1658,7 @@
;; 1.5707964 coerced back to double-float is greater than (/ pi 2)
(single-float -1.5707963 1.5707963)))
#'tan
nil nil))
#'tan))
nil nil))))
(defoptimizer (conjugate derive-type) ((num))
(one-arg-derive-type num
@ -1696,15 +1679,13 @@
(high (numeric-type-high arg)))
(let ((new-low (most-negative-bound low high))
(new-high (most-positive-bound low high)))
(modified-numeric-type arg :low new-low :high new-high))))))
#'conjugate))
(modified-numeric-type arg :low new-low :high new-high))))))))
(defoptimizer (cis derive-type) ((num))
(one-arg-derive-type num
(lambda (arg)
(specifier-type
`(complex ,(or (numeric-type-format arg) 'float))))
#'cis))
`(complex ,(or (numeric-type-format arg) 'float))))))
;;;; TRUNCATE, FLOOR, CEILING, and ROUND

View file

@ -765,7 +765,7 @@
(destructuring-bind (q r) (values-type-required res)
(make-values-type (list (%two-arg-derive-type q
(specifier-type `(eql ,(ldb (byte sb-vm:n-word-bits 0) -1)))
#'logand-derive-type-aux #'logand)
#'logand-derive-type-aux)
r))))))
(deftransform sb-vm::truncate-mod64 ((n d) * * :node node)

View file

@ -557,9 +557,7 @@
`(not (zerop (logand x y))))
(defoptimizer (logtest derive-type) ((x y))
(let ((type (two-arg-derive-type x y
#'logand-derive-type-aux
#'logand)))
(let ((type (two-arg-derive-type x y #'logand-derive-type-aux)))
(when type
(multiple-value-bind (typep definitely)
(ctypep 0 type)
@ -609,9 +607,7 @@
(lambda (index integer same)
(declare (ignore same))
(logand-derive-type-aux integer
(ash-derive-type-aux one index nil)))
(lambda (index integer)
(logand integer (ash 1 index))))))
(ash-derive-type-aux one index nil))))))
(cond ((not and)
nil)
((type= and (specifier-type '(eql 0)))
@ -1584,22 +1580,18 @@
(t
(list arg)))))
(unless (eq arg *empty-type*)
;; Make sure all args are some type of numeric-type. For member
;; types, convert the list of members into a union of equivalent
;; single-element member-type's.
;; Make sure all args are some type of numeric-type.
(let ((new-args nil))
(dolist (arg (split arg))
(dolist (arg (split arg) new-args)
(if (member-type-p arg)
;; Run down the list of members and convert to a list of
;; member types.
;; Convert member types (i.e. complex numbers) to their supertypes
(mapc-member-type-members
(lambda (member)
(push (if (numberp member) (make-eql-type member) *empty-type*)
new-args))
(lambda (x)
(if (numberp x)
(pushnew (specifier-type (type-of x)) new-args :test #'eq)
(return)))
arg)
(push arg new-args)))
(unless (member *empty-type* new-args)
new-args)))))
(push arg new-args)))))))
;;; Take a list of types and return a canonical type specifier,
;;; combining any MEMBER types together. If both positive and negative
@ -1667,14 +1659,6 @@
(apply #'type-union (make-member-type xset)
numeric-type misc-types))))
;;; Convert a member type with a single member to a numeric type.
;;; It can only be a complex number
(defun convert-member-type (arg)
(let* ((members (member-type-members arg))
(member (first members)))
(aver (not (rest members)))
(specifier-type (type-of member))))
;;; This is used in defoptimizers for computing the resulting type of
;;; a function.
;;;
@ -1683,21 +1667,13 @@
;;; "atomic" lvar type like numeric-type or member-type (containing
;;; just one element). It should return the resulting type, which can
;;; be a list of types.
;;;
;;; For the case of member types, if a MEMBER-FUN is given it is
;;; called to compute the result otherwise the member type is first
;;; converted to a numeric type and the DERIVE-FUN is called.
(defun %one-arg-derive-type (arg-type derive-fun member-fun)
(declare (type function derive-fun)
(ignore member-fun))
(defun %one-arg-derive-type (arg-type derive-fun)
(declare (type function derive-fun))
(let ((arg-list (prepare-arg-for-derive-type arg-type)))
(when arg-list
(labels ((deriver (x)
(cond
((numeric-type-p x)
(funcall derive-fun x))
((member-type-p x)
(funcall derive-fun (convert-member-type x))))))
(when (numeric-type-p x)
(funcall derive-fun x))))
;; Run down the list of args and derive the type of each one,
;; saving all of the results in a list.
(let ((results nil))
@ -1713,8 +1689,8 @@
(make-derived-union-type results)
(first results)))))))
(defun one-arg-derive-type (arg derive-fun member-fun)
(%one-arg-derive-type (lvar-type arg) derive-fun member-fun))
(defun one-arg-derive-type (arg derive-fun)
(%one-arg-derive-type (lvar-type arg) derive-fun))
;;; Same as ONE-ARG-DERIVE-TYPE, except we assume the function takes
;;; two arguments. DERIVE-FUN takes 3 args in this case: the two
@ -1722,37 +1698,16 @@
;;; really represent the same lvar. This is useful for deriving the
;;; type of things like (* x x), which should always be positive. If
;;; we didn't do this, we wouldn't be able to tell.
(defun two-arg-derive-type (arg1 arg2 derive-fun member-fun)
(defun two-arg-derive-type (arg1 arg2 derive-fun)
(%two-arg-derive-type (lvar-type arg1) (lvar-type arg2)
derive-fun member-fun
(same-leaf-ref-p arg1 arg2)))
derive-fun (same-leaf-ref-p arg1 arg2)))
(defun %two-arg-derive-type (arg1-type arg2-type derive-fun member-fun &optional same-leaf)
(declare (type function derive-fun)
(type (or function null) member-fun))
(defun %two-arg-derive-type (arg1-type arg2-type derive-fun &optional same-leaf)
(declare (type function derive-fun))
(labels ((deriver (x y same-arg)
(cond ((and (member-type-p x) (member-type-p y))
(if member-fun
(funcall derive-fun (convert-member-type x) (convert-member-type y) same-arg)
(let* ((x (first (member-type-members x)))
(y (first (member-type-members y)))
(result (ignore-errors
(funcall member-fun x y))))
(cond ((null result) *empty-type*)
((and (floatp result) (float-nan-p result))
(make-numeric-type :class 'float
:format (type-of result)
:complexp :real))
(t
(specifier-type `(eql ,result)))))))
((and (member-type-p x) (numeric-type-p y))
(funcall derive-fun (convert-member-type x) y same-arg))
((and (numeric-type-p x) (member-type-p y))
(funcall derive-fun x (convert-member-type y) same-arg))
((and (numeric-type-p x) (numeric-type-p y))
(funcall derive-fun x y same-arg))
(t
*universal-type*)))
(if (and (numeric-type-p x) (numeric-type-p y))
(funcall derive-fun x y same-arg)
*universal-type*))
(derive (type1 type2 same-arg)
(let ((a1 (prepare-arg-for-derive-type type1))
(a2 (prepare-arg-for-derive-type type2)))
@ -1821,7 +1776,7 @@
(numeric-contagion x y))))
(defoptimizer (+ derive-type) ((x y))
(two-arg-derive-type x y #'+-derive-type-aux #'sb-xc:+))
(two-arg-derive-type x y #'+-derive-type-aux))
(defun --derive-type-aux (x y same-arg)
(cond ((and (integer-type-p x)
@ -1873,7 +1828,7 @@
(numeric-contagion x y))))
(defoptimizer (- derive-type) ((x y))
(two-arg-derive-type x y #'--derive-type-aux #'sb-xc:-))
(two-arg-derive-type x y #'--derive-type-aux))
(defun *-derive-type-aux (x y same-arg)
(cond ((and same-arg
@ -1940,14 +1895,14 @@
(return
(let ((result (%two-arg-derive-type (type-intersection x (specifier-type '(and integer (not (eql 0)))))
y
#'*-derive-type-aux #'sb-xc:*)))
#'*-derive-type-aux)))
(when result
(type-union result (specifier-type '(eql 0)))))))))
;; If one of the integer arguments is non zero seperate the zero
;; result from the rest of the result range.
(try-zero x-type y-type)
(try-zero y-type x-type)
(two-arg-derive-type x y #'*-derive-type-aux #'sb-xc:*)))))
(two-arg-derive-type x y #'*-derive-type-aux)))))
(defoptimizer (%signed-multiply-high derive-type) ((x y))
(two-arg-derive-type x y
@ -1959,8 +1914,7 @@
(make-numeric-type :class 'integer
:low
(ash low (- sb-vm:n-word-bits))
:high (ash high (- sb-vm:n-word-bits))))))
#'sb-xc:*))
:high (ash high (- sb-vm:n-word-bits))))))))
(defoptimizer (%multiply-high derive-type) ((x y) node)
(%signed-multiply-high-derive-type-optimizer node))
@ -2020,7 +1974,7 @@
(numeric-contagion x y))))
(defoptimizer (/ derive-type) ((x y))
(two-arg-derive-type x y #'/-derive-type-aux #'sb-xc:/))
(two-arg-derive-type x y #'/-derive-type-aux))
(defconstant +left-shift-derive-type-cutoff+ 256)
@ -2067,7 +2021,7 @@
*universal-type*)))
(defoptimizer (ash derive-type) ((n shift))
(two-arg-derive-type n shift #'ash-derive-type-aux #'ash))
(two-arg-derive-type n shift #'ash-derive-type-aux))
(defun lognot-derive-type-aux (int)
(derive-integer-type-aux int int
@ -2081,7 +2035,7 @@
(numeric-type-format type))))))
(defoptimizer (lognot derive-type) ((int))
(one-arg-derive-type int #'lognot-derive-type-aux #'lognot))
(one-arg-derive-type int #'lognot-derive-type-aux))
(defun %negate-derive-type-aux (type)
(flet ((negate-bound (b)
@ -2098,7 +2052,7 @@
r))))
(defoptimizer (%negate derive-type) ((num))
(one-arg-derive-type num #'%negate-derive-type-aux #'sb-xc:-))
(one-arg-derive-type num #'%negate-derive-type-aux))
(defun abs-derive-type-aux (type)
(cond ((ratio-type-p type)
@ -2150,7 +2104,7 @@
type))))))
(defoptimizer (abs derive-type) ((num))
(one-arg-derive-type num #'abs-derive-type-aux #'abs))
(one-arg-derive-type num #'abs-derive-type-aux))
(defun rem-result-type (number-type divisor-type)
;; Figure out what the remainder type is. The remainder is an
@ -2271,9 +2225,9 @@
(defoptimizer (truncate derive-type) ((number divisor))
(let ((quot (two-arg-derive-type number divisor
#'truncate-derive-type-quot-aux #'truncate))
#'truncate-derive-type-quot-aux))
(rem (two-arg-derive-type number divisor
#'truncate-derive-type-rem-aux #'rem)))
#'truncate-derive-type-rem-aux)))
(when (and quot rem)
(make-values-type (list quot rem)))))
@ -2282,28 +2236,23 @@
(defoptimizer (%unary-truncate derive-type) ((number))
(one-arg-derive-type number
#'%unary-truncate-derive-type-aux
#'truncate))
#'%unary-truncate-derive-type-aux))
(defoptimizer (%unary-truncate/single-float derive-type) ((number))
(one-arg-derive-type number
#'%unary-truncate-derive-type-aux
#'truncate))
#'%unary-truncate-derive-type-aux))
(defoptimizer (%unary-truncate/double-float derive-type) ((number))
(one-arg-derive-type number
#'%unary-truncate-derive-type-aux
#'truncate))
#'%unary-truncate-derive-type-aux))
(defoptimizer (unary-truncate derive-type) ((number))
(let* ((one (specifier-type '(integer 1 1)))
(quot (one-arg-derive-type number
(lambda (x)
(truncate-derive-type-quot-aux x one nil))
#'truncate))
(truncate-derive-type-quot-aux x one nil))))
(rem (one-arg-derive-type number
(lambda (x) (truncate-derive-type-rem-aux x one nil))
(lambda (x) (nth-value 1 (truncate x 1))))))
(lambda (x) (truncate-derive-type-rem-aux x one nil)))))
(when (and quot rem)
(make-values-type (list quot rem)))))
@ -2333,9 +2282,9 @@
(defoptimizer (ftruncate derive-type) ((number divisor))
(let ((quot
(two-arg-derive-type number divisor
#'ftruncate-derive-type-quot-aux #'ftruncate))
#'ftruncate-derive-type-quot-aux))
(rem (two-arg-derive-type number divisor
#'truncate-derive-type-rem-aux #'rem)))
#'truncate-derive-type-rem-aux)))
(when (and quot rem)
(make-values-type (list quot rem)))))
@ -2356,9 +2305,7 @@
'*)
(if hi
(,fun (type-bound-number hi))
'*))))))
(lambda (x)
(values (,fun x)))))))))
'*))))))))))))
(defoptimizer (round-single derive-type) ((number mode))
(derive single-float))
(defoptimizer (round-double derive-type) ((number mode))
@ -2383,8 +2330,7 @@
'*)
,(if high
(round high)
'*))))))
#'round))
'*))))))))
;;; Define optimizers for FLOOR and CEILING.
(macrolet
@ -2452,9 +2398,9 @@
(t
(numeric-contagion num div)))))
(let ((quot (two-arg-derive-type
number divisor #'derive-q #',name))
number divisor #'derive-q))
(rem (two-arg-derive-type
number divisor #'derive-r #'mod)))
number divisor #'derive-r)))
(when (and quot rem)
(make-values-type (list quot rem))))))))))
@ -2827,7 +2773,7 @@
(t `(,high))))))
(defoptimizer (random derive-type) ((bound &optional state))
(one-arg-derive-type bound #'random-derive-type-aux nil))
(one-arg-derive-type bound #'random-derive-type-aux))
;;;; miscellaneous derive-type methods
@ -2857,8 +2803,7 @@
(specifier-type `(integer ,(integer-length lo)))))
(hi
(when (< hi 0)
(specifier-type `(integer ,(integer-length hi)))))))))
#'integer-length))
(specifier-type `(integer ,(integer-length hi)))))))))))
(defoptimizer (%bignum-length derive-type) ((x))
(one-arg-derive-type
@ -2874,8 +2819,7 @@
(specifier-type `(integer ,(%bignum-length lo)))))
(hi
(when (< hi 0)
(specifier-type `(integer ,(%bignum-length hi))))))))
nil))
(specifier-type `(integer ,(%bignum-length hi))))))))))
(defoptimizer (logcount derive-type) ((x))
(one-arg-derive-type
@ -2924,8 +2868,7 @@
(specifier-type `(integer 1))))
(hi
(when (< hi -1)
(specifier-type `(integer 1)))))))
#'logcount))
(specifier-type `(integer 1)))))))))
(defoptimizer (isqrt derive-type) ((x))
(one-arg-derive-type
@ -2939,8 +2882,7 @@
(hi-res (if (typep hi 'unsigned-byte)
(isqrt hi)
'*)))
(specifier-type `(integer ,lo-res ,hi-res))))
#'isqrt))
(specifier-type `(integer ,lo-res ,hi-res))))))
(defoptimizer (char-code derive-type) ((char))
(let ((type (type-intersection (lvar-type char) (specifier-type 'character))))
@ -2983,8 +2925,7 @@
((csubtypep type (specifier-type 'extended-char))
(specifier-type 'extended-char))
(t #+sb-xc-host (specifier-type 'character)
#-sb-xc-host type))))
nil))
#-sb-xc-host type))))))
(deftransform code-char ((code))
(splice-fun-args code 'char-code 1)
@ -3083,7 +3024,7 @@
:high 1))))))))
(defoptimizer (signum derive-type) ((num))
(one-arg-derive-type num #'signum-derive-type-aux nil))
(one-arg-derive-type num #'signum-derive-type-aux))
;;;; byte operations
;;;;
@ -3137,18 +3078,14 @@
(let* ((shifted (two-arg-derive-type num posn
(lambda (num posn same)
(declare (ignore same))
(ash-derive-type-aux num (%negate-derive-type-aux posn) nil))
(lambda (num posn)
(ash num (- posn)))))
(ash-derive-type-aux num (%negate-derive-type-aux posn) nil))))
(minus-one (specifier-type '(eql -1)))
(mask (one-arg-derive-type size
(lambda (x)
(lognot-derive-type-aux
(ash-derive-type-aux minus-one x nil)))
(lambda (x)
(lognot (ash -1 x))))))
(ash-derive-type-aux minus-one x nil))))))
(when (and shifted mask)
(%two-arg-derive-type shifted mask #'logand-derive-type-aux #'logand))))
(%two-arg-derive-type shifted mask #'logand-derive-type-aux))))
;; Handle (ldb (byte y (- 64 y)) x)
(minuend (related-byte-spec size posn)))
(if (and minuend
@ -3196,13 +3133,11 @@
(or (one-arg-derive-type size
(lambda (x)
(lognot-derive-type-aux
(ash-derive-type-aux minus-one x nil)))
(lambda (x)
(lognot (ash -1 x))))
(ash-derive-type-aux minus-one x nil))))
(return)))
(mask-shifted
(or (%two-arg-derive-type mask (lvar-type posn)
#'ash-derive-type-aux #'ash)
#'ash-derive-type-aux)
(return)))
(int
(or (%two-arg-derive-type (lvar-type int) mask-shifted
@ -3211,19 +3146,16 @@
(%two-arg-derive-type
int
(lognot-derive-type-aux mask)
#'logand-derive-type-aux
#'logand))
(lambda (int mask)
(logandc2 int mask)))
#'logand-derive-type-aux)))
(return)))
(new-masked (or (%two-arg-derive-type mask (lvar-type newbyte)
#'logand-derive-type-aux #'logand)
#'logand-derive-type-aux)
(return)))
(new
(or (%two-arg-derive-type new-masked (lvar-type posn)
#'ash-derive-type-aux #'ash)
#'ash-derive-type-aux)
(return))))
(%two-arg-derive-type int new #'logior-derive-type-aux #'logior))))
(%two-arg-derive-type int new #'logior-derive-type-aux))))
(int-interval (type-approximate-interval (lvar-type int))))
(or
(when (and int-interval
@ -3255,9 +3187,7 @@
(ash-derive-type-aux
(lognot-derive-type-aux
(ash-derive-type-aux minus-one size nil))
posn nil))
(lambda (x)
(lognot (ash -1 x))))
posn nil)))
(return)))
(int
(or (%two-arg-derive-type (lvar-type int) mask
@ -3266,15 +3196,12 @@
(%two-arg-derive-type
int
(lognot-derive-type-aux mask)
#'logand-derive-type-aux
#'logand))
(lambda (int mask)
(logandc2 int mask)))
#'logand-derive-type-aux)))
(return)))
(new (or (%two-arg-derive-type mask (lvar-type newbyte)
#'logand-derive-type-aux #'logand)
#'logand-derive-type-aux)
(return))))
(%two-arg-derive-type int new #'logior-derive-type-aux #'logior))))
(%two-arg-derive-type int new #'logior-derive-type-aux))))
(defmacro min-or-nil (&rest numbers-or-nil)
(let ((min-sym (gensym "MIN")))
@ -3467,7 +3394,7 @@
*universal-type*))
(defoptimizer (%ash/right derive-type) ((n shift))
(two-arg-derive-type n shift #'%ash/right-derive-type-aux #'%ash/right)))
(two-arg-derive-type n shift #'%ash/right-derive-type-aux)))
(defmacro combination-typed-p (node name &rest types)
(labels ((gen (type)
@ -4788,7 +4715,7 @@
(if (and (not (or (csubtypep (lvar-type x) (specifier-type 'word))
(csubtypep (lvar-type x) (specifier-type 'sb-vm:signed-word))))
(csubtypep (lvar-type y) (specifier-type 'fixnum))
(csubtypep (one-arg-derive-type y #'lognot-derive-type-aux #'lognot)
(csubtypep (one-arg-derive-type y #'lognot-derive-type-aux)
(specifier-type 'fixnum)))
`(logand x (lognot y))
(give-up-ir1-transform)))
@ -6533,8 +6460,7 @@
(make-numeric-type
:class 'rational
:low (%rational (numeric-type-low type))
:high (%rational (numeric-type-high type)))))
#'rational))
:high (%rational (numeric-type-high type)))))))
(defoptimizer (rationalize derive-type) ((x))
(one-arg-derive-type x (lambda (type)
@ -6550,8 +6476,7 @@
(make-numeric-type
:class 'rational
:low (%rationalize (numeric-type-low type))
:high (%rationalize (numeric-type-high type)))))
#'rationalize))
:high (%rationalize (numeric-type-high type)))))))
;;;; transforming APPLY