1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 14:30:50 -08:00

Strength-reduce apply with (list ...) as tail argument

* lisp/emacs-lisp/byte-opt.el (byte-optimize-apply):
Transform (apply F ... (list X ...)) -> (funcall F ... X ...)
This commit is contained in:
Mattias Engdegård 2022-08-12 15:04:51 +02:00
parent e99d7c4d62
commit 1d8712bcc9

View file

@ -1207,25 +1207,26 @@ See Info node `(elisp) Integer Basics'."
form))) form)))
(defun byte-optimize-apply (form) (defun byte-optimize-apply (form)
;; If the last arg is a literal constant, turn this into a funcall. (let ((len (length form)))
;; The funcall optimizer can then transform (funcall 'foo ...) -> (foo ...). (if (>= len 2)
(if (= (length form) 2)
;; single-argument `apply' is not worth optimizing (bug#40968)
form
(let ((fn (nth 1 form)) (let ((fn (nth 1 form))
(last (nth (1- (length form)) form))) ; I think this really is fastest (last (nth (1- len) form)))
(or (if (or (null last) (cond
;; (apply F ... '(X Y ...)) -> (funcall F ... 'X 'Y ...)
((or (null last)
(eq (car-safe last) 'quote)) (eq (car-safe last) 'quote))
(if (listp (nth 1 last)) (let ((last-value (nth 1 last)))
(let ((butlast (nreverse (cdr (reverse (cdr (cdr form))))))) (if (listp last-value)
(nconc (list 'funcall fn) butlast `(funcall ,fn ,@(butlast (cddr form))
(mapcar (lambda (x) (list 'quote x)) (nth 1 last)))) ,@(mapcar (lambda (x) (list 'quote x)) last-value))
(byte-compile-warn-x (byte-compile-warn-x
last last "last arg to apply can't be a literal atom: `%s'" last)
"last arg to apply can't be a literal atom: `%s'" nil)))
last) ;; (apply F ... (list X Y ...)) -> (funcall F ... X Y ...)
nil)) ((eq (car-safe last) 'list)
form)))) `(funcall ,fn ,@(butlast (cddr form)) ,@(cdr last)))
(t form)))
form)))
(put 'funcall 'byte-optimizer #'byte-optimize-funcall) (put 'funcall 'byte-optimizer #'byte-optimize-funcall)
(put 'apply 'byte-optimizer #'byte-optimize-apply) (put 'apply 'byte-optimizer #'byte-optimize-apply)