comparison lisp/byte-optimize.el @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
471 (setq backwards (cdr backwards))) 471 (setq backwards (cdr backwards)))
472 (if (and (cdr form) (null backwards)) 472 (if (and (cdr form) (null backwards))
473 (byte-compile-log 473 (byte-compile-log
474 " all subforms of %s called for effect; deleted" form)) 474 " all subforms of %s called for effect; deleted" form))
475 (and backwards 475 (and backwards
476 ;; Now optimize the rest of the forms. We need the return
477 ;; values. We already did the car.
478 (setcdr backwards
479 (mapcar 'byte-optimize-form (cdr backwards)))
476 (cons fn (nreverse backwards)))) 480 (cons fn (nreverse backwards))))
477 (cons fn (mapcar 'byte-optimize-form (cdr form))))) 481 (cons fn (mapcar 'byte-optimize-form (cdr form)))))
478 482
479 ((eq fn 'interactive) 483 ((eq fn 'interactive)
480 (byte-compile-warn "misplaced interactive spec: %s" 484 (byte-compile-warn "misplaced interactive spec: %s"
697 701
698 (defun byte-optimize-plus (form) 702 (defun byte-optimize-plus (form)
699 (setq form (byte-optimize-delay-constants-math form 1 '+)) 703 (setq form (byte-optimize-delay-constants-math form 1 '+))
700 (if (memq 0 form) (setq form (delq 0 (copy-sequence form)))) 704 (if (memq 0 form) (setq form (delq 0 (copy-sequence form))))
701 ;;(setq form (byte-optimize-associative-two-args-math form)) 705 ;;(setq form (byte-optimize-associative-two-args-math form))
706
702 (case (length (cdr form)) 707 (case (length (cdr form))
703 ((0) 708 ((0) ; (+)
704 (condition-case () 709 (condition-case ()
705 (eval form) 710 (eval form)
706 (error form))) 711 (error form)))
707 712
708 ;; `add1' and `sub1' are a marginally fewer instructions
709 ;; than `plus' and `minus', so use them when possible.
710 ((2)
711 (cond
712 ((eq (nth 1 form) 1) `(1+ ,(nth 2 form))) ; (+ 1 x) --> (1+ x)
713 ((eq (nth 2 form) 1) `(1+ ,(nth 1 form))) ; (+ x 1) --> (1+ x)
714 ((eq (nth 1 form) -1) `(1- ,(nth 2 form))) ; (+ -1 x) --> (1- x)
715 ((eq (nth 2 form) -1) `(1- ,(nth 1 form))) ; (+ x -1) --> (1- x)
716 (t form)))
717
718 ;; It is not safe to delete the function entirely 713 ;; It is not safe to delete the function entirely
719 ;; (actually, it would be safe if we know the sole arg 714 ;; (actually, it would be safe if we knew the sole arg
720 ;; is not a marker). 715 ;; is not a marker).
721 ;; ((null (cdr (cdr form))) (nth 1 form)) 716 ;; ((1)
722 (t form))) 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))))
723 731
724 (defun byte-optimize-minus (form) 732 (defun byte-optimize-minus (form)
725 ;; Put constants at the end, except the last constant. 733 ;; Put constants at the end, except the last constant.
726 (setq form (byte-optimize-delay-constants-math form 2 '+)) 734 (setq form (byte-optimize-delay-constants-math form 2 '+))
727 ;; Now only first and last element can be a number. 735 ;; Now only first and last element can be an integer.
728 (let ((last (car (reverse (nthcdr 3 form))))) 736 (let ((last (last (nthcdr 3 form))))
729 (cond ((eq 0 last) 737 (cond ((eq 0 last)
730 ;; (- x y ... 0) --> (- x y ...) 738 ;; (- x y ... 0) --> (- x y ...)
731 (setq form (copy-sequence form)) 739 (setq form (copy-sequence form))
732 (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form)))) 740 (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form))))
733 ;; If form is (- CONST foo... CONST), merge first and last. 741 ;; If form is (- CONST foo... CONST), merge first and last.
734 ((and (numberp (nth 1 form)) 742 ((and (numberp (nth 1 form))
735 (numberp last)) 743 (numberp last))
736 (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form)) 744 (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form))
737 (delq last (copy-sequence (nthcdr 3 form)))))))) 745 (delq last (copy-sequence (nthcdr 3 form))))))))
738 (setq form 746
739 ;;; It is not safe to delete the function entirely 747 (case (length (cdr form))
740 ;;; (actually, it would be safe if we know the sole arg 748 ((0) ; (-)
741 ;;; is not a marker). 749 (condition-case ()
742 ;;; (if (eq (nth 2 form) 0) 750 (eval form)
743 ;;; (nth 1 form) ; (- x 0) --> x 751 (error form)))
744 (byte-optimize-predicate 752
745 (if (and (null (cdr (cdr (cdr form)))) 753 ;; It is not safe to delete the function entirely
746 (eq (nth 1 form) 0)) ; (- 0 x) --> (- x) 754 ;; (actually, it would be safe if we knew the sole arg
747 (cons (car form) (cdr (cdr form))) 755 ;; is not a marker).
748 form)) 756 ;; ((1)
749 ;;; ) 757 ;; (nth 1 form)
750 ) 758
751 759 ((2) ; (+ x y)
752 ;; `add1' and `sub1' are a marginally fewer instructions than `plus' 760 (byte-optimize-predicate
753 ;; and `minus', so use them when possible. 761 (cond
754 (cond ((and (null (nthcdr 3 form)) 762 ;; `add1' and `sub1' are a marginally fewer instructions than `plus'
755 (eq (nth 2 form) 1)) 763 ;; and `minus', so use them when possible.
756 (list '1- (nth 1 form))) ; (- x 1) --> (1- x) 764 ((eq (nth 2 form) 1) `(1- ,(nth 1 form))) ; (- x 1) --> (1- x)
757 ((and (null (nthcdr 3 form)) 765 ((eq (nth 2 form) -1) `(1+ ,(nth 1 form))) ; (- x -1) --> (1+ x)
758 (eq (nth 2 form) -1)) 766 ((eq (nth 1 form) 0) `(- ,(nth 2 form))) ; (- 0 x) --> (- x)
759 (list '1+ (nth 1 form))) ; (- x -1) --> (1+ x) 767 (t form))))
760 (t 768
761 form)) 769 (t (byte-optimize-predicate form))))
762 )
763 770
764 (defun byte-optimize-multiply (form) 771 (defun byte-optimize-multiply (form)
765 (setq form (byte-optimize-delay-constants-math form 1 '*)) 772 (setq form (byte-optimize-delay-constants-math form 1 '*))
766 ;; If there is a constant in FORM, it is now the last element. 773 ;; If there is a constant integer in FORM, it is now the last element.
767 (cond ((null (cdr form)) 1) 774 (cond ((null (cdr form)) 1)
768 ;;; It is not safe to delete the function entirely 775 ;;; It is not safe to delete the function entirely
769 ;;; (actually, it would be safe if we know the sole arg 776 ;;; (actually, it would be safe if we know the sole arg
770 ;;; is not a marker or if it appears in other arithmetic). 777 ;;; is not a marker or if it appears in other arithmetic).
771 ;;; ((null (cdr (cdr form))) (nth 1 form)) 778 ;;; ((null (cdr (cdr form))) (nth 1 form))
772 ((let ((last (car (reverse form)))) 779 ((let ((last (last form)))
773 (cond ((eq 0 last) (cons 'progn (cdr form))) 780 (byte-optimize-predicate
774 ((eq 1 last) (delq 1 (copy-sequence form))) 781 (cond ((eq 0 last) (cons 'progn (cdr form)))
775 ((eq -1 last) (list '- (delq -1 (copy-sequence form)))) 782 ((eq 1 last) (delq 1 (copy-sequence form)))
776 ((and (eq 2 last) 783 ((eq -1 last) (list '- (delq -1 (copy-sequence form))))
777 (memq t (mapcar 'symbolp (cdr form)))) 784 ((and (eq 2 last)
778 (prog1 (setq form (delq 2 (copy-sequence form))) 785 (memq t (mapcar 'symbolp (cdr form))))
779 (while (not (symbolp (car (setq form (cdr form)))))) 786 (prog1 (setq form (delq 2 (copy-sequence form)))
780 (setcar form (list '+ (car form) (car form))))) 787 (while (not (symbolp (car (setq form (cdr form))))))
781 (form)))))) 788 (setcar form (list '+ (car form) (car form)))))
789 (form)))))))
782 790
783 (defun byte-optimize-divide (form) 791 (defun byte-optimize-divide (form)
784 (setq form (byte-optimize-delay-constants-math form 2 '*)) 792 (setq form (byte-optimize-delay-constants-math form 2 '*))
785 (let ((last (car (reverse (cdr (cdr form)))))) 793 ;; If there is a constant integer in FORM, it is now the last element.
794 (let ((last (last (cdr (cdr form)))))
786 (if (numberp last) 795 (if (numberp last)
787 (cond ((= (length form) 3) 796 (cond ((= (length form) 3)
788 (if (and (numberp (nth 1 form)) 797 (if (and (numberp (nth 1 form))
789 (not (zerop last)) 798 (not (zerop last))
790 (condition-case nil 799 (condition-case nil
799 (butlast (cdr (cdr form))))) 808 (butlast (cdr (cdr form)))))
800 last nil)))) 809 last nil))))
801 (cond 810 (cond
802 ;;; ((null (cdr (cdr form))) 811 ;;; ((null (cdr (cdr form)))
803 ;;; (nth 1 form)) 812 ;;; (nth 1 form))
804 ((eq (nth 1 form) 0) 813 ((eq (nth 1 form) 0)
805 (append '(progn) (cdr (cdr form)) '(0))) 814 (append '(progn) (cdr (cdr form)) '(0)))
806 ((eq last -1) 815 ((eq last -1)
807 (list '- (if (nthcdr 3 form) 816 (list '- (if (nthcdr 3 form)
808 (butlast form) 817 (butlast form)
809 (nth 1 form)))) 818 (nth 1 form))))
810 (form)))) 819 (form))))
811 820
812 (defun byte-optimize-logmumble (form) 821 (defun byte-optimize-logmumble (form)
813 (setq form (byte-optimize-delay-constants-math form 1 (car form))) 822 (setq form (byte-optimize-delay-constants-math form 1 (car form)))
814 (byte-optimize-predicate 823 (byte-optimize-predicate
815 (cond ((memq 0 form) 824 (cond ((memq 0 form)
1217 (defun disassemble-offset () 1226 (defun disassemble-offset ()
1218 "Don't call this!" 1227 "Don't call this!"
1219 ;; fetch and return the offset for the current opcode. 1228 ;; fetch and return the offset for the current opcode.
1220 ;; return NIL if this opcode has no offset 1229 ;; return NIL if this opcode has no offset
1221 ;; OP, PTR and BYTES are used and set dynamically 1230 ;; OP, PTR and BYTES are used and set dynamically
1222 (defvar op) 1231 (declare (special op ptr bytes))
1223 (defvar ptr)
1224 (defvar bytes)
1225 (cond ((< op byte-nth) 1232 (cond ((< op byte-nth)
1226 (let ((tem (logand op 7))) 1233 (let ((tem (logand op 7)))
1227 (setq op (logand op 248)) 1234 (setq op (logand op 248))
1228 (cond ((eq tem 6) 1235 (cond ((eq tem 6)
1229 (setq ptr (1+ ptr)) ;offset in next byte 1236 (setq ptr (1+ ptr)) ;offset in next byte
1453 ;If this does not enumerate all DEFVAR_BOOL variables, the byte-optimizer 1460 ;If this does not enumerate all DEFVAR_BOOL variables, the byte-optimizer
1454 ;may generate incorrect code.") 1461 ;may generate incorrect code.")
1455 1462
1456 (defun byte-optimize-lapcode (lap &optional for-effect) 1463 (defun byte-optimize-lapcode (lap &optional for-effect)
1457 "Simple peephole optimizer. LAP is both modified and returned." 1464 "Simple peephole optimizer. LAP is both modified and returned."
1458 (let (lap0 ;; off0 unused 1465 (let (lap0
1459 lap1 ;; off1 1466 lap1
1460 lap2 ;; off2 1467 lap2
1468 variable-frequency
1461 (keep-going 'first-time) 1469 (keep-going 'first-time)
1462 (add-depth 0) 1470 (add-depth 0)
1463 rest tmp tmp2 tmp3 1471 rest tmp tmp2 tmp3
1464 (side-effect-free (if byte-compile-delete-errors 1472 (side-effect-free (if byte-compile-delete-errors
1465 byte-compile-side-effect-free-ops 1473 byte-compile-side-effect-free-ops
1901 ) 1909 )
1902 ;; Cleanup stage: 1910 ;; Cleanup stage:
1903 ;; Rebuild byte-compile-constants / byte-compile-variables. 1911 ;; Rebuild byte-compile-constants / byte-compile-variables.
1904 ;; Simple optimizations that would inhibit other optimizations if they 1912 ;; Simple optimizations that would inhibit other optimizations if they
1905 ;; were done in the optimizing loop, and optimizations which there is no 1913 ;; were done in the optimizing loop, and optimizations which there is no
1906 ;; need to do more than once. 1914 ;; need to do more than once.
1907 (setq byte-compile-constants nil 1915 (setq byte-compile-constants nil
1908 byte-compile-variables nil) 1916 byte-compile-variables nil
1917 variable-frequency (make-hash-table :test 'eq))
1909 (setq rest lap) 1918 (setq rest lap)
1910 (while rest 1919 (while rest
1911 (setq lap0 (car rest) 1920 (setq lap0 (car rest)
1912 lap1 (nth 1 rest)) 1921 lap1 (nth 1 rest))
1913 (if (memq (car lap0) byte-constref-ops) 1922 (case (car lap0)
1914 (if (eq (cdr lap0) 'byte-constant) 1923 ((byte-varref byte-varset byte-varbind)
1915 (or (memq (cdr lap0) byte-compile-variables) 1924 (incf (gethash (cdr lap0) variable-frequency 0))
1916 (setq byte-compile-variables (cons (cdr lap0) 1925 (unless (memq (cdr lap0) byte-compile-variables)
1917 byte-compile-variables))) 1926 (push (cdr lap0) byte-compile-variables)))
1918 (or (memq (cdr lap0) byte-compile-constants) 1927 ((byte-constant)
1919 (setq byte-compile-constants (cons (cdr lap0) 1928 (unless (memq (cdr lap0) byte-compile-constants)
1920 byte-compile-constants))))) 1929 (push (cdr lap0) byte-compile-constants))))
1921 (cond (;; 1930 (cond (;;
1922 ;; const-C varset-X const-C --> const-C dup varset-X 1931 ;; const-C varset-X const-C --> const-C dup varset-X
1923 ;; const-C varbind-X const-C --> const-C dup varbind-X 1932 ;; const-C varbind-X const-C --> const-C dup varbind-X
1924 ;; 1933 ;;
1925 (and (eq (car lap0) 'byte-constant) 1934 (and (eq (car lap0) 'byte-constant)
1926 (eq (car (nth 2 rest)) 'byte-constant) 1935 (eq (car (nth 2 rest)) 'byte-constant)
1927 (eq (cdr lap0) (car (nth 2 rest))) 1936 (eq (cdr lap0) (cdr (nth 2 rest)))
1928 (memq (car lap1) '(byte-varbind byte-varset))) 1937 (memq (car lap1) '(byte-varbind byte-varset)))
1929 (byte-compile-log-lap " %s %s %s\t-->\t%s dup %s" 1938 (byte-compile-log-lap " %s %s %s\t-->\t%s dup %s"
1930 lap0 lap1 lap0 lap0 lap1) 1939 lap0 lap1 lap0 lap0 lap1)
1931 (setcar (cdr (cdr rest)) (cons (car lap1) (cdr lap1))) 1940 (setcar (cdr (cdr rest)) (cons (car lap1) (cdr lap1)))
1932 (setcar (cdr rest) (cons 'byte-dup 0)) 1941 (setcar (cdr rest) (cons 'byte-dup 0))
1958 (setq keep-going t) 1967 (setq keep-going t)
1959 (setq lap (delq lap0 lap)) 1968 (setq lap (delq lap0 lap))
1960 (setcdr lap1 (+ (cdr lap1) (cdr lap0)))) 1969 (setcdr lap1 (+ (cdr lap1) (cdr lap0))))
1961 ) 1970 )
1962 (setq rest (cdr rest))) 1971 (setq rest (cdr rest)))
1972 ;; Since the first 6 entries of the compiled-function constants
1973 ;; vector are most efficient for varref/set/bind ops, we sort by
1974 ;; reference count. This generates maximally space efficient and
1975 ;; pretty time-efficient byte-code. See `byte-compile-constants-vector'.
1976 (setq byte-compile-variables
1977 (sort byte-compile-variables
1978 #'(lambda (v1 v2)
1979 (< (gethash v1 variable-frequency)
1980 (gethash v2 variable-frequency)))))
1981 ;; Another hack - put the most used variable in position 6, for
1982 ;; better locality of reference with adjoining constants.
1983 (let ((tail (last byte-compile-variables 6)))
1984 (setq byte-compile-variables
1985 (append (nbutlast byte-compile-variables 6)
1986 (nreverse tail))))
1963 (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))) 1987 (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth)))
1964 lap) 1988 lap)
1965 1989
1966 (provide 'byte-optimize) 1990 (provide 'byte-optimize)
1967 1991