[cmucl-commit] [git] CMU Common Lisp branch master updated. snapshot-2014-09-30-g8f5f6ab

Raymond Toy rtoy at common-lisp.net
Thu Oct 2 04:26:08 UTC 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMU Common Lisp".

The branch, master has been updated
       via  8f5f6abc07afeb0822ae48b3615c83734960dda6 (commit)
      from  3ff38ffa166153b7266ecdb04a3ff59b85b4c0b4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8f5f6abc07afeb0822ae48b3615c83734960dda6
Author: Raymond Toy <toy.raymond at gmail.com>
Date:   Wed Oct 1 21:25:58 2014 -0700

    Micro-optimize SCALE-FLOAT to use multiplication when possible.
    
    If the exponent (second arg of SCALE-FLOAT) is such that 2^exponent
    can be represented as a float (single or double), we can implement
    SCALE-FLOAT using a multiplication by 2^exponent, since multiplication
    by 2^exponent is exact.
    
     * src/compiler/float-tran.lisp:
       * Update deftransforms for SCALE-FLOAT to do a multiply when
         possible.
     * tests/float-tran.lisp:
       * Add tests to make sure the deftransforms for SCALE-FLOAT are
         applied appropriately.

diff --git a/src/compiler/float-tran.lisp b/src/compiler/float-tran.lisp
index 23aa93f..6efe701 100644
--- a/src/compiler/float-tran.lisp
+++ b/src/compiler/float-tran.lisp
@@ -488,21 +488,50 @@
   '(integer-decode-double-float x))
 
 (deftransform scale-float ((f ex) (single-float *) * :when :both)
-  (if (and (backend-featurep :x86)
-	   (not (backend-featurep :sse2))
-	   (csubtypep (continuation-type ex)
-		      (specifier-type '(signed-byte 32)))
-	   (not (byte-compiling)))
-      '(coerce (%scalbn (coerce f 'double-float) ex) 'single-float)
-      '(scale-single-float f ex)))
+  (cond ((and (backend-featurep :x86)
+	      (not (backend-featurep :sse2))
+	      (csubtypep (continuation-type ex)
+			 (specifier-type '(signed-byte 32)))
+	      (not (byte-compiling)))
+	 '(coerce (%scalbn (coerce f 'double-float) ex) 'single-float))
+	((csubtypep (continuation-type ex)
+		    (specifier-type `(integer #.(- vm:single-float-normal-exponent-min
+						   vm:single-float-bias
+						   vm:single-float-digits)
+					      #.(- vm:single-float-normal-exponent-max
+						   vm:single-float-bias
+						   1))))
+	 ;; The exponent is such that 2^ex will fit in a single-float.
+	 ;; Thus, scale-float can be done multiplying by a suitable
+	 ;; constant.
+	 `(* f (kernel:make-single-float (dpb (+ ex (1+ vm:single-float-bias))
+					      vm:single-float-exponent-byte
+					      (kernel:single-float-bits 1f0)))))
+	(t
+	 '(scale-single-float f ex))))
 
 (deftransform scale-float ((f ex) (double-float *) * :when :both)
-  (if (and (backend-featurep :x86)
-	   (not (backend-featurep :sse2))
-	   (csubtypep (continuation-type ex)
-		      (specifier-type '(signed-byte 32))))
-      '(%scalbn f ex)
-      '(scale-double-float f ex)))
+  (cond ((and (backend-featurep :x86)
+	      (not (backend-featurep :sse2))
+	      (csubtypep (continuation-type ex)
+			 (specifier-type '(signed-byte 32))))
+	 '(%scalbn f ex))
+	((csubtypep (continuation-type ex)
+		    (specifier-type `(integer #.(- vm:double-float-normal-exponent-min
+						   vm:double-float-bias
+						   vm:double-float-digits)
+					      #.(- vm:double-float-normal-exponent-max
+						   vm:double-float-bias
+						   1))))
+	 ;; The exponent is such that 2^ex will fit in a double-float.
+	 ;; Thus, scale-float can be done multiplying by a suitable
+	 ;; constant.
+	 `(* f (kernel:make-double-float (dpb (+ ex (1+ vm:double-float-bias))
+					      vm:double-float-exponent-byte
+					      (kernel::double-float-bits 1d0))
+					 0)))
+	(t
+	 '(scale-double-float f ex))))
 
 ;;; toy at rtp.ericsson.se:
 ;;;
diff --git a/tests/float-tran.lisp b/tests/float-tran.lisp
index 9b84659..8eb1990 100644
--- a/tests/float-tran.lisp
+++ b/tests/float-tran.lisp
@@ -152,3 +152,61 @@
     ;; test-fun should have transformed (log x 10) to kernel:%log10
     (assert-true (search "log10" (with-output-to-string (*standard-output*)
 				   (disassemble test-fun-good-2))))))
+
+(define-test scale-float-transform.single
+  (let ((xfrm-scale
+	  (compile nil
+		   (lambda (x n)
+		     (declare (single-float x)
+			      (type (integer -149 127) n))
+		     (scale-float x n))))
+	(scale
+	  (compile nil
+		   (lambda (x n)
+		     (declare (single-float x)
+			      (type (signed-byte 32) n))
+		     (scale-float x n)))))
+    ;; If the deftransform for scale-float was applied, (scale-float
+    ;; most-positive-single-float 2) is done as a multiplication which
+    ;; will overflow.  The operation will be '*.  If the deftransform
+    ;; was not applied, the overflow will still be signaled, but the
+    ;; operation will be 'scale-float.
+    (assert-eql '*
+		(handler-case 
+		    (funcall xfrm-scale most-positive-single-float 2)
+		  (arithmetic-error (c)
+	            (arithmetic-error-operation c))))
+    (assert-eql 'scale-float
+		(handler-case
+		    (funcall scale most-positive-single-float 2)
+		  (arithmetic-error (c)
+		    (arithmetic-error-operation c))))))
+
+(define-test scale-float-transform.double
+  (let ((xfrm-scale
+	  (compile nil
+		   (lambda (x n)
+		     (declare (double-float x)
+			      (type (integer -1074 1023) n))
+		     (scale-float x n))))
+	(scale
+	  (compile nil
+		   (lambda (x n)
+		     (declare (double-float x)
+			      (type (signed-byte 32) n))
+		     (scale-float x n)))))
+    ;; If the deftransform for scale-float was applied, (scale-float
+    ;; most-positive-double-float 2) is done as a multiplication which
+    ;; will overflow.  The operation will be '*.  If the deftransform
+    ;; was not applied, the overflow will still be signaled, but the
+    ;; operation will be 'scale-float.
+    (assert-eql '*
+		(handler-case 
+		    (funcall xfrm-scale most-positive-double-float 2)
+		  (arithmetic-error (c)
+	            (arithmetic-error-operation c))))
+    (assert-eql 'scale-float
+		(handler-case
+		    (funcall scale most-positive-double-float 2)
+		  (arithmetic-error (c)
+		    (arithmetic-error-operation c))))))

-----------------------------------------------------------------------

Summary of changes:
 src/compiler/float-tran.lisp |   55 +++++++++++++++++++++++++++++----------
 tests/float-tran.lisp        |   58 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 13 deletions(-)


hooks/post-receive
-- 
CMU Common Lisp


More information about the cmucl-commit mailing list