Mercurial > hg > xemacs-beta
comparison lisp/byte-optimize.el @ 446:1ccc32a20af4 r21-2-38
Import from CVS: tag r21-2-38
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:37:21 +0200 |
parents | 576fb035e263 |
children | 3078fd1074e8 |
comparison
equal
deleted
inserted
replaced
445:34f3776fcf0e | 446:1ccc32a20af4 |
---|---|
1 ;;; byte-optimize.el --- the optimization passes of the emacs-lisp byte compiler. | 1 ;;; byte-optimize.el --- the optimization passes of the emacs-lisp byte compiler. |
2 | 2 |
3 ;;; Copyright (c) 1991, 1994 Free Software Foundation, Inc. | 3 ;;; Copyright (c) 1991, 1994 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Jamie Zawinski <jwz@jwz.org> | 5 ;; Authors: Jamie Zawinski <jwz@jwz.org> |
6 ;; Hallvard Furuseth <hbf@ulrik.uio.no> | 6 ;; Hallvard Furuseth <hbf@ulrik.uio.no> |
7 ;; Martin Buchholz <martin@xemacs.org> | |
7 ;; Keywords: internal | 8 ;; Keywords: internal |
8 | 9 |
9 ;; This file is part of XEmacs. | 10 ;; This file is part of XEmacs. |
10 | 11 |
11 ;; XEmacs is free software; you can redistribute it and/or modify it | 12 ;; XEmacs is free software; you can redistribute it and/or modify it |
564 (setq opt (get (car form) 'byte-optimizer))) | 565 (setq opt (get (car form) 'byte-optimizer))) |
565 (not (eq form (setq new (funcall opt form))))) | 566 (not (eq form (setq new (funcall opt form))))) |
566 (progn | 567 (progn |
567 ;; (if (equal form new) (error "bogus optimizer -- %s" opt)) | 568 ;; (if (equal form new) (error "bogus optimizer -- %s" opt)) |
568 (byte-compile-log " %s\t==>\t%s" form new) | 569 (byte-compile-log " %s\t==>\t%s" form new) |
569 (setq new (byte-optimize-form new for-effect)) | 570 (byte-optimize-form new for-effect)) |
570 new) | |
571 form))) | 571 form))) |
572 | 572 |
573 | 573 |
574 (defun byte-optimize-body (forms all-for-effect) | 574 (defun byte-optimize-body (forms all-for-effect) |
575 ;; Optimize the cdr of a progn or implicit progn; `forms' is a list of | 575 ;; Optimize the cdr of a progn or implicit progn; `forms' is a list of |
697 (setq form orig) | 697 (setq form orig) |
698 (setq form (nconc (delq nil form) | 698 (setq form (nconc (delq nil form) |
699 (list (apply fun (nreverse constants))))))))) | 699 (list (apply fun (nreverse constants))))))))) |
700 form)) | 700 form)) |
701 | 701 |
702 ;;; It is not safe to optimize calls to arithmetic ops with one arg | |
703 ;;; away entirely (actually, it would be safe if we know the sole arg | |
704 ;;; is not a marker or if it appears in other arithmetic). | |
705 | |
706 ;;; But this degree of paranoia is normally unjustified, so optimize unless | |
707 ;;; the user has done (declaim (safety 3)). Implemented in bytecomp.el. | |
708 | |
702 (defun byte-optimize-plus (form) | 709 (defun byte-optimize-plus (form) |
703 (setq form (byte-optimize-delay-constants-math form 1 '+)) | 710 (byte-optimize-predicate (byte-optimize-delay-constants-math form 1 '+))) |
704 (if (memq 0 form) (setq form (delq 0 (copy-sequence form)))) | |
705 ;;(setq form (byte-optimize-associative-two-args-math form)) | |
706 | |
707 (case (length (cdr form)) | |
708 ((0) ; (+) | |
709 (condition-case () | |
710 (eval form) | |
711 (error form))) | |
712 | |
713 ;; It is not safe to delete the function entirely | |
714 ;; (actually, it would be safe if we knew the sole arg | |
715 ;; is not a marker). | |
716 ;; ((1) | |
717 ;; (nth 1 form)) | |
718 | |
719 ((2) ; (+ x y) | |
720 (byte-optimize-predicate | |
721 (cond | |
722 ;; `add1' and `sub1' are a marginally fewer instructions | |
723 ;; than `plus' and `minus', so use them when possible. | |
724 ((eq (nth 1 form) 1) `(1+ ,(nth 2 form))) ; (+ 1 x) --> (1+ x) | |
725 ((eq (nth 2 form) 1) `(1+ ,(nth 1 form))) ; (+ x 1) --> (1+ x) | |
726 ((eq (nth 1 form) -1) `(1- ,(nth 2 form))) ; (+ -1 x) --> (1- x) | |
727 ((eq (nth 2 form) -1) `(1- ,(nth 1 form))) ; (+ x -1) --> (1- x) | |
728 (t form)))) | |
729 | |
730 (t (byte-optimize-predicate form)))) | |
731 | |
732 (defun byte-optimize-minus (form) | |
733 ;; Put constants at the end, except the last constant. | |
734 (setq form (byte-optimize-delay-constants-math form 2 '+)) | |
735 ;; Now only first and last element can be an integer. | |
736 (let ((last (last (nthcdr 3 form)))) | |
737 (cond ((eq 0 last) | |
738 ;; (- x y ... 0) --> (- x y ...) | |
739 (setq form (copy-sequence form)) | |
740 (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form)))) | |
741 ;; If form is (- CONST foo... CONST), merge first and last. | |
742 ((and (numberp (nth 1 form)) | |
743 (numberp last)) | |
744 (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form)) | |
745 (delq last (copy-sequence (nthcdr 3 form)))))))) | |
746 | |
747 (case (length (cdr form)) | |
748 ((0) ; (-) | |
749 (condition-case () | |
750 (eval form) | |
751 (error form))) | |
752 | |
753 ;; It is not safe to delete the function entirely | |
754 ;; (actually, it would be safe if we knew the sole arg | |
755 ;; is not a marker). | |
756 ;; ((1) | |
757 ;; (nth 1 form) | |
758 | |
759 ((2) ; (+ x y) | |
760 (byte-optimize-predicate | |
761 (cond | |
762 ;; `add1' and `sub1' are a marginally fewer instructions than `plus' | |
763 ;; and `minus', so use them when possible. | |
764 ((eq (nth 2 form) 1) `(1- ,(nth 1 form))) ; (- x 1) --> (1- x) | |
765 ((eq (nth 2 form) -1) `(1+ ,(nth 1 form))) ; (- x -1) --> (1+ x) | |
766 ((eq (nth 1 form) 0) `(- ,(nth 2 form))) ; (- 0 x) --> (- x) | |
767 (t form)))) | |
768 | |
769 (t (byte-optimize-predicate form)))) | |
770 | 711 |
771 (defun byte-optimize-multiply (form) | 712 (defun byte-optimize-multiply (form) |
772 (setq form (byte-optimize-delay-constants-math form 1 '*)) | 713 (setq form (byte-optimize-delay-constants-math form 1 '*)) |
773 ;; If there is a constant integer in FORM, it is now the last element. | 714 ;; If there is a constant integer in FORM, it is now the last element. |
774 (cond ((null (cdr form)) 1) | 715 |
775 ;;; It is not safe to delete the function entirely | 716 (case (car (last form)) |
776 ;;; (actually, it would be safe if we know the sole arg | 717 ;; (* x y 0) --> (progn x y 0) |
777 ;;; is not a marker or if it appears in other arithmetic). | 718 (0 (cons 'progn (cdr form))) |
778 ;;; ((null (cdr (cdr form))) (nth 1 form)) | 719 (t (byte-optimize-predicate form)))) |
779 ((let ((last (last form))) | 720 |
780 (byte-optimize-predicate | 721 (defun byte-optimize-minus (form) |
781 (cond ((eq 0 last) (cons 'progn (cdr form))) | 722 ;; Put constants at the end, except the first arg. |
782 ((eq 1 last) (delq 1 (copy-sequence form))) | 723 (setq form (byte-optimize-delay-constants-math form 2 '+)) |
783 ((eq -1 last) (list '- (delq -1 (copy-sequence form)))) | 724 ;; Now only the first and last args can be integers. |
784 ((and (eq 2 last) | 725 (let ((last (car (last (nthcdr 3 form))))) |
785 (memq t (mapcar 'symbolp (cdr form)))) | 726 (cond |
786 (prog1 (setq form (delq 2 (copy-sequence form))) | 727 ;; If form is (- CONST foo... CONST), merge first and last. |
787 (while (not (symbolp (car (setq form (cdr form)))))) | 728 ((and (numberp (nth 1 form)) (numberp last)) |
788 (setcar form (list '+ (car form) (car form))))) | 729 (decf (nth 1 form) last) |
789 (form))))))) | 730 (butlast form)) |
731 | |
732 ;; (- 0 x ...) --> (- (- x) ...) | |
733 ((and (eq 0 (nth 1 form)) (>= (length form) 3)) | |
734 `(- (- ,(nth 2 form)) ,@(nthcdr 3 form))) | |
735 | |
736 (t (byte-optimize-predicate form))))) | |
790 | 737 |
791 (defun byte-optimize-divide (form) | 738 (defun byte-optimize-divide (form) |
739 ;; Put constants at the end, except the first arg. | |
792 (setq form (byte-optimize-delay-constants-math form 2 '*)) | 740 (setq form (byte-optimize-delay-constants-math form 2 '*)) |
793 ;; If there is a constant integer in FORM, it is now the last element. | 741 ;; Now only the first and last args can be integers. |
794 (let ((last (last (cdr (cdr form))))) | 742 (let ((last (car (last (nthcdr 3 form))))) |
795 (if (numberp last) | |
796 (cond ((= (length form) 3) | |
797 (if (and (numberp (nth 1 form)) | |
798 (not (zerop last)) | |
799 (condition-case nil | |
800 (/ (nth 1 form) last) | |
801 (error nil))) | |
802 (setq form (list 'progn (/ (nth 1 form) last))))) | |
803 ((= last 1) | |
804 (setq form (butlast form))) | |
805 ((numberp (nth 1 form)) | |
806 (setq form (cons (car form) | |
807 (cons (/ (nth 1 form) last) | |
808 (butlast (cdr (cdr form))))) | |
809 last nil)))) | |
810 (cond | 743 (cond |
811 ;;; ((null (cdr (cdr form))) | 744 ;; If form is (/ CONST foo... CONST), merge first and last. |
812 ;;; (nth 1 form)) | 745 ((and (numberp (nth 1 form)) (numberp last)) |
746 (condition-case nil | |
747 (cons (nth 0 form) | |
748 (cons (/ (nth 1 form) last) | |
749 (butlast (cdr (cdr form))))) | |
750 (error form))) | |
751 | |
752 ;; (/ 0 x y) --> (progn x y 0) | |
813 ((eq (nth 1 form) 0) | 753 ((eq (nth 1 form) 0) |
814 (append '(progn) (cdr (cdr form)) '(0))) | 754 (append '(progn) (cdr (cdr form)) '(0))) |
815 ((eq last -1) | 755 |
816 (list '- (if (nthcdr 3 form) | 756 ;; We don't have to check for divide-by-zero because `/' does. |
817 (butlast form) | 757 (t (byte-optimize-predicate form))))) |
818 (nth 1 form)))) | |
819 (form)))) | |
820 | 758 |
821 (defun byte-optimize-logmumble (form) | 759 (defun byte-optimize-logmumble (form) |
822 (setq form (byte-optimize-delay-constants-math form 1 (car form))) | 760 (setq form (byte-optimize-delay-constants-math form 1 (car form))) |
823 (byte-optimize-predicate | 761 (byte-optimize-predicate |
824 (cond ((memq 0 form) | 762 (cond ((memq 0 form) |
846 (rest (cdr form))) | 784 (rest (cdr form))) |
847 (while (and rest ok) | 785 (while (and rest ok) |
848 (setq ok (byte-compile-constp (car rest)) | 786 (setq ok (byte-compile-constp (car rest)) |
849 rest (cdr rest))) | 787 rest (cdr rest))) |
850 (if ok | 788 (if ok |
851 (condition-case () | 789 (condition-case err |
852 (list 'quote (eval form)) | 790 (list 'quote (eval form)) |
853 (error form)) | 791 (error |
792 (byte-compile-warn "evaluating %s: %s" form err) | |
793 form)) | |
854 form))) | 794 form))) |
855 | 795 |
856 (defun byte-optimize-identity (form) | 796 (defun byte-optimize-identity (form) |
857 (if (and (cdr form) (null (cdr (cdr form)))) | 797 (if (and (cdr form) (null (cdr (cdr form)))) |
858 (nth 1 form) | 798 (nth 1 form) |
903 | 843 |
904 (put '+ 'byte-optimizer 'byte-optimize-plus) | 844 (put '+ 'byte-optimizer 'byte-optimize-plus) |
905 (put '* 'byte-optimizer 'byte-optimize-multiply) | 845 (put '* 'byte-optimizer 'byte-optimize-multiply) |
906 (put '- 'byte-optimizer 'byte-optimize-minus) | 846 (put '- 'byte-optimizer 'byte-optimize-minus) |
907 (put '/ 'byte-optimizer 'byte-optimize-divide) | 847 (put '/ 'byte-optimizer 'byte-optimize-divide) |
848 (put '% 'byte-optimizer 'byte-optimize-predicate) | |
908 (put 'max 'byte-optimizer 'byte-optimize-associative-math) | 849 (put 'max 'byte-optimizer 'byte-optimize-associative-math) |
909 (put 'min 'byte-optimizer 'byte-optimize-associative-math) | 850 (put 'min 'byte-optimizer 'byte-optimize-associative-math) |
910 | 851 |
911 (put '= 'byte-optimizer 'byte-optimize-binary-predicate) | 852 (put '= 'byte-optimizer 'byte-optimize-binary-predicate) |
912 (put 'eq 'byte-optimizer 'byte-optimize-binary-predicate) | 853 (put 'eq 'byte-optimizer 'byte-optimize-binary-predicate) |
1072 (put 'or 'byte-optimizer 'byte-optimize-or) | 1013 (put 'or 'byte-optimizer 'byte-optimize-or) |
1073 (put 'cond 'byte-optimizer 'byte-optimize-cond) | 1014 (put 'cond 'byte-optimizer 'byte-optimize-cond) |
1074 (put 'if 'byte-optimizer 'byte-optimize-if) | 1015 (put 'if 'byte-optimizer 'byte-optimize-if) |
1075 (put 'while 'byte-optimizer 'byte-optimize-while) | 1016 (put 'while 'byte-optimizer 'byte-optimize-while) |
1076 | 1017 |
1077 ;; Remove any reason for avoiding `char-before'. | 1018 ;; The supply of bytecodes is small and constrained by backward compatibility. |
1019 ;; Several functions have byte-coded versions and hence are very efficient. | |
1020 ;; Related functions which can be expressed in terms of the byte-coded | |
1021 ;; ones should be transformed into bytecoded calls for efficiency. | |
1022 ;; This is especially the case for functions with a backward- and | |
1023 ;; forward- version, but with a bytecode only for the forward one. | |
1024 | |
1025 ;; Some programmers have hand-optimized calls like (backward-char) | |
1026 ;; into the call (forward-char -1). | |
1027 ;; But it's so much nicer for the byte-compiler to do this automatically! | |
1028 | |
1029 ;; (char-before) ==> (char-after (1- (point))) | |
1030 (put 'char-before 'byte-optimizer 'byte-optimize-char-before) | |
1078 (defun byte-optimize-char-before (form) | 1031 (defun byte-optimize-char-before (form) |
1079 `(char-after (1- ,(or (nth 1 form) '(point))) ,@(cdr (cdr form)))) | 1032 `(char-after |
1080 | 1033 ,(cond |
1081 (put 'char-before 'byte-optimizer 'byte-optimize-char-before) | 1034 ((null (nth 1 form)) |
1035 '(1- (point))) | |
1036 ((equal '(point) (nth 1 form)) | |
1037 '(1- (point))) | |
1038 (t `(1- (or ,(nth 1 form) (point))))) | |
1039 ,@(cdr (cdr form)))) | |
1040 | |
1041 ;; (backward-char n) ==> (forward-char (- n)) | |
1042 (put 'backward-char 'byte-optimizer 'byte-optimize-backward-char) | |
1043 (defun byte-optimize-backward-char (form) | |
1044 `(forward-char | |
1045 ,(typecase (nth 1 form) | |
1046 (null -1) | |
1047 (integer (- (nth 1 form))) | |
1048 (t `(- (or ,(nth 1 form) 1)))) | |
1049 ,@(cdr (cdr form)))) | |
1050 | |
1051 ;; (backward-word n) ==> (forward-word (- n)) | |
1052 (put 'backward-word 'byte-optimizer 'byte-optimize-backward-word) | |
1053 (defun byte-optimize-backward-word (form) | |
1054 `(forward-word | |
1055 ,(typecase (nth 1 form) | |
1056 (null -1) | |
1057 (integer (- (nth 1 form))) | |
1058 (t `(- (or ,(nth 1 form) 1)))) | |
1059 ,@(cdr (cdr form)))) | |
1060 | |
1061 ;; The following would be a valid optimization of the above kind, but | |
1062 ;; the gain in performance is very small, since the saved funcall is | |
1063 ;; counterbalanced by the necessity of adding a bytecode for (point). | |
1064 ;; | |
1065 ;; Also, users are more likely to have modified the behavior of | |
1066 ;; delete-char via advice or some similar mechanism. This is much | |
1067 ;; less of a problem for the previous functions because it wouldn't | |
1068 ;; make sense to modify the behaviour of `backward-char' without also | |
1069 ;; modifying `forward-char', for example. | |
1070 | |
1071 ;; (delete-char n) ==> (delete-region (point) (+ (point) n)) | |
1072 ;; (put 'delete-char 'byte-optimizer 'byte-optimize-delete-char) | |
1073 ;; (defun byte-optimize-delete-char (form) | |
1074 ;; (case (length (cdr form)) | |
1075 ;; (0 `(delete-region (point) (1+ (point)))) | |
1076 ;; (1 `(delete-region (point) (+ (point) ,(nth 1 form)))) | |
1077 ;; (t form))) | |
1082 | 1078 |
1083 ;; byte-compile-negation-optimizer lives in bytecomp.el | 1079 ;; byte-compile-negation-optimizer lives in bytecomp.el |
1084 ;(put '/= 'byte-optimizer 'byte-compile-negation-optimizer) | 1080 ;(put '/= 'byte-optimizer 'byte-compile-negation-optimizer) |
1085 (put 'atom 'byte-optimizer 'byte-compile-negation-optimizer) | 1081 (put 'atom 'byte-optimizer 'byte-compile-negation-optimizer) |
1086 (put 'nlistp 'byte-optimizer 'byte-compile-negation-optimizer) | 1082 (put 'nlistp 'byte-optimizer 'byte-compile-negation-optimizer) |
1087 | |
1088 | 1083 |
1089 (defun byte-optimize-funcall (form) | 1084 (defun byte-optimize-funcall (form) |
1090 ;; (funcall '(lambda ...) ...) ==> ((lambda ...) ...) | 1085 ;; (funcall '(lambda ...) ...) ==> ((lambda ...) ...) |
1091 ;; (funcall 'foo ...) ==> (foo ...) | 1086 ;; (funcall 'foo ...) ==> (foo ...) |
1092 (let ((fn (nth 1 form))) | 1087 (let ((fn (nth 1 form))) |
1253 (put fn 'side-effect-free 'error-free))) | 1248 (put fn 'side-effect-free 'error-free))) |
1254 | 1249 |
1255 | 1250 |
1256 (defun byte-compile-splice-in-already-compiled-code (form) | 1251 (defun byte-compile-splice-in-already-compiled-code (form) |
1257 ;; form is (byte-code "..." [...] n) | 1252 ;; form is (byte-code "..." [...] n) |
1258 (if (not (memq byte-optimize '(t lap))) | 1253 (if (not (memq byte-optimize '(t byte))) |
1259 (byte-compile-normal-call form) | 1254 (byte-compile-normal-call form) |
1260 (byte-inline-lapcode | 1255 (byte-inline-lapcode |
1261 (byte-decompile-bytecode-1 (nth 1 form) (nth 2 form) t)) | 1256 (byte-decompile-bytecode-1 (nth 1 form) (nth 2 form) t)) |
1262 (setq byte-compile-maxdepth (max (+ byte-compile-depth (nth 3 form)) | 1257 (setq byte-compile-maxdepth (max (+ byte-compile-depth (nth 3 form)) |
1263 byte-compile-maxdepth)) | 1258 byte-compile-maxdepth)) |