comparison lisp/emacs-lisp/byte-opt.el @ 86056:e0931ee6cc83

* emacs-lisp/byte-opt.el (byte-compile-trueconstp): Handle more constant forms. (byte-compile-nilconstp): New function. (byte-optimize-cond): Kill subsequent branches when a branch is know to be taken or not taken. (byte-optimize-if): Use byte-compile-nilconstp instead of hand coding.
author Dan Nicolaescu <dann@ics.uci.edu>
date Tue, 13 Nov 2007 16:10:14 +0000
parents e33327200372
children bd6f75b64f62
comparison
equal deleted inserted replaced
86055:f064a093bf93 86056:e0931ee6cc83
183 183
184 184
185 ;;; Code: 185 ;;; Code:
186 186
187 (require 'bytecomp) 187 (require 'bytecomp)
188 (eval-when-compile (require 'cl))
188 189
189 (defun byte-compile-log-lap-1 (format &rest args) 190 (defun byte-compile-log-lap-1 (format &rest args)
190 (if (aref byte-code-vector 0) 191 (if (aref byte-code-vector 0)
191 (error "The old version of the disassembler is loaded. Reload new-bytecomp as well")) 192 (error "The old version of the disassembler is loaded. Reload new-bytecomp as well"))
192 (byte-compile-log-1 193 (byte-compile-log-1
624 ;; you must return something not EQ to it if you make an optimization. 625 ;; you must return something not EQ to it if you make an optimization.
625 ;; 626 ;;
626 ;; It is now safe to optimize code such that it introduces new bindings. 627 ;; It is now safe to optimize code such that it introduces new bindings.
627 628
628 ;; I'd like this to be a defsubst, but let's not be self-referential... 629 ;; I'd like this to be a defsubst, but let's not be self-referential...
629 (defmacro byte-compile-trueconstp (form) 630 (defsubst byte-compile-trueconstp (form)
630 ;; Returns non-nil if FORM is a non-nil constant. 631 "Return non-nil if FORM always evaluates to a non-nil value."
631 `(cond ((consp ,form) (eq (car ,form) 'quote)) 632 (cond ((consp form)
632 ((not (symbolp ,form))) 633 (case (car form)
633 ((eq ,form t)) 634 (quote (cadr form))
634 ((keywordp ,form)))) 635 (progn (byte-compile-trueconstp (car (last (cdr form)))))))
636 ((not (symbolp form)))
637 ((eq form t))
638 ((keywordp form))))
639
640 (defsubst byte-compile-nilconstp (form)
641 "Return non-nil if FORM always evaluates to a nil value."
642 (cond ((consp form)
643 (case (car form)
644 (quote (null (cadr form)))
645 (progn (byte-compile-nilconstp (car (last (cdr form)))))))
646 ((not (symbolp form)) nil)
647 ((null form))))
635 648
636 ;; If the function is being called with constant numeric args, 649 ;; If the function is being called with constant numeric args,
637 ;; evaluate as much as possible at compile-time. This optimizer 650 ;; evaluate as much as possible at compile-time. This optimizer
638 ;; assumes that the function is associative, like + or *. 651 ;; assumes that the function is associative, like + or *.
639 (defun byte-optimize-associative-math (form) 652 (defun byte-optimize-associative-math (form)
988 (if (memq nil (cdr form)) 1001 (if (memq nil (cdr form))
989 (setq form (delq nil (copy-sequence form)))) 1002 (setq form (delq nil (copy-sequence form))))
990 (setq rest form) 1003 (setq rest form)
991 (while (setq rest (cdr rest)) 1004 (while (setq rest (cdr rest))
992 (cond ((byte-compile-trueconstp (car-safe (car rest))) 1005 (cond ((byte-compile-trueconstp (car-safe (car rest)))
993 (cond ((eq rest (cdr form)) 1006 ;; This branch will always be taken: kill the subsequent ones.
994 (setq form 1007 (cond ((eq rest (cdr form)) ;First branch of `cond'.
995 (if (cdr (car rest)) 1008 (setq form `(progn ,@(car rest))))
996 (if (cdr (cdr (car rest)))
997 (cons 'progn (cdr (car rest)))
998 (nth 1 (car rest)))
999 (car (car rest)))))
1000 ((cdr rest) 1009 ((cdr rest)
1001 (setq form (copy-sequence form)) 1010 (setq form (copy-sequence form))
1002 (setcdr (memq (car rest) form) nil))) 1011 (setcdr (memq (car rest) form) nil)))
1003 (setq rest nil))))) 1012 (setq rest nil))
1013 ((and (consp (car rest))
1014 (byte-compile-nilconstp (caar rest)))
1015 ;; This branch will never be taken: kill its body.
1016 (setcdr (car rest) nil)))))
1004 ;; 1017 ;;
1005 ;; Turn (cond (( <x> )) ... ) into (or <x> (cond ... )) 1018 ;; Turn (cond (( <x> )) ... ) into (or <x> (cond ... ))
1006 (if (eq 'cond (car-safe form)) 1019 (if (eq 'cond (car-safe form))
1007 (let ((clauses (cdr form))) 1020 (let ((clauses (cdr form)))
1008 (if (and (consp (car clauses)) 1021 (if (and (consp (car clauses))
1029 (nconc (butlast clause) 1042 (nconc (butlast clause)
1030 (list 1043 (list
1031 (byte-optimize-if 1044 (byte-optimize-if
1032 `(if ,(car (last clause)) ,@(nthcdr 2 form))))))) 1045 `(if ,(car (last clause)) ,@(nthcdr 2 form)))))))
1033 ((byte-compile-trueconstp clause) 1046 ((byte-compile-trueconstp clause)
1034 (nth 2 form)) 1047 `(progn ,clause ,(nth 2 form)))
1035 ((null clause) 1048 ((byte-compile-nilconstp clause)
1036 (if (nthcdr 4 form) 1049 `(progn ,clause ,@(nthcdr 3 form)))
1037 (cons 'progn (nthcdr 3 form))
1038 (nth 3 form)))
1039 ((nth 2 form) 1050 ((nth 2 form)
1040 (if (equal '(nil) (nthcdr 3 form)) 1051 (if (equal '(nil) (nthcdr 3 form))
1041 (list 'if clause (nth 2 form)) 1052 (list 'if clause (nth 2 form))
1042 form)) 1053 form))
1043 ((or (nth 3 form) (nthcdr 4 form)) 1054 ((or (nth 3 form) (nthcdr 4 form))