From f644ad38dfa09b81aa53972dc4c549ffca13cc4e Mon Sep 17 00:00:00 2001 From: rtoy <rtoy> Date: Thu, 10 Jul 2008 21:31:34 +0000 Subject: [PATCH] Fix minor issue: (defun zot (x) (declare (type (INTEGER -536871936 536871934) x) (optimize (speed 3))) (kernel::%double-float x)) produces a compiler note being unable to optimize due to type uncertainty x. This is confusing because the vop does get used, and we get a nice single intruction. This is caused by the unsigned-byte 32 deftransform for %single-float/%double-float Work around the issue by o adding new deftransform to convert %single-float/%double-float to %%single-float/%%double-float, o adjusting the deftransform for unsigned 32-bit to call %%foo, o adding a deftransform to always convert %foo to %%foo for signed 32-bit arg, o changing the vop translation to %%foo instead of %foo. --- compiler/sparc/float.lisp | 92 +++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/compiler/sparc/float.lisp b/compiler/sparc/float.lisp index 21672a8e8..25010de17 100644 --- a/compiler/sparc/float.lisp +++ b/compiler/sparc/float.lisp @@ -5,7 +5,7 @@ ;;; Carnegie Mellon University, and has been placed in the public domain. ;;; (ext:file-comment - "$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/float.lisp,v 1.57 2008/06/24 17:12:35 rtoy Exp $") + "$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/float.lisp,v 1.58 2008/07/10 21:31:34 rtoy Exp $") ;;; ;;; ********************************************************************** ;;; @@ -1011,6 +1011,58 @@ ;;;; Conversion: +;; Tell the compiler about %%single-float and %%double-float. Add +;; functions for byte-compiled code. +(macrolet + ((frob (name type) + `(progn + (defknown ,name ((signed-byte 32)) + ,type) + (defun ,name (n) + (declare (type (signed-byte 32) n)) + (,name n))))) + (frob %%single-float single-float) + (frob %%double-float double-float)) + +;; Sparc doesn't have an instruction to convert a 32-bit unsigned +;; integer to a float, but does have one for a 32-bit signed integer. +;; What we do here is break up the 32-bit number into 2 smaller +;; pieces. Each of these are converted to a float, and the higher +;; order piece is scaled appropriately, and finally everything is +;; summed together. The pieces are done in a way such that no +;; roundoff occurs. The scaling should not produce any roundoff +;; either, since the scale factor is an exact power of two. The final +;; sum will produce the correct rounded result. (I think,) +;; +;; But need to be careful because we still want to call the VOP for +;; the small pieces, so we need the transform to give up if it's known +;; that the argument is smaller than a 32-bit unsigned integer. +(macrolet ((frob (name vop-trans limit unit) + `(progn + (deftransform ,name ((n) ((unsigned-byte 32))) + ;; Should this be extended to a (unsigned-byte 53)? We could. Just + ;; take the low 31 bits, and the rest, and float them and combine + ;; them as before. + (when (csubtypep (c::continuation-type n) + (c::specifier-type '(unsigned-byte 31))) + ;; We want to give-up if we know the number can't have the + ;; MSB set. The signed 32-bit vop can handle that. + (c::give-up)) + `(+ (,',vop-trans (ldb (byte ,',limit 0) n)) + (* (,',vop-trans (ldb (byte ,',(- 32 limit) ,',limit) n)) + (scale-float ,',unit ,',limit)))) + ;; Always convert %foo to %%foo for 32-bit signed values. + (deftransform ,name ((n) ((signed-byte 32))) + `(,',vop-trans n))))) + ;; If we break up the numbers into the low 12 bits and the high 20 + ;; bits, we can use a single AND instruction to get the low 12 bits. + ;; This is a microoptimization for Sparc. Otherwise, the only + ;; constraint is that the pieces must be small enough to fit in the + ;; desired float format without rounding. + (frob %single-float %%single-float 12 1f0) + (frob %double-float %%double-float 12 1f0)) + + (macrolet ((frob (name translate inst to-sc to-type) `(define-vop (,name) (:args (x :scs (signed-reg) :target stack-temp @@ -1040,45 +1092,11 @@ (* (tn-offset stack-tn) vm:word-bytes)) (note-this-location vop :internal-error) (inst ,inst y temp)))))) - (frob %single-float/signed %single-float fitos single-reg single-float) - (frob %double-float/signed %double-float fitod double-reg double-float) + (frob %single-float/signed %%single-float fitos single-reg single-float) + (frob %double-float/signed %%double-float fitod double-reg double-float) #+long-float (frob %long-float/signed %long-float fitoq long-reg long-float)) -;; Sparc doesn't have an instruction to convert a 32-bit unsigned -;; integer to a float, but does have one for a 32-bit signed integer. -;; What we do here is break up the 32-bit number into 2 smaller -;; pieces. Each of these are converted to a float, and the higher -;; order piece is scaled appropriately, and finally everything is -;; summed together. The pieces are done in a way such that no -;; roundoff occurs. The scaling should not produce any roundoff -;; either, since the scale factor is an exact power of two. The final -;; sum will produce the correct rounded result. (I think,) -;; -;; But need to be careful because we still want to call the VOP for -;; the small pieces, so we need the transform to give up if it's known -;; that the argument is smaller than a 32-bit unsigned integer. -(macrolet ((frob (name limit unit) - `(deftransform ,name ((n) ((unsigned-byte 32))) - ;; Should this be extended to a (unsigned-byte 53)? We could. Just - ;; take the low 31 bits, and the rest, and float them and combine - ;; them as before. - (when (csubtypep (c::continuation-type n) - (c::specifier-type '(unsigned-byte 31))) - ;; We want to give-up if we know the number can't have the - ;; MSB set. The signed 32-bit vop can handle that. - (c::give-up)) - `(+ (,',name (ldb (byte ,',limit 0) n)) - (* (,',name (ldb (byte ,',(- 32 limit) ,',limit) n)) - (scale-float ,',unit ,',limit)))))) - ;; If we break up the numbers into the low 12 bits and the high 20 - ;; bits, we can use a single AND instruction to get the low 12 bits. - ;; This is a microoptimization for Sparc. Otherwise, the only - ;; constraint is that the pieces must be small enough to fit in the - ;; desired float format without rounding. - (frob %single-float 12 1f0) - (frob %double-float 12 1f0)) - (macrolet ((frob (name translate inst from-sc from-type to-sc to-type) `(define-vop (,name) (:args (x :scs (,from-sc))) -- GitLab