aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2023-02-12 12:33:27 +0100
committerMattias EngdegÄrd2023-02-13 16:57:49 +0100
commit8aef401b4f66a64ddfa9390590fb2cae1f96d522 (patch)
treefb54bed75d8cb6f6149e256350689ce94f06c8da
parenta3edacd3f547195740304139cb68aaa94d7b18ee (diff)
downloademacs-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.el67
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))))))))