Commit 5d7af879 authored by Raymond Toy's avatar Raymond Toy

Teach compiler to derive the results of DECODE-FLOAT.

src/compiler/float-tran.lisp
o Add defoptimizer for DECODE-FLOAT.

src/general-info/release-20f.txt:
o Update notes.
parent daa00b27
......@@ -2014,6 +2014,89 @@
(specifier-type `(complex ,(or (numeric-type-format arg) 'float))))
#'cis))
;;; Derive the result types of DECODE-FLOAT
(defun decode-float-frac-derive-type-aux (arg)
;; The fraction part of DECODE-FLOAT is always a subset of the
;; interval [0.5, 1), even for subnormals. While possible to derive
;; a tighter bound in some cases, we don't. Just return that
;; interval of the approriate type when possible. If not, just use
;; float.
(if (numeric-type-format arg)
(specifier-type `(,(numeric-type-format arg)
,(coerce 1/2 (numeric-type-format arg))
(,(coerce 1 (numeric-type-format arg)))))
(specifier-type '(float 0.5 (1.0)))))
(defun decode-float-exp-derive-type-aux (arg)
;; Derive the exponent part of the float. It's always an integer
;; type.
(flet ((calc-exp (x)
(when x
(nth-value 1 (decode-float x))))
(min-exp ()
;; Use decode-float on 0 of the appropriate type to find
;; the min exponent. If we don't know the actual number
;; format, use double, which has the widest range
;; (including double-double-float).
(if (numeric-type-format arg)
(nth-value 1 (decode-float (coerce 0 (numeric-type-format arg))))
(nth-value 1 (decode-float (coerce 0 'double-float)))))
(max-exp ()
;; Use decode-float on the most postive number of the
;; appropriate type to find the max exponent. If we don't
;; know the actual number format, use double, which has the
;; widest range (including double-double-float).
(if (eq (numeric-type-format arg) 'single-float)
(nth-value 1 (decode-float most-positive-single-float))
(nth-value 1 (decode-float most-positive-double-float)))))
(let* ((lo (or (bound-func #'calc-exp
(numeric-type-low arg))
(min-exp)))
(hi (or (bound-func #'calc-exp
(numeric-type-high arg))
(max-exp))))
(specifier-type `(integer ,(or lo '*) ,(or hi '*))))))
(defun decode-float-sign-derive-type-aux (arg)
;; Derive the sign of the float.
(flet ((calc-sign (x)
(when x
(nth-value 2 (decode-float x)))))
(let* ((lo (bound-func #'calc-sign
(numeric-type-low arg)))
(hi (bound-func #'calc-sign
(numeric-type-high arg))))
(if (numeric-type-format arg)
(specifier-type `(,(numeric-type-format arg)
;; If lo or high bounds are NIL, use -1
;; or 1 of the appropriate type instead.
,(or lo (coerce -1 (numeric-type-format arg)))
,(or hi (coerce 1 (numeric-type-format arg)))))
(specifier-type '(or (member 1f0 -1f0
1d0 -1d0
#+double-double 1w0
#+double-double -1w0)))))))
(defoptimizer (decode-float derive-type) ((num))
(let ((f (one-arg-derive-type num
#'(lambda (arg)
(decode-float-frac-derive-type-aux arg))
#'(lambda (arg)
(nth-value 0 (decode-float arg)))))
(e (one-arg-derive-type num
#'(lambda (arg)
(decode-float-exp-derive-type-aux arg))
#'(lambda (arg)
(nth-value 1 (decode-float arg)))))
(s (one-arg-derive-type num
#'(lambda (arg)
(decode-float-sign-derive-type-aux arg))
#'(lambda (arg)
(nth-value 2 (decode-float arg))))))
(make-values-type :required (list f
e
s))))
;;; Support for double-double floats
;;;
......
......@@ -28,6 +28,7 @@ New in this release:
lowercase letters when needed.
* Micro-optimize KERNEL:DOUBLE-FLOAT-BITS for x86/sse2.
* Add micro-optimization for unary FTRUNCATE for x86/sse2.
* Compiler can derive the types of the results of DECODE-FLOAT.
* ANSI compliance fixes:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment