]> git.eshelyaron.com Git - emacs.git/commitdiff
Don't compile (+ X 0) as (* X 1)
authorMattias Engdegård <mattiase@acm.org>
Wed, 21 Jun 2023 14:56:12 +0000 (16:56 +0200)
committerMattias Engdegård <mattiase@acm.org>
Wed, 21 Jun 2023 16:00:26 +0000 (18:00 +0200)
Previously (+ X 0) was reduced to (+ X) which became (* X 1) in
codegen, but this is wrong for X = -0.0 and also slightly slower.

* lisp/emacs-lisp/byte-opt.el (byte-optimize-plus): Don't reduce an
addition to (+ X) by eliminating zeros; retain one 0 argument.
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--test-cases):
Add test case.

lisp/emacs-lisp/byte-opt.el
test/lisp/emacs-lisp/bytecomp-tests.el

index f64674d5a6c0c06cd603bdab75014a09f6a32865..307e3841e9b9c98470fbdbe5afcfabc051d29342 100644 (file)
@@ -873,7 +873,13 @@ for speeding up processing.")
   (cons accum args))
 
 (defun byte-optimize-plus (form)
-  (let ((args (remq 0 (byte-opt--arith-reduce #'+ 0 (cdr form)))))
+  (let* ((not-0 (remq 0 (byte-opt--arith-reduce #'+ 0 (cdr form))))
+         (args (if (and (= (length not-0) 1)
+                        (> (length form) 2))
+                   ;; We removed numbers and only one arg remains: add a 0
+                   ;; so that it isn't turned into (* X 1) later on.
+                   (append not-0 '(0))
+                 not-0)))
     (cond
      ;; (+) -> 0
      ((null args) 0)
index 963ea9abe0c90678d393801591d6ee2d0e371ee4..278496f5259347bd51354334617d282a7480f127 100644 (file)
@@ -776,6 +776,10 @@ inner loops respectively."
       (nconc x nil nil))
     (let ((x (cons 1 (cons 2 (cons 3 4)))))
       (nconc nil x nil (list 5 6) nil))
+
+    ;; (+ 0 -0.0) etc
+    (let ((x (bytecomp-test-identity -0.0)))
+      (list x (+ x) (+ 0 x) (+ x 0) (+ 1 2 -3 x) (+ 0 x 0)))
     )
   "List of expressions for cross-testing interpreted and compiled code.")