From 195ca6b9a37511e2681e75a35781074b16101a42 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Wed, 21 Jun 2023 16:56:12 +0200 Subject: [PATCH] Don't compile (+ X 0) as (* X 1) 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 | 8 +++++++- test/lisp/emacs-lisp/bytecomp-tests.el | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index f64674d5a6c..307e3841e9b 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -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) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 963ea9abe0c..278496f5259 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -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.") -- 2.39.2