1.0.29.40: more (EXPT MINUS-ONE INTEGER) optimization
authorNikodemus Siivola <nikodemus@random-state.net>
Thu, 25 Jun 2009 11:26:57 +0000 (11:26 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Thu, 25 Jun 2009 11:26:57 +0000 (11:26 +0000)
* Branchless version, thanks to Paul Khuong.

* Also optimize -1.0 and -1.0d0 cases.

* Tests.

NEWS
src/compiler/float-tran.lisp
src/compiler/srctran.lisp
tests/compiler.impure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index 68c9042..e6ccfbf 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,8 +11,9 @@
     about object allocation.
   * optimization: more efficient type-checks for FIXNUMs when the value
     is known to be a signed word on x86 and x86-64.
-  * optimization: (EXPT -1 INTEGER) is compiled into (IF (EVENP INTEGER) 1 -1).
-    (thanks to Stas Boukarev)
+  * optimization: compiler now optimizes (EXPT -1 INTEGER), (EXPT -1.0 INTEGER),
+    and (EXPT -1.0d0 INTEGER) into an ODDP test. (thanks to Stas Boukarev and
+    Paul Khuong)
   * improvement: DESCRIBE output has been reworked to be easier to read and
     contains more pertinent information.
   * improvement: failure to provide requested stack allocation compiler notes
index dc2cadc..681aa48 100644 (file)
     'single-float))
 (deftransform expt ((x y) ((double-float 0d0) (signed-byte 32)) *)
   `(%pow x (coerce y 'double-float)))
-(deftransform expt ((x y) ((integer -1 -1) integer) *)
-  `(if (evenp y) 1 -1))
 
 ;;; ANSI says log with base zero returns zero.
 (deftransform log ((x y) (float float) float)
index fc0b639..30ef11e 100644 (file)
           ((= val -1/2) '(/ (sqrt x)))
           (t (give-up-ir1-transform)))))
 
+(deftransform expt ((x y) ((constant-arg (member -1 -1.0 -1.0d0)) integer) *)
+  "recode as an ODDP check"
+  (let ((val (lvar-value x)))
+    (if (eql 1 val)
+        '(- 1 (* 2 (logand 1 y)))
+        `(if (oddp y)
+             ,val
+             ,(abs val)))))
+
 ;;; KLUDGE: Shouldn't (/ 0.0 0.0), etc. cause exceptions in these
 ;;; transformations?
 ;;; Perhaps we should have to prove that the denominator is nonzero before
index bda6fb3..9b509c2 100644 (file)
                          `(lambda (x y z)
                             (make-array '3 :initial-contents `(,x ,y ,z)))))))
 
+;;; optimizing (EXPT -1 INTEGER)
+(test-util:with-test (:name (expt minus-one integer))
+  (dolist (x '(-1 -1.0 -1.0d0))
+    (let ((fun (compile nil `(lambda (x) (expt ,x (the fixnum x))))))
+      (assert (zerop (count-code-callees fun)))
+      (dotimes (i 12)
+        (if (oddp i)
+            (assert (eql x (funcall fun i)))
+            (assert (eql (- x) (funcall fun i))))))))
+
 ;;; success
index a87f76c..ec38d39 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.29.39"
+"1.0.29.40"