diff options
| author | Mattias EngdegÄrd | 2023-02-12 12:33:27 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2023-02-13 16:57:49 +0100 |
| commit | 8aef401b4f66a64ddfa9390590fb2cae1f96d522 (patch) | |
| tree | fb54bed75d8cb6f6149e256350689ce94f06c8da | |
| parent | a3edacd3f547195740304139cb68aaa94d7b18ee (diff) | |
| download | emacs-8aef401b4f66a64ddfa9390590fb2cae1f96d522.tar.gz emacs-8aef401b4f66a64ddfa9390590fb2cae1f96d522.zip | |
LAP optimiser: more stack reduction hoisting
Hoisting stack reduction ops allows them to coalesce and/or cancel out
pushing ops, and for useful operations to sink and combine, such as
not + goto-if-[not-]nil.
* lisp/emacs-lisp/byte-opt.el (byte-optimize-lapcode):
Add the rule
UNARY discardN-preserve-tos --> discardN-preserve-tos UNARY
where UNARY pops and pushes one value.
Generalise the rule
const discardN-preserve-tos --> discardN const
to any 0-ary op, not just const: varref, point, etc.
| -rw-r--r-- | lisp/emacs-lisp/byte-opt.el | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 833e88887f9..1fa8e8bdf8b 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el | |||
| @@ -2042,6 +2042,22 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 2042 | (let ((side-effect-free (if byte-compile-delete-errors | 2042 | (let ((side-effect-free (if byte-compile-delete-errors |
| 2043 | byte-compile-side-effect-free-ops | 2043 | byte-compile-side-effect-free-ops |
| 2044 | byte-compile-side-effect-and-error-free-ops)) | 2044 | byte-compile-side-effect-and-error-free-ops)) |
| 2045 | ;; Ops taking and produce a single value on the stack. | ||
| 2046 | (unary-ops '( byte-not byte-length byte-list1 byte-nreverse | ||
| 2047 | byte-car byte-cdr byte-car-safe byte-cdr-safe | ||
| 2048 | byte-symbolp byte-consp byte-stringp | ||
| 2049 | byte-listp byte-integerp byte-numberp | ||
| 2050 | byte-add1 byte-sub1 byte-negate | ||
| 2051 | ;; There are more of these but the list is | ||
| 2052 | ;; getting long and the gain is typically small. | ||
| 2053 | )) | ||
| 2054 | ;; Ops producing a single result without looking at the stack. | ||
| 2055 | (producer-ops '( byte-constant byte-varref | ||
| 2056 | byte-point byte-point-max byte-point-min | ||
| 2057 | byte-following-char byte-preceding-char | ||
| 2058 | byte-current-column | ||
| 2059 | byte-eolp byte-eobp byte-bolp byte-bobp | ||
| 2060 | byte-current-buffer byte-widen)) | ||
| 2045 | (add-depth 0) | 2061 | (add-depth 0) |
| 2046 | (keep-going 'first-time) | 2062 | (keep-going 'first-time) |
| 2047 | ;; Create a cons cell as head of the list so that removing the first | 2063 | ;; Create a cons cell as head of the list so that removing the first |
| @@ -2421,12 +2437,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 2421 | ;; const, varref, point etc. | 2437 | ;; const, varref, point etc. |
| 2422 | ;; | 2438 | ;; |
| 2423 | ((and (eq (car (nth 2 rest)) 'byte-return) | 2439 | ((and (eq (car (nth 2 rest)) 'byte-return) |
| 2424 | (memq (car lap1) '( byte-constant byte-varref | 2440 | (memq (car lap1) producer-ops) |
| 2425 | byte-point byte-point-max byte-point-min | ||
| 2426 | byte-following-char byte-preceding-char | ||
| 2427 | byte-current-column | ||
| 2428 | byte-eolp byte-eobp byte-bolp byte-bobp | ||
| 2429 | byte-current-buffer byte-widen)) | ||
| 2430 | (or (memq (car lap0) '( byte-discard byte-discardN | 2441 | (or (memq (car lap0) '( byte-discard byte-discardN |
| 2431 | byte-discardN-preserve-tos | 2442 | byte-discardN-preserve-tos |
| 2432 | byte-stack-set)) | 2443 | byte-stack-set)) |
| @@ -2438,26 +2449,15 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 2438 | lap0 lap1 (nth 2 rest) lap1 (nth 2 rest))) | 2449 | lap0 lap1 (nth 2 rest) lap1 (nth 2 rest))) |
| 2439 | 2450 | ||
| 2440 | ;; | 2451 | ;; |
| 2441 | ;; discardN-preserve-tos OP return --> OP return | 2452 | ;; (discardN-preserve-tos|dup) UNARY return --> UNARY return |
| 2442 | ;; dup OP return --> OP return | 2453 | ;; where UNARY takes and produces a single value on the stack |
| 2443 | ;; where OP is 1->1 in stack use, like `not'. | ||
| 2444 | ;; | 2454 | ;; |
| 2445 | ;; FIXME: ideally we should run this backwards, so that we could do | 2455 | ;; FIXME: ideally we should run this backwards, so that we could do |
| 2446 | ;; discardN-preserve-tos OP1...OPn return -> OP1..OPn return | 2456 | ;; discardN-preserve-tos OP1...OPn return -> OP1..OPn return |
| 2447 | ;; but that would require a different approach. | 2457 | ;; but that would require a different approach. |
| 2448 | ;; | 2458 | ;; |
| 2449 | ((and (eq (car (nth 2 rest)) 'byte-return) | 2459 | ((and (eq (car (nth 2 rest)) 'byte-return) |
| 2450 | (memq (car lap1) | 2460 | (memq (car lap1) unary-ops) |
| 2451 | '( byte-not | ||
| 2452 | byte-symbolp byte-consp byte-stringp | ||
| 2453 | byte-listp byte-integerp byte-numberp | ||
| 2454 | byte-list1 | ||
| 2455 | byte-car byte-cdr byte-car-safe byte-cdr-safe | ||
| 2456 | byte-length | ||
| 2457 | byte-add1 byte-sub1 byte-negate byte-nreverse | ||
| 2458 | ;; There are more of these but the list is | ||
| 2459 | ;; getting long and the gain is small. | ||
| 2460 | )) | ||
| 2461 | (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup)) | 2461 | (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup)) |
| 2462 | (and (eq (car lap0) 'byte-stack-set) | 2462 | (and (eq (car lap0) 'byte-stack-set) |
| 2463 | (eql (cdr lap0) 1)))) | 2463 | (eql (cdr lap0) 1)))) |
| @@ -2785,14 +2785,32 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 2785 | (push newjmp (cdr rest))) | 2785 | (push newjmp (cdr rest))) |
| 2786 | t))))) | 2786 | t))))) |
| 2787 | 2787 | ||
| 2788 | ;; | ||
| 2789 | ;; UNARY discardN-preserve-tos --> discardN-preserve-tos UNARY | ||
| 2790 | ;; where UNARY takes and produces a single value on the stack | ||
| 2791 | ;; | ||
| 2792 | ((and (memq (car lap0) unary-ops) | ||
| 2793 | (or (eq (car lap1) 'byte-discardN-preserve-tos) | ||
| 2794 | (and (eq (car lap1) 'byte-stack-set) | ||
| 2795 | (eql (cdr lap1) 1))) | ||
| 2796 | ;; unless followed by return (which will eat the discard) | ||
| 2797 | (not (eq (car lap2) 'byte-return))) | ||
| 2798 | (setq keep-going t) | ||
| 2799 | (byte-compile-log-lap " %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0) | ||
| 2800 | (setcar rest lap1) | ||
| 2801 | (setcar (cdr rest) lap0)) | ||
| 2802 | |||
| 2788 | ;; | 2803 | ;; |
| 2789 | ;; const discardN-preserve-tos ==> discardN const | 2804 | ;; PRODUCER discardN-preserve-tos(X) --> discard(X) PRODUCER |
| 2790 | ;; const stack-set(1) ==> discard const | 2805 | ;; where PRODUCER pushes a result without looking at the stack: |
| 2806 | ;; const, varref, point etc. | ||
| 2791 | ;; | 2807 | ;; |
| 2792 | ((and (eq (car lap0) 'byte-constant) | 2808 | ((and (memq (car lap0) producer-ops) |
| 2793 | (or (eq (car lap1) 'byte-discardN-preserve-tos) | 2809 | (or (eq (car lap1) 'byte-discardN-preserve-tos) |
| 2794 | (and (eq (car lap1) 'byte-stack-set) | 2810 | (and (eq (car lap1) 'byte-stack-set) |
| 2795 | (eql (cdr lap1) 1)))) | 2811 | (eql (cdr lap1) 1))) |
| 2812 | ;; unless followed by return (which will eat the discard) | ||
| 2813 | (not (eq (car lap2) 'byte-return))) | ||
| 2796 | (setq keep-going t) | 2814 | (setq keep-going t) |
| 2797 | (let ((newdiscard (if (eql (cdr lap1) 1) | 2815 | (let ((newdiscard (if (eql (cdr lap1) 1) |
| 2798 | (cons 'byte-discard nil) | 2816 | (cons 'byte-discard nil) |
| @@ -2801,6 +2819,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 2801 | " %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0) | 2819 | " %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0) |
| 2802 | (setf (car rest) newdiscard) | 2820 | (setf (car rest) newdiscard) |
| 2803 | (setf (cadr rest) lap0))) | 2821 | (setf (cadr rest) lap0))) |
| 2822 | |||
| 2804 | (t | 2823 | (t |
| 2805 | ;; If no rule matched, advance and try again. | 2824 | ;; If no rule matched, advance and try again. |
| 2806 | (setq prev (cdr prev)))))))) | 2825 | (setq prev (cdr prev)))))))) |