emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 52a55e1 5/5: Optimise let and let* whose body is constant or the


From: Mattias Engdegård
Subject: master 52a55e1 5/5: Optimise let and let* whose body is constant or the last variable
Date: Fri, 30 Jul 2021 04:54:07 -0400 (EDT)

branch: master
commit 52a55e11deb7822c67a8d7e6f2544b8f41d25a4e
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>

    Optimise let and let* whose body is constant or the last variable
    
    Simplify  (let ((X1 E1) ... (Xn En)) Xn)
          =>  (progn E1 ... En)
    
    and       (let* ((X1 E1) ... (Xn En)) Xn)
          =>  (let* ((X1 E1) ... (Xn-1 En-1)) En)
    
    and similarly the case where the body is a constant, extending a
    previous optimisation that only applied to the constant nil.
    This reduces the number of bound variables, shortens the code, and
    enables further optimisations.
    
    * lisp/emacs-lisp/byte-opt.el (byte-optimize-letX): Rewrite using
    `pcase` and add the aforementioned transformations.
    * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--test-cases):
    Add test cases.
---
 lisp/emacs-lisp/byte-opt.el            | 37 +++++++++++++++++++++++-----------
 test/lisp/emacs-lisp/bytecomp-tests.el | 18 +++++++++++++++++
 2 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index c9dfa69..d444d70 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1250,18 +1250,31 @@ See Info node `(elisp) Integer Basics'."
 (put 'let 'byte-optimizer #'byte-optimize-letX)
 (put 'let* 'byte-optimizer #'byte-optimize-letX)
 (defun byte-optimize-letX (form)
-  (cond ((null (nth 1 form))
-        ;; No bindings
-        (cons 'progn (cdr (cdr form))))
-       ((or (nth 2 form) (nthcdr 3 form))
-        form)
-        ;; The body is nil
-       ((eq (car form) 'let)
-        (append '(progn) (mapcar 'car-safe (mapcar 'cdr-safe (nth 1 form)))
-                '(nil)))
-       (t
-        (let ((binds (reverse (nth 1 form))))
-          (list 'let* (reverse (cdr binds)) (nth 1 (car binds)) nil)))))
+  (pcase form
+    ;; No bindings.
+    (`(,_ () . ,body)
+     `(progn . ,body))
+
+    ;; Body is empty or just contains a constant.
+    (`(,head ,bindings . ,(or '() `(,(and const (pred macroexp-const-p)))))
+     (if (eq head 'let)
+         `(progn ,@(mapcar (lambda (binding)
+                             (and (consp binding) (cadr binding)))
+                           bindings)
+                 ,const)
+       `(let* ,(butlast bindings) ,(cadar (last bindings)) ,const)))
+
+    ;; Body is last variable.
+    (`(,head ,bindings ,(and var (pred symbolp) (pred (not keywordp))
+                             (pred (not booleanp))
+                             (guard (eq var (caar (last bindings))))))
+     (if (eq head 'let)
+         `(progn ,@(mapcar (lambda (binding)
+                             (and (consp binding) (cadr binding)))
+                           bindings))
+       `(let* ,(butlast bindings) ,(cadar (last bindings)))))
+
+    (_ form)))
 
 
 (put 'nth 'byte-optimizer #'byte-optimize-nth)
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index ee0f931..5aa853c 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -509,6 +509,24 @@
                               ((member x '("b" "c")) 2)
                               ((not x) 3)))
             '("a" "b" "c" "d" nil))
+
+    ;; `let' and `let*' optimisations with body being constant or variable
+    (let* (a
+           (b (progn (setq a (cons 1 a)) 2))
+           (c (1+ b))
+           (d (list a c)))
+      d)
+    (let ((a nil))
+      (let ((b (progn (setq a (cons 1 a)) 2))
+            (c (progn (setq a (cons 3 a))))
+            (d (list a)))
+        d))
+    (let* ((_a 1)
+           (_b 2))
+      'z)
+    (let ((_a 1)
+          (_b 2))
+      'z)
     )
   "List of expressions for cross-testing interpreted and compiled code.")
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]