1.0.29.47: Floating point correctness improvement
authorPaul Khuong <pvk@pvk.ca>
Fri, 26 Jun 2009 16:54:18 +0000 (16:54 +0000)
committerPaul Khuong <pvk@pvk.ca>
Fri, 26 Jun 2009 16:54:18 +0000 (16:54 +0000)
* 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
src/code/numbers.lisp
src/compiler/srctran.lisp
tests/float.pure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index b7e0b04..d6ec6ff 100644 (file)
--- 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
index 525beb7..b8ef200 100644 (file)
        (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))
index db475c1..7421fd7 100644 (file)
           (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)))
index 08513dd..fee0323 100644 (file)
     (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)
index c8d0637..1246f7b 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.46"
+"1.0.29.47"