# HG changeset patch # User Chong Yidong # Date 1227293508 0 # Node ID 57a48846650477938fac1a7bc8f64b1b9056bdba # Parent 8fff0bee6091a05c23ab32b44f6b6450ac137bf0 (byte-compile-butlast): Move up in file. (byte-optimize-plus): Don't call byte-optimize-delay-constants-math (bug#1334). Use byte-optimize-predicate to optimize constants. (byte-optimize-minus): Don't call byte-optimize-delay-constants-math. Remove zero arguments first if possible. Call byte-optimize-predicate to optimize constants. (byte-optimize-multiply): Remove optimizations for arguments of 0 and 2, which may be inaccurate. Optimize (* x -1) to (- x). Call byte-optimize-predicate. (byte-optimize-divide): Leave runtime errors unchanged. Optimize (/ x 1) to (+ x 0). Remove optimizations for arguments of 0 and 2.0, which may be inaccurate. Call byte-optimize-predicate. diff -r 8fff0bee6091 -r 57a488466504 lisp/emacs-lisp/byte-opt.el --- a/lisp/emacs-lisp/byte-opt.el Fri Nov 21 18:51:19 2008 +0000 +++ b/lisp/emacs-lisp/byte-opt.el Fri Nov 21 18:51:48 2008 +0000 @@ -747,119 +747,104 @@ (list (apply fun (nreverse constants))))))))) form)) +(defsubst byte-compile-butlast (form) + (nreverse (cdr (reverse form)))) + (defun byte-optimize-plus (form) - (setq form (byte-optimize-delay-constants-math form 1 '+)) + ;; Don't call `byte-optimize-delay-constants-math' (bug#1334). + ;;(setq form (byte-optimize-delay-constants-math form 1 '+)) (if (memq 0 form) (setq form (delq 0 (copy-sequence form)))) - ;;(setq form (byte-optimize-associative-two-args-math form)) - (cond ((null (cdr form)) - (condition-case () - (eval form) - (error form))) -;;; It is not safe to delete the function entirely -;;; (actually, it would be safe if we know the sole arg -;;; is not a marker). -;;; ((null (cdr (cdr form))) (nth 1 form)) - ((null (cddr form)) - (if (numberp (nth 1 form)) - (nth 1 form) - form)) - ((and (null (nthcdr 3 form)) - (or (memq (nth 1 form) '(1 -1)) - (memq (nth 2 form) '(1 -1)))) - ;; Optimize (+ x 1) into (1+ x) and (+ x -1) into (1- x). - (let ((integer - (if (memq (nth 1 form) '(1 -1)) - (nth 1 form) - (nth 2 form))) - (other - (if (memq (nth 1 form) '(1 -1)) - (nth 2 form) - (nth 1 form)))) - (list (if (eq integer 1) '1+ '1-) - other))) - (t form))) + ;; For (+ constants...), byte-optimize-predicate does the work. + (when (memq nil (mapcar 'numberp (cdr form))) + (cond + ;; (+ x 1) --> (1+ x) and (+ x -1) --> (1- x). + ((and (= (length form) 3) + (or (memq (nth 1 form) '(1 -1)) + (memq (nth 2 form) '(1 -1)))) + (let (integer other) + (if (memq (nth 1 form) '(1 -1)) + (setq integer (nth 1 form) other (nth 2 form)) + (setq integer (nth 2 form) other (nth 1 form))) + (setq form + (list (if (eq integer 1) '1+ '1-) other)))) + ;; Here, we could also do + ;; (+ x y ... 1) --> (1+ (+ x y ...)) + ;; (+ x y ... -1) --> (1- (+ x y ...)) + ;; The resulting bytecode is smaller, but is it faster? -- cyd + )) + (byte-optimize-predicate form)) (defun byte-optimize-minus (form) - ;; Put constants at the end, except the last constant. - (setq form (byte-optimize-delay-constants-math form 2 '+)) - ;; Now only first and last element can be a number. - (let ((last (car (reverse (nthcdr 3 form))))) - (cond ((eq 0 last) - ;; (- x y ... 0) --> (- x y ...) - (setq form (copy-sequence form)) - (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form)))) - ((equal (nthcdr 2 form) '(1)) - (setq form (list '1- (nth 1 form)))) - ((equal (nthcdr 2 form) '(-1)) - (setq form (list '1+ (nth 1 form)))) - ;; If form is (- CONST foo... CONST), merge first and last. - ((and (numberp (nth 1 form)) - (numberp last)) - (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form)) - (delq last (copy-sequence (nthcdr 3 form)))))))) -;;; It is not safe to delete the function entirely -;;; (actually, it would be safe if we know the sole arg -;;; is not a marker). -;;; (if (eq (nth 2 form) 0) -;;; (nth 1 form) ; (- x 0) --> x - (byte-optimize-predicate - (if (and (null (cdr (cdr (cdr form)))) - (eq (nth 1 form) 0)) ; (- 0 x) --> (- x) - (cons (car form) (cdr (cdr form))) - form)) -;;; ) - ) + ;; Don't call `byte-optimize-delay-constants-math' (bug#1334). + ;;(setq form (byte-optimize-delay-constants-math form 2 '+)) + ;; Remove zeros. + (when (and (nthcdr 3 form) + (memq 0 (cddr form))) + (setq form (nconc (list (car form) (cadr form)) + (delq 0 (copy-sequence (cddr form))))) + ;; After the above, we must turn (- x) back into (- x 0) + (or (cddr form) + (setq form (nconc form (list 0))))) + ;; For (- constants..), byte-optimize-predicate does the work. + (when (memq nil (mapcar 'numberp (cdr form))) + (cond + ;; (- x 1) --> (1- x) + ((equal (nthcdr 2 form) '(1)) + (setq form (list '1- (nth 1 form)))) + ;; (- x -1) --> (1+ x) + ((equal (nthcdr 2 form) '(-1)) + (setq form (list '1+ (nth 1 form)))) + ;; (- 0 x) --> (- x) + ((and (eq (nth 1 form) 0) + (= (length form) 3)) + (setq form (list '- (nth 2 form)))) + ;; Here, we could also do + ;; (- x y ... 1) --> (1- (- x y ...)) + ;; (- x y ... -1) --> (1+ (- x y ...)) + ;; The resulting bytecode is smaller, but is it faster? -- cyd + )) + (byte-optimize-predicate form)) (defun byte-optimize-multiply (form) (setq form (byte-optimize-delay-constants-math form 1 '*)) - ;; If there is a constant in FORM, it is now the last element. - (cond ((null (cdr form)) 1) -;;; It is not safe to delete the function entirely -;;; (actually, it would be safe if we know the sole arg -;;; is not a marker or if it appears in other arithmetic). -;;; ((null (cdr (cdr form))) (nth 1 form)) - ((let ((last (car (reverse form)))) - (cond ((eq 0 last) (cons 'progn (cdr form))) - ((eq 1 last) (delq 1 (copy-sequence form))) - ((eq -1 last) (list '- (delq -1 (copy-sequence form)))) - ((and (eq 2 last) - (memq t (mapcar 'symbolp (cdr form)))) - (prog1 (setq form (delq 2 (copy-sequence form))) - (while (not (symbolp (car (setq form (cdr form)))))) - (setcar form (list '+ (car form) (car form))))) - (form)))))) - -(defsubst byte-compile-butlast (form) - (nreverse (cdr (reverse form)))) + ;; For (* constants..), byte-optimize-predicate does the work. + (when (memq nil (mapcar 'numberp (cdr form))) + ;; After `byte-optimize-predicate', if there is a INTEGER constant + ;; in FORM, it is in the last element. + (let ((last (car (reverse (cdr form))))) + (cond + ;; Would handling (* ... 0) here cause floating point errors? + ;; See bug#1334. + ((eq 1 last) (setq form (byte-compile-butlast form))) + ((eq -1 last) + (setq form (list '- (if (nthcdr 3 form) + (byte-compile-butlast form) + (nth 1 form)))))))) + (byte-optimize-predicate form)) (defun byte-optimize-divide (form) (setq form (byte-optimize-delay-constants-math form 2 '*)) + ;; After `byte-optimize-predicate', if there is a INTEGER constant + ;; in FORM, it is in the last element. (let ((last (car (reverse (cdr (cdr form)))))) - (if (numberp last) - (cond ((= (length form) 3) - (if (and (numberp (nth 1 form)) - (not (zerop last)) - (condition-case nil - (/ (nth 1 form) last) - (error nil))) - (setq form (list 'progn (/ (nth 1 form) last))))) - ((= last 1) - (setq form (byte-compile-butlast form))) - ((numberp (nth 1 form)) - (setq form (cons (car form) - (cons (/ (nth 1 form) last) - (byte-compile-butlast (cdr (cdr form))))) - last nil)))) (cond -;;; ((null (cdr (cdr form))) -;;; (nth 1 form)) - ((eq (nth 1 form) 0) - (append '(progn) (cdr (cdr form)) '(0))) - ((eq last -1) - (list '- (if (nthcdr 3 form) - (byte-compile-butlast form) - (nth 1 form)))) - (form)))) + ;; Runtime error (leave it intact). + ((or (null last) + (eq last 0) + (memql 0.0 (cddr form)))) + ;; No constants in expression + ((not (numberp last))) + ;; For (* constants..), byte-optimize-predicate does the work. + ((null (memq nil (mapcar 'numberp (cdr form))))) + ;; (/ x y.. 1) --> (/ x y..) + ((and (eq last 1) (nthcdr 3 form)) + (setq form (byte-compile-butlast form))) + ;; (/ x -1), (/ x .. -1) --> (- x), (- (/ x ..)) + ((eq last -1) + (setq form (list '- (if (nthcdr 3 form) + (byte-compile-butlast form) + (nth 1 form))))))) + (byte-optimize-predicate form)) (defun byte-optimize-logmumble (form) (setq form (byte-optimize-delay-constants-math form 1 (car form)))