aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2022-08-12 20:12:25 +0200
committerMattias EngdegÄrd2022-08-16 20:44:50 +0200
commite618b6faee5b81d17501fdb2e6b121062f95c021 (patch)
tree7b9c47a1a008da199e7e361287ecbb021c8c32d8
parent869db699ee276349b5de17b54daa4e75433075b9 (diff)
downloademacs-e618b6faee5b81d17501fdb2e6b121062f95c021.tar.gz
emacs-e618b6faee5b81d17501fdb2e6b121062f95c021.zip
Improved `if` and `while` optimisation
Recognise some more special cases: (if X nil t) -> (not X) (if X t) -> (not (not X)) (if X t nil) -> (not (not X)) (if VAR VAR X...) -> (or VAR (progn X...)) * lisp/emacs-lisp/byte-opt.el (byte-opt-negate): New. (byte-optimize-if): Add transformations above and refactor. (byte-optimize-while): Better static nil-detection.
-rw-r--r--lisp/emacs-lisp/byte-opt.el91
1 files changed, 53 insertions, 38 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 062f5bf0a22..579e2f61ae1 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1190,49 +1190,64 @@ See Info node `(elisp) Integer Basics'."
1190 (and clauses form))) 1190 (and clauses form)))
1191 form)) 1191 form))
1192 1192
1193(defsubst byte-opt--negate (form)
1194 "Negate FORM, avoiding double negation if already negated."
1195 (if (and (consp form) (memq (car form) '(not null)))
1196 (cadr form)
1197 `(not ,form)))
1198
1193(defun byte-optimize-if (form) 1199(defun byte-optimize-if (form)
1194 ;; (if (progn <insts> <test>) <rest>) ==> (progn <insts> (if <test> <rest>)) 1200 (let ((condition (nth 1 form))
1195 ;; (if <true-constant> <then> <else...>) ==> <then> 1201 (then (nth 2 form))
1196 ;; (if <false-constant> <then> <else...>) ==> (progn <else...>) 1202 (else (nthcdr 3 form)))
1197 ;; (if <test> nil <else...>) ==> (if (not <test>) (progn <else...>)) 1203 (cond
1198 ;; (if <test> <then> nil) ==> (if <test> <then>) 1204 ;; (if (progn ... X) ...) -> (progn ... (if X ...))
1199 (let ((clause (nth 1 form))) 1205 ((eq (car-safe condition) 'progn)
1200 (cond ((and (eq (car-safe clause) 'progn) 1206 (nconc (butlast condition)
1201 (proper-list-p clause)) 1207 (list
1202 (if (null (cddr clause)) 1208 (byte-optimize-if
1203 ;; A trivial `progn'. 1209 `(,(car form) ,(car (last condition)) ,@(nthcdr 2 form))))))
1204 (byte-optimize-if `(,(car form) ,(cadr clause) ,@(nthcdr 2 form))) 1210 ;; (if TRUE THEN ...) -> (progn TRUE THEN)
1205 (nconc (butlast clause) 1211 ((byte-compile-trueconstp condition)
1206 (list 1212 `(progn ,condition ,then))
1207 (byte-optimize-if 1213 ;; (if FALSE THEN ELSE...) -> (progn FALSE ELSE...)
1208 `(,(car form) ,(car (last clause)) ,@(nthcdr 2 form))))))) 1214 ((byte-compile-nilconstp condition)
1209 ((byte-compile-trueconstp clause) 1215 (if else
1210 `(progn ,clause ,(nth 2 form))) 1216 `(progn ,condition ,@else)
1211 ((byte-compile-nilconstp clause) 1217 condition))
1212 `(progn ,clause ,@(nthcdr 3 form))) 1218 ;; (if X nil t) -> (not X)
1213 ((nth 2 form) 1219 ((and (eq then nil) (eq else '(t)))
1214 (if (equal '(nil) (nthcdr 3 form)) 1220 `(not ,condition))
1215 (list (car form) clause (nth 2 form)) 1221 ;; (if X t [nil]) -> (not (not X))
1216 form)) 1222 ((and (eq then t) (or (null else) (eq else '(nil))))
1217 ((or (nth 3 form) (nthcdr 4 form)) 1223 `(not ,(byte-opt--negate condition)))
1218 (list (car form) 1224 ;; (if VAR VAR X...) -> (or VAR (progn X...))
1219 ;; Don't make a double negative; 1225 ((and (symbolp condition) (eq condition then))
1220 ;; instead, take away the one that is there. 1226 `(or ,then ,(if (cdr else)
1221 (if (and (consp clause) (memq (car clause) '(not null)) 1227 `(progn . ,else)
1222 (= (length clause) 2)) ; (not xxxx) or (not (xxxx)) 1228 (car else))))
1223 (nth 1 clause) 1229 ;; (if X THEN nil) -> (if X THEN)
1224 (list 'not clause)) 1230 (then
1225 (if (nthcdr 4 form) 1231 (if (equal else '(nil))
1226 (cons 'progn (nthcdr 3 form)) 1232 (list (car form) condition then)
1227 (nth 3 form)))) 1233 form))
1228 (t 1234 ;; (if X nil ELSE...) -> (if (not X) (progn ELSE...))
1229 (list 'progn clause nil))))) 1235 ((or (car else) (cdr else))
1236 (list (car form) (byte-opt--negate condition)
1237 (if (cdr else)
1238 `(progn . ,else)
1239 (car else))))
1240 ;; (if X nil nil) -> (progn X nil)
1241 (t
1242 (list 'progn condition nil)))))
1230 1243
1231(defun byte-optimize-while (form) 1244(defun byte-optimize-while (form)
1232 (when (< (length form) 2) 1245 (when (< (length form) 2)
1233 (byte-compile-warn-x form "too few arguments for `while'")) 1246 (byte-compile-warn-x form "too few arguments for `while'"))
1234 (if (nth 1 form) 1247 (let ((condition (nth 1 form)))
1235 form)) 1248 (if (byte-compile-nilconstp condition)
1249 condition
1250 form)))
1236 1251
1237(put 'and 'byte-optimizer #'byte-optimize-and) 1252(put 'and 'byte-optimizer #'byte-optimize-and)
1238(put 'or 'byte-optimizer #'byte-optimize-or) 1253(put 'or 'byte-optimizer #'byte-optimize-or)