From c6e249ac371fae7bf2d04defa9433720108376e4 Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Thu, 25 Jun 2009 11:26:57 +0000 Subject: [PATCH] 1.0.29.40: more (EXPT MINUS-ONE INTEGER) optimization * Branchless version, thanks to Paul Khuong. * Also optimize -1.0 and -1.0d0 cases. * Tests. --- NEWS | 5 +++-- src/compiler/float-tran.lisp | 2 -- src/compiler/srctran.lisp | 9 +++++++++ tests/compiler.impure.lisp | 10 ++++++++++ version.lisp-expr | 2 +- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 68c9042..e6ccfbf 100644 --- 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 diff --git a/src/compiler/float-tran.lisp b/src/compiler/float-tran.lisp index dc2cadc..681aa48 100644 --- a/src/compiler/float-tran.lisp +++ b/src/compiler/float-tran.lisp @@ -512,8 +512,6 @@ '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) diff --git a/src/compiler/srctran.lisp b/src/compiler/srctran.lisp index fc0b639..30ef11e 100644 --- a/src/compiler/srctran.lisp +++ b/src/compiler/srctran.lisp @@ -3323,6 +3323,15 @@ ((= 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 diff --git a/tests/compiler.impure.lisp b/tests/compiler.impure.lisp index bda6fb3..9b509c2 100644 --- a/tests/compiler.impure.lisp +++ b/tests/compiler.impure.lisp @@ -1873,4 +1873,14 @@ `(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 diff --git a/version.lisp-expr b/version.lisp-expr index a87f76c..ec38d39 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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" -- 1.7.10.4