Mercurial > emacs
comparison lisp/emacs-lisp/byte-opt.el @ 99772:57a488466504
(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.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Fri, 21 Nov 2008 18:51:48 +0000 |
parents | 90a2847062be |
children | a9dc0e7c3f2b |
comparison
equal
deleted
inserted
replaced
99771:8fff0bee6091 | 99772:57a488466504 |
---|---|
745 (setq form orig) | 745 (setq form orig) |
746 (setq form (nconc (delq nil form) | 746 (setq form (nconc (delq nil form) |
747 (list (apply fun (nreverse constants))))))))) | 747 (list (apply fun (nreverse constants))))))))) |
748 form)) | 748 form)) |
749 | 749 |
750 (defsubst byte-compile-butlast (form) | |
751 (nreverse (cdr (reverse form)))) | |
752 | |
750 (defun byte-optimize-plus (form) | 753 (defun byte-optimize-plus (form) |
751 (setq form (byte-optimize-delay-constants-math form 1 '+)) | 754 ;; Don't call `byte-optimize-delay-constants-math' (bug#1334). |
755 ;;(setq form (byte-optimize-delay-constants-math form 1 '+)) | |
752 (if (memq 0 form) (setq form (delq 0 (copy-sequence form)))) | 756 (if (memq 0 form) (setq form (delq 0 (copy-sequence form)))) |
753 ;;(setq form (byte-optimize-associative-two-args-math form)) | 757 ;; For (+ constants...), byte-optimize-predicate does the work. |
754 (cond ((null (cdr form)) | 758 (when (memq nil (mapcar 'numberp (cdr form))) |
755 (condition-case () | 759 (cond |
756 (eval form) | 760 ;; (+ x 1) --> (1+ x) and (+ x -1) --> (1- x). |
757 (error form))) | 761 ((and (= (length form) 3) |
758 ;;; It is not safe to delete the function entirely | 762 (or (memq (nth 1 form) '(1 -1)) |
759 ;;; (actually, it would be safe if we know the sole arg | 763 (memq (nth 2 form) '(1 -1)))) |
760 ;;; is not a marker). | 764 (let (integer other) |
761 ;;; ((null (cdr (cdr form))) (nth 1 form)) | 765 (if (memq (nth 1 form) '(1 -1)) |
762 ((null (cddr form)) | 766 (setq integer (nth 1 form) other (nth 2 form)) |
763 (if (numberp (nth 1 form)) | 767 (setq integer (nth 2 form) other (nth 1 form))) |
764 (nth 1 form) | 768 (setq form |
765 form)) | 769 (list (if (eq integer 1) '1+ '1-) other)))) |
766 ((and (null (nthcdr 3 form)) | 770 ;; Here, we could also do |
767 (or (memq (nth 1 form) '(1 -1)) | 771 ;; (+ x y ... 1) --> (1+ (+ x y ...)) |
768 (memq (nth 2 form) '(1 -1)))) | 772 ;; (+ x y ... -1) --> (1- (+ x y ...)) |
769 ;; Optimize (+ x 1) into (1+ x) and (+ x -1) into (1- x). | 773 ;; The resulting bytecode is smaller, but is it faster? -- cyd |
770 (let ((integer | 774 )) |
771 (if (memq (nth 1 form) '(1 -1)) | 775 (byte-optimize-predicate form)) |
772 (nth 1 form) | |
773 (nth 2 form))) | |
774 (other | |
775 (if (memq (nth 1 form) '(1 -1)) | |
776 (nth 2 form) | |
777 (nth 1 form)))) | |
778 (list (if (eq integer 1) '1+ '1-) | |
779 other))) | |
780 (t form))) | |
781 | 776 |
782 (defun byte-optimize-minus (form) | 777 (defun byte-optimize-minus (form) |
783 ;; Put constants at the end, except the last constant. | 778 ;; Don't call `byte-optimize-delay-constants-math' (bug#1334). |
784 (setq form (byte-optimize-delay-constants-math form 2 '+)) | 779 ;;(setq form (byte-optimize-delay-constants-math form 2 '+)) |
785 ;; Now only first and last element can be a number. | 780 ;; Remove zeros. |
786 (let ((last (car (reverse (nthcdr 3 form))))) | 781 (when (and (nthcdr 3 form) |
787 (cond ((eq 0 last) | 782 (memq 0 (cddr form))) |
788 ;; (- x y ... 0) --> (- x y ...) | 783 (setq form (nconc (list (car form) (cadr form)) |
789 (setq form (copy-sequence form)) | 784 (delq 0 (copy-sequence (cddr form))))) |
790 (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form)))) | 785 ;; After the above, we must turn (- x) back into (- x 0) |
791 ((equal (nthcdr 2 form) '(1)) | 786 (or (cddr form) |
792 (setq form (list '1- (nth 1 form)))) | 787 (setq form (nconc form (list 0))))) |
793 ((equal (nthcdr 2 form) '(-1)) | 788 ;; For (- constants..), byte-optimize-predicate does the work. |
794 (setq form (list '1+ (nth 1 form)))) | 789 (when (memq nil (mapcar 'numberp (cdr form))) |
795 ;; If form is (- CONST foo... CONST), merge first and last. | 790 (cond |
796 ((and (numberp (nth 1 form)) | 791 ;; (- x 1) --> (1- x) |
797 (numberp last)) | 792 ((equal (nthcdr 2 form) '(1)) |
798 (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form)) | 793 (setq form (list '1- (nth 1 form)))) |
799 (delq last (copy-sequence (nthcdr 3 form)))))))) | 794 ;; (- x -1) --> (1+ x) |
800 ;;; It is not safe to delete the function entirely | 795 ((equal (nthcdr 2 form) '(-1)) |
801 ;;; (actually, it would be safe if we know the sole arg | 796 (setq form (list '1+ (nth 1 form)))) |
802 ;;; is not a marker). | 797 ;; (- 0 x) --> (- x) |
803 ;;; (if (eq (nth 2 form) 0) | 798 ((and (eq (nth 1 form) 0) |
804 ;;; (nth 1 form) ; (- x 0) --> x | 799 (= (length form) 3)) |
805 (byte-optimize-predicate | 800 (setq form (list '- (nth 2 form)))) |
806 (if (and (null (cdr (cdr (cdr form)))) | 801 ;; Here, we could also do |
807 (eq (nth 1 form) 0)) ; (- 0 x) --> (- x) | 802 ;; (- x y ... 1) --> (1- (- x y ...)) |
808 (cons (car form) (cdr (cdr form))) | 803 ;; (- x y ... -1) --> (1+ (- x y ...)) |
809 form)) | 804 ;; The resulting bytecode is smaller, but is it faster? -- cyd |
810 ;;; ) | 805 )) |
811 ) | 806 (byte-optimize-predicate form)) |
812 | 807 |
813 (defun byte-optimize-multiply (form) | 808 (defun byte-optimize-multiply (form) |
814 (setq form (byte-optimize-delay-constants-math form 1 '*)) | 809 (setq form (byte-optimize-delay-constants-math form 1 '*)) |
815 ;; If there is a constant in FORM, it is now the last element. | 810 ;; For (* constants..), byte-optimize-predicate does the work. |
816 (cond ((null (cdr form)) 1) | 811 (when (memq nil (mapcar 'numberp (cdr form))) |
817 ;;; It is not safe to delete the function entirely | 812 ;; After `byte-optimize-predicate', if there is a INTEGER constant |
818 ;;; (actually, it would be safe if we know the sole arg | 813 ;; in FORM, it is in the last element. |
819 ;;; is not a marker or if it appears in other arithmetic). | 814 (let ((last (car (reverse (cdr form))))) |
820 ;;; ((null (cdr (cdr form))) (nth 1 form)) | 815 (cond |
821 ((let ((last (car (reverse form)))) | 816 ;; Would handling (* ... 0) here cause floating point errors? |
822 (cond ((eq 0 last) (cons 'progn (cdr form))) | 817 ;; See bug#1334. |
823 ((eq 1 last) (delq 1 (copy-sequence form))) | 818 ((eq 1 last) (setq form (byte-compile-butlast form))) |
824 ((eq -1 last) (list '- (delq -1 (copy-sequence form)))) | 819 ((eq -1 last) |
825 ((and (eq 2 last) | 820 (setq form (list '- (if (nthcdr 3 form) |
826 (memq t (mapcar 'symbolp (cdr form)))) | 821 (byte-compile-butlast form) |
827 (prog1 (setq form (delq 2 (copy-sequence form))) | 822 (nth 1 form)))))))) |
828 (while (not (symbolp (car (setq form (cdr form)))))) | 823 (byte-optimize-predicate form)) |
829 (setcar form (list '+ (car form) (car form))))) | |
830 (form)))))) | |
831 | |
832 (defsubst byte-compile-butlast (form) | |
833 (nreverse (cdr (reverse form)))) | |
834 | 824 |
835 (defun byte-optimize-divide (form) | 825 (defun byte-optimize-divide (form) |
836 (setq form (byte-optimize-delay-constants-math form 2 '*)) | 826 (setq form (byte-optimize-delay-constants-math form 2 '*)) |
827 ;; After `byte-optimize-predicate', if there is a INTEGER constant | |
828 ;; in FORM, it is in the last element. | |
837 (let ((last (car (reverse (cdr (cdr form)))))) | 829 (let ((last (car (reverse (cdr (cdr form)))))) |
838 (if (numberp last) | |
839 (cond ((= (length form) 3) | |
840 (if (and (numberp (nth 1 form)) | |
841 (not (zerop last)) | |
842 (condition-case nil | |
843 (/ (nth 1 form) last) | |
844 (error nil))) | |
845 (setq form (list 'progn (/ (nth 1 form) last))))) | |
846 ((= last 1) | |
847 (setq form (byte-compile-butlast form))) | |
848 ((numberp (nth 1 form)) | |
849 (setq form (cons (car form) | |
850 (cons (/ (nth 1 form) last) | |
851 (byte-compile-butlast (cdr (cdr form))))) | |
852 last nil)))) | |
853 (cond | 830 (cond |
854 ;;; ((null (cdr (cdr form))) | 831 ;; Runtime error (leave it intact). |
855 ;;; (nth 1 form)) | 832 ((or (null last) |
856 ((eq (nth 1 form) 0) | 833 (eq last 0) |
857 (append '(progn) (cdr (cdr form)) '(0))) | 834 (memql 0.0 (cddr form)))) |
858 ((eq last -1) | 835 ;; No constants in expression |
859 (list '- (if (nthcdr 3 form) | 836 ((not (numberp last))) |
860 (byte-compile-butlast form) | 837 ;; For (* constants..), byte-optimize-predicate does the work. |
861 (nth 1 form)))) | 838 ((null (memq nil (mapcar 'numberp (cdr form))))) |
862 (form)))) | 839 ;; (/ x y.. 1) --> (/ x y..) |
840 ((and (eq last 1) (nthcdr 3 form)) | |
841 (setq form (byte-compile-butlast form))) | |
842 ;; (/ x -1), (/ x .. -1) --> (- x), (- (/ x ..)) | |
843 ((eq last -1) | |
844 (setq form (list '- (if (nthcdr 3 form) | |
845 (byte-compile-butlast form) | |
846 (nth 1 form))))))) | |
847 (byte-optimize-predicate form)) | |
863 | 848 |
864 (defun byte-optimize-logmumble (form) | 849 (defun byte-optimize-logmumble (form) |
865 (setq form (byte-optimize-delay-constants-math form 1 (car form))) | 850 (setq form (byte-optimize-delay-constants-math form 1 (car form))) |
866 (byte-optimize-predicate | 851 (byte-optimize-predicate |
867 (cond ((memq 0 form) | 852 (cond ((memq 0 form) |