summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/byte-opt.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/byte-opt.el')
-rw-r--r--lisp/emacs-lisp/byte-opt.el95
1 files changed, 59 insertions, 36 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index d4c21e5ddb8..f49aff90a20 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -31,7 +31,7 @@
;; "No matter how hard you try, you can't make a racehorse out of a pig.
;; You can, however, make a faster pig."
;;
-;; Or, to put it another way, the emacs byte compiler is a VW Bug. This code
+;; Or, to put it another way, the Emacs byte compiler is a VW Bug. This code
;; makes it be a VW Bug with fuel injection and a turbocharger... You're
;; still not going to make it go faster than 70 mph, but it might be easier
;; to get it there.
@@ -185,6 +185,7 @@
;;; Code:
(require 'bytecomp)
+(eval-when-compile (require 'cl))
(defun byte-compile-log-lap-1 (format &rest args)
(if (aref byte-code-vector 0)
@@ -627,13 +628,24 @@
;;
;; It is now safe to optimize code such that it introduces new bindings.
-;; I'd like this to be a defsubst, but let's not be self-referential...
-(defmacro byte-compile-trueconstp (form)
- ;; Returns non-nil if FORM is a non-nil constant.
- `(cond ((consp ,form) (eq (car ,form) 'quote))
- ((not (symbolp ,form)))
- ((eq ,form t))
- ((keywordp ,form))))
+(defsubst byte-compile-trueconstp (form)
+ "Return non-nil if FORM always evaluates to a non-nil value."
+ (cond ((consp form)
+ (case (car form)
+ (quote (cadr form))
+ (progn (byte-compile-trueconstp (car (last (cdr form)))))))
+ ((not (symbolp form)))
+ ((eq form t))
+ ((keywordp form))))
+
+(defsubst byte-compile-nilconstp (form)
+ "Return non-nil if FORM always evaluates to a nil value."
+ (cond ((consp form)
+ (case (car form)
+ (quote (null (cadr form)))
+ (progn (byte-compile-nilconstp (car (last (cdr form)))))))
+ ((not (symbolp form)) nil)
+ ((null form))))
;; If the function is being called with constant numeric args,
;; evaluate as much as possible at compile-time. This optimizer
@@ -992,17 +1004,17 @@
(setq rest form)
(while (setq rest (cdr rest))
(cond ((byte-compile-trueconstp (car-safe (car rest)))
- (cond ((eq rest (cdr form))
- (setq form
- (if (cdr (car rest))
- (if (cdr (cdr (car rest)))
- (cons 'progn (cdr (car rest)))
- (nth 1 (car rest)))
- (car (car rest)))))
+ ;; This branch will always be taken: kill the subsequent ones.
+ (cond ((eq rest (cdr form)) ;First branch of `cond'.
+ (setq form `(progn ,@(car rest))))
((cdr rest)
(setq form (copy-sequence form))
(setcdr (memq (car rest) form) nil)))
- (setq rest nil)))))
+ (setq rest nil))
+ ((and (consp (car rest))
+ (byte-compile-nilconstp (caar rest)))
+ ;; This branch will never be taken: kill its body.
+ (setcdr (car rest) nil)))))
;;
;; Turn (cond (( <x> )) ... ) into (or <x> (cond ... ))
(if (eq 'cond (car-safe form))
@@ -1016,17 +1028,26 @@
form))
(defun byte-optimize-if (form)
+ ;; (if (progn <insts> <test>) <rest>) ==> (progn <insts> (if <test> <rest>))
;; (if <true-constant> <then> <else...>) ==> <then>
;; (if <false-constant> <then> <else...>) ==> (progn <else...>)
;; (if <test> nil <else...>) ==> (if (not <test>) (progn <else...>))
;; (if <test> <then> nil) ==> (if <test> <then>)
(let ((clause (nth 1 form)))
- (cond ((byte-compile-trueconstp clause)
- (nth 2 form))
- ((null clause)
- (if (nthcdr 4 form)
- (cons 'progn (nthcdr 3 form))
- (nth 3 form)))
+ (cond ((and (eq (car-safe clause) 'progn)
+ ;; `clause' is a proper list.
+ (null (cdr (last clause))))
+ (if (null (cddr clause))
+ ;; A trivial `progn'.
+ (byte-optimize-if `(if ,(cadr clause) ,@(nthcdr 2 form)))
+ (nconc (butlast clause)
+ (list
+ (byte-optimize-if
+ `(if ,(car (last clause)) ,@(nthcdr 2 form)))))))
+ ((byte-compile-trueconstp clause)
+ `(progn ,clause ,(nth 2 form)))
+ ((byte-compile-nilconstp clause)
+ `(progn ,clause ,@(nthcdr 3 form)))
((nth 2 form)
(if (equal '(nil) (nthcdr 3 form))
(list 'if clause (nth 2 form))
@@ -1139,9 +1160,11 @@
(defun byte-optimize-featurep (form)
;; Emacs-21's byte-code doesn't run under XEmacs or SXEmacs anyway, so we
;; can safely optimize away this test.
- (if (member (cdr-safe form) '((quote xemacs) (quote sxemacs)))
+ (if (member (cdr-safe form) '(((quote xemacs)) ((quote sxemacs))))
nil
- form))
+ (if (member (cdr-safe form) '(((quote emacs))))
+ t
+ form)))
(put 'set 'byte-optimizer 'byte-optimize-set)
(defun byte-optimize-set (form)
@@ -1328,7 +1351,7 @@
;; This list contains numbers, which are pc values,
;; before each instruction.
(defun byte-decompile-bytecode (bytes constvec)
- "Turns BYTECODE into lapcode, referring to CONSTVEC."
+ "Turn BYTECODE into lapcode, referring to CONSTVEC."
(let ((byte-compile-constants nil)
(byte-compile-variables nil)
(byte-compile-tag-number 0))
@@ -1998,17 +2021,17 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
(assq 'byte-code (symbol-function 'byte-optimize-form))
(let ((byte-optimize nil)
(byte-compile-warnings nil))
- (mapcar (lambda (x)
- (or noninteractive (message "compiling %s..." x))
- (byte-compile x)
- (or noninteractive (message "compiling %s...done" x)))
- '(byte-optimize-form
- byte-optimize-body
- byte-optimize-predicate
- byte-optimize-binary-predicate
- ;; Inserted some more than necessary, to speed it up.
- byte-optimize-form-code-walker
- byte-optimize-lapcode))))
+ (mapc (lambda (x)
+ (or noninteractive (message "compiling %s..." x))
+ (byte-compile x)
+ (or noninteractive (message "compiling %s...done" x)))
+ '(byte-optimize-form
+ byte-optimize-body
+ byte-optimize-predicate
+ byte-optimize-binary-predicate
+ ;; Inserted some more than necessary, to speed it up.
+ byte-optimize-form-code-walker
+ byte-optimize-lapcode))))
nil)
;; arch-tag: 0f14076b-737e-4bef-aae6-908826ec1ff1