X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Ffloat-tran.lisp;h=681aa48868c8fd2904e340e78ff34f6db506baeb;hb=07ab1e4811ab16f95a9a5e8d767426a0787f22c0;hp=b05138a033b8886e9846cdcb7da1be420ca6bc4e;hpb=b4c650bad5478d99132fdf0e219d63cf07d0a5f8;p=sbcl.git diff --git a/src/compiler/float-tran.lisp b/src/compiler/float-tran.lisp index b05138a..681aa48 100644 --- a/src/compiler/float-tran.lisp +++ b/src/compiler/float-tran.lisp @@ -298,15 +298,29 @@ ;;;; float contagion +(defun safe-ctype-for-single-coercion-p (x) + ;; See comment in SAFE-SINGLE-COERCION-P -- this deals with the same + ;; problem, but in the context of evaluated and compiled (+ ) + ;; giving different result if we fail to check for this. + (or (not (csubtypep x (specifier-type 'integer))) + (csubtypep x (specifier-type `(integer ,most-negative-exactly-single-float-fixnum + ,most-positive-exactly-single-float-fixnum))))) + ;;; Do some stuff to recognize when the loser is doing mixed float and ;;; rational arithmetic, or different float types, and fix it up. If ;;; we don't, he won't even get so much as an efficiency note. (deftransform float-contagion-arg1 ((x y) * * :defun-only t :node node) - `(,(lvar-fun-name (basic-combination-fun node)) - (float x y) y)) + (if (or (not (types-equal-or-intersect (lvar-type y) (specifier-type 'single-float))) + (safe-ctype-for-single-coercion-p (lvar-type x))) + `(,(lvar-fun-name (basic-combination-fun node)) + (float x y) y) + (give-up-ir1-transform))) (deftransform float-contagion-arg2 ((x y) * * :defun-only t :node node) - `(,(lvar-fun-name (basic-combination-fun node)) - x (float y x))) + (if (or (not (types-equal-or-intersect (lvar-type x) (specifier-type 'single-float))) + (safe-ctype-for-single-coercion-p (lvar-type y))) + `(,(lvar-fun-name (basic-combination-fun node)) + x (float y x)) + (give-up-ir1-transform))) (dolist (x '(+ * / -)) (%deftransform x '(function (rational float) *) #'float-contagion-arg1) @@ -622,7 +636,7 @@ (progn ;;; Handle monotonic functions of a single variable whose domain is -;;; possibly part of the real line. ARG is the variable, FCN is the +;;; possibly part of the real line. ARG is the variable, FUN is the ;;; function, and DOMAIN is a specifier that gives the (real) domain ;;; of the function. If ARG is a subset of the DOMAIN, we compute the ;;; bounds directly. Otherwise, we compute the bounds for the @@ -633,8 +647,8 @@ ;;; DOMAIN-LOW and DOMAIN-HIGH. ;;; ;;; DEFAULT-LOW and DEFAULT-HIGH are the lower and upper bounds if we -;;; can't compute the bounds using FCN. -(defun elfun-derive-type-simple (arg fcn domain-low domain-high +;;; can't compute the bounds using FUN. +(defun elfun-derive-type-simple (arg fun domain-low domain-high default-low default-high &optional (increasingp t)) (declare (type (or null real) domain-low domain-high)) @@ -658,9 +672,9 @@ ;; Process the intersection. (let* ((low (interval-low intersection)) (high (interval-high intersection)) - (res-lo (or (bound-func fcn (if increasingp low high)) + (res-lo (or (bound-func fun (if increasingp low high)) default-low)) - (res-hi (or (bound-func fcn (if increasingp high low)) + (res-hi (or (bound-func fun (if increasingp high low)) default-high)) (format (case (numeric-type-class arg) ((integer rational) 'single-float) @@ -1239,7 +1253,7 @@ ;;; inputs are union types. #-sb-xc-host ; (See CROSS-FLOAT-INFINITY-KLUDGE.) (progn -(defun trig-derive-type-aux (arg domain fcn +(defun trig-derive-type-aux (arg domain fun &optional def-lo def-hi (increasingp t)) (etypecase arg (numeric-type @@ -1260,8 +1274,8 @@ ;; exactly the same way as the functions themselves do ;; it. (if (csubtypep arg domain) - (let ((res-lo (bound-func fcn (numeric-type-low arg))) - (res-hi (bound-func fcn (numeric-type-high arg)))) + (let ((res-lo (bound-func fun (numeric-type-low arg))) + (res-hi (bound-func fun (numeric-type-high arg)))) (unless increasingp (rotatef res-lo res-hi)) (make-numeric-type