From 5e0af0dad59e01274b0e84b58e5f0904c9890b37 Mon Sep 17 00:00:00 2001 From: Paul Khuong Date: Fri, 26 Jun 2009 16:54:18 +0000 Subject: [PATCH] 1.0.29.47: Floating point correctness improvement * Don't perform constant folding for addition/subtraction of 0 or multiplication/division/exponentiation by +/- 1 on float types. * Also operate on the imaginary part for generic addition and subtraction with mixed complex/real arguments, as specified. * Update NEWS for 10.29.44. --- NEWS | 7 +++++++ src/code/numbers.lisp | 6 +++--- src/compiler/srctran.lisp | 41 ++++++++++++++++------------------------- tests/float.pure.lisp | 3 +-- version.lisp-expr | 2 +- 5 files changed, 28 insertions(+), 31 deletions(-) diff --git a/NEWS b/NEWS index b7e0b04..d6ec6ff 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,10 @@ values in other threads. * new feature: SB-INTROSPECT:ALLOCATION-INFORMATION provides information about object allocation. + * optimization: more efficient complex float and real float operations + on x86-64. + * optimization: division of a real float by a complex float is implemented + with a specialised code sequence. * optimization: MAKE-INSTANCE with non-constant class-argument but constant keywords is an order of magnitude faster. * optimization: MAKE-INSTANCE with constant keyword arguments is somewhat @@ -20,6 +24,9 @@ * 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: less unsafe constant folding in floating point arithmetic, + especially for mixed complex/real -float operations. + * improvement: complex float division is slightly more stable. * 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/code/numbers.lisp b/src/code/numbers.lisp index 525beb7..b8ef200 100644 --- a/src/code/numbers.lisp +++ b/src/code/numbers.lisp @@ -358,14 +358,14 @@ (bignum-cross-fixnum ,op ,big-op) (float-contagion ,op x y) - ((complex complex) + ((complex complex) + (canonical-complex (,op (realpart x) (realpart y)) (,op (imagpart x) (imagpart y)))) (((foreach bignum fixnum ratio single-float double-float #!+long-float long-float) complex) - (complex (,op x (realpart y)) (,op (imagpart y)))) + (complex (,op x (realpart y)) (,op 0 (imagpart y)))) ((complex (or rational float)) - (complex (,op (realpart x) y) (imagpart x))) + (complex (,op (realpart x) y) (,op (imagpart x) 0))) (((foreach fixnum bignum) ratio) (let* ((dy (denominator y)) diff --git a/src/compiler/srctran.lisp b/src/compiler/srctran.lisp index db475c1..7421fd7 100644 --- a/src/compiler/srctran.lisp +++ b/src/compiler/srctran.lisp @@ -3252,41 +3252,32 @@ (values (type= (numeric-contagion x y) (numeric-contagion y y))))))) +(def!type exact-number () + '(or rational (complex rational))) + ;;; Fold (+ x 0). ;;; -;;; If y is not constant, not zerop, or is contagious, or a positive -;;; float +0.0 then give up. -(deftransform + ((x y) (t (constant-arg t)) *) +;;; Only safely applicable for exact numbers. For floating-point +;;; x, one would have to first show that neither x or y are signed +;;; 0s, and that x isn't an SNaN. +(deftransform + ((x y) (exact-number (constant-arg (eql 0))) *) "fold zero arg" - (let ((val (lvar-value y))) - (unless (and (zerop val) - (not (and (floatp val) (plusp (float-sign val)))) - (not-more-contagious y x)) - (give-up-ir1-transform))) 'x) ;;; Fold (- x 0). -;;; -;;; If y is not constant, not zerop, or is contagious, or a negative -;;; float -0.0 then give up. -(deftransform - ((x y) (t (constant-arg t)) *) +(deftransform - ((x y) (exact-number (constant-arg (eql 0))) *) "fold zero arg" - (let ((val (lvar-value y))) - (unless (and (zerop val) - (not (and (floatp val) (minusp (float-sign val)))) - (not-more-contagious y x)) - (give-up-ir1-transform))) 'x) ;;; Fold (OP x +/-1) -(macrolet ((def (name result minus-result) - `(deftransform ,name ((x y) (t (constant-arg real)) *) - "fold identity operations" - (let ((val (lvar-value y))) - (unless (and (= (abs val) 1) - (not-more-contagious y x)) - (give-up-ir1-transform)) - (if (minusp val) ',minus-result ',result))))) +;;; +;;; %NEGATE might not always signal correctly. +(macrolet + ((def (name result minus-result) + `(deftransform ,name ((x y) + (exact-number (constant-arg (member 1 -1)))) + "fold identity operations" + (if (minusp (lvar-value y)) ',minus-result ',result)))) (def * x (%negate x)) (def / x (%negate x)) (def expt x (/ 1 x))) diff --git a/tests/float.pure.lisp b/tests/float.pure.lisp index 08513dd..fee0323 100644 --- a/tests/float.pure.lisp +++ b/tests/float.pure.lisp @@ -234,8 +234,7 @@ (assert (eql 0.0d0 (funcall f 123.0d0 0.0d0))) (assert (eql 0.0d0 (funcall f 123.0 0.0d0))))) - -;; 1.0.29.xFIXMEx introduces a ton of changes for complex floats +;; 1.0.29.44 introduces a ton of changes for complex floats ;; on x86-64. Huge test of doom to help catch weird corner ;; cases. (with-test (:name :complex-floats) diff --git a/version.lisp-expr b/version.lisp-expr index c8d0637..1246f7b 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.46" +"1.0.29.47" -- 1.7.10.4